Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] NanoVDB math::ZeroCrossing with ray producing incorrect results #1846

Open
w0utert opened this issue Jun 11, 2024 · 1 comment
Open
Labels

Comments

@w0utert
Copy link

w0utert commented Jun 11, 2024

Environment

Operating System: Ubuntu 22.04
Version / Commit SHA: OpenVDB 11.0.1
Other: gcc 10.5.0

Describe the bug

I'm trying to intersect a level-set grid with a Ray in NanoVDB, and I'm getting back strange (wrong) results that don't look like they might be from incorrect usage.

Specifically, it looks as if somewhere internally in the NanoVDB HDDA, ray coordinates are being jumbled up, producing a combination of an off-by-one error and some inversion or bit reversal or something similar.

To Reproduce

Since this is very hard to explain in words I wrote a standalone test program to debug and qualify the NanoVDB raytrace result against the OpenVDB raytrace interface.

What the following program does is create a level-set sphere with radius 10 and voxel size 1, then raytrace a horizontal scanline through the middle of the sphere, 101 samples in the x-range [-10, 10]. I do this for both NanoVDB and OpenVDB, and print the intersection to a CSV file with the following columns:

  • intersects yes/no
  • ray origin x world
  • ray origin y world
  • ray origin x index
  • ray origin y index
  • intersection x index
  • intersection y index,
  • intersection z index
  • intersection time

I'm aware the OpenVDB LevelSetIntersector returns the actual level-set surface intersection, while the NanoVDB math::ZeroCrossing with a ray returns the ray-voxel intersection and I need to do further march to the surface, but for demonstrating the bug, this example suffices.

Program source:

#define NANOVDB_USE_OPENVDB

#include <openvdb/openvdb.h>

#include <openvdb/tools/LevelSetSphere.h>
#include <openvdb/tools/RayIntersector.h>

#include <nanovdb/NanoVDB.h>
#include <nanovdb/math/Ray.h>
#include <nanovdb/math/HDDA.h>
#include <nanovdb/util/Util.h>
#include <nanovdb/tools/CreateNanoGrid.h>
#include <nanovdb/tools/CreatePrimitives.h>

#include <fmt/format-inl.h>

int main(int argc, char **argv)
{
  openvdb::initialize();

  auto grid = openvdb::tools::createLevelSetSphere<openvdb::FloatGrid>(10.0f, { 0.0f, 0.0f, 0.0f }, 1.0f);
  auto handle = nanovdb::tools::createLevelSetSphere(10.0);

  nanovdb::NanoGrid<float> *nano_grid = handle.grid<float>();

  const auto vdb_voxel_size = grid->voxelSize();
  const auto nano_voxel_size = nano_grid->voxelSize();

  std::cerr << "OpenVDB voxel size: " << vdb_voxel_size << std::endl;
  std::cerr << "NanoVDB voxel size: " << nano_voxel_size[0] << "," << nano_voxel_size[1] << "," << nano_voxel_size[2] << std::endl;

  const double voxel_size = vdb_voxel_size.x();

  const openvdb::CoordBBox grid_bbox = grid->evalActiveVoxelBoundingBox();

  const double max_world_dim = std::max(std::max(grid_bbox.dim().x(), grid_bbox.dim().y()), grid_bbox.dim().z()) * voxel_size;

  const int image_width = 101;
  const int image_height = 101;

  const float viewport_width = 20.0f; 
  const double viewport_height = ((double) image_height / image_width) * viewport_width;


  {
    std::ofstream out("trace.nano.out");

    for (int j = 0; j < image_width; j++)
    {
      int i = 50;

      const float x = ((static_cast<float>(j) / static_cast<float>(image_width - 1)) - 0.5f) * viewport_width;
      const float y = ((static_cast<float>(image_height - i - 1) / static_cast<float>(image_height - 1)) - 0.5f) * viewport_height;

      const auto accessor = nano_grid->tree().getAccessor();

      const nanovdb::math::Ray<float> ray({ x, y, 20.0f }, { 0.0f, 0.0f, -1.0f });
      nanovdb::math::Ray<float> ray_index = ray.worldToIndexF(*nano_grid);

      float t0;
      nanovdb::Coord ijk;
      float v;

      const bool crossing = nanovdb::math::ZeroCrossing(ray_index, accessor, ijk, v, t0);

       out << fmt::format("{}: {:#6.2f}\t{:#6.2f}\t{:#6.2f}\t{:#6.2f}\t{:6d}{:6d}{:6d}\t{:#6.2f}\n",(int) crossing, x, y, ray_index.eye()[0], ray_index.eye()[1], ijk[0], ijk[1], ijk[2], t0);
    }
  }

  {
    std::ofstream out("trace.openvdb.out");

    for (int j = 0; j < image_width; j++)
    {
      int i = 50;

      const float x = ((static_cast<float>(j) / static_cast<float>(image_width - 1)) - 0.5f) * viewport_width;
      const float y = ((static_cast<float>(image_height - i - 1) / static_cast<float>(image_height - 1)) - 0.5f) * viewport_height;

      openvdb::tools::LevelSetRayIntersector<openvdb::FloatGrid, openvdb::tools::LinearSearchImpl<openvdb::FloatGrid, 2, double>> intersector(*grid);

      openvdb::Vec3d xyz;
      double t0;

      openvdb::math::Ray<double> ray{ { x, y, 20}, { 0.0f, 0.0f, -1.0f } };
      const openvdb::math::Ray<double> ray_index = ray.worldToIndex(*grid);

      const bool crossing = intersector.intersectsIS(ray, xyz, t0);

      out << fmt::format("{}: {:#6.2f}\t{:#6.2f}\t{:#6.2f}\t{:#6.2f}\t{:#6.2f}{:#6.2f}{:#6.2f}\t{:#6.2f}\n",(int) crossing, x, y, ray_index.eye()[0], ray_index.eye()[1], ray_index(t0).x(), ray_index(t0).y(), ray_index(t0).z(), t0);
    }
  }

  return 0;
}

Output for OpenVDB:

1: -10.00	  0.00	-10.00	  0.00	-10.00  0.00  0.00	 20.00
1:  -9.80	  0.00	 -9.80	  0.00	 -9.80  0.00  1.98	 18.02
1:  -9.60	  0.00	 -9.60	  0.00	 -9.60  0.00  2.77	 17.23
1:  -9.40	  0.00	 -9.40	  0.00	 -9.40  0.00  3.38	 16.62
1:  -9.20	  0.00	 -9.20	  0.00	 -9.20  0.00  3.91	 16.09
1:  -9.00	  0.00	 -9.00	  0.00	 -9.00  0.00  4.34	 15.66
1:  -8.80	  0.00	 -8.80	  0.00	 -8.80  0.00  4.73	 15.27
1:  -8.60	  0.00	 -8.60	  0.00	 -8.60  0.00  5.09	 14.91
1:  -8.40	  0.00	 -8.40	  0.00	 -8.40  0.00  5.40	 14.60
1:  -8.20	  0.00	 -8.20	  0.00	 -8.20  0.00  5.71	 14.29
1:  -8.00	  0.00	 -8.00	  0.00	 -8.00  0.00  6.00	 14.00
1:  -7.80	  0.00	 -7.80	  0.00	 -7.80  0.00  6.24	 13.76
1:  -7.60	  0.00	 -7.60	  0.00	 -7.60  0.00  6.48	 13.52
1:  -7.40	  0.00	 -7.40	  0.00	 -7.40  0.00  6.71	 13.29
1:  -7.20	  0.00	 -7.20	  0.00	 -7.20  0.00  6.93	 13.07
1:  -7.00	  0.00	 -7.00	  0.00	 -7.00  0.00  7.14	 12.86
1:  -6.80	  0.00	 -6.80	  0.00	 -6.80  0.00  7.32	 12.68
1:  -6.60	  0.00	 -6.60	  0.00	 -6.60  0.00  7.50	 12.50
1:  -6.40	  0.00	 -6.40	  0.00	 -6.40  0.00  7.67	 12.33
1:  -6.20	  0.00	 -6.20	  0.00	 -6.20  0.00  7.84	 12.16
1:  -6.00	  0.00	 -6.00	  0.00	 -6.00  0.00  8.00	 12.00
1:  -5.80	  0.00	 -5.80	  0.00	 -5.80  0.00  8.14	 11.86
1:  -5.60	  0.00	 -5.60	  0.00	 -5.60  0.00  8.27	 11.73
1:  -5.40	  0.00	 -5.40	  0.00	 -5.40  0.00  8.40	 11.60
1:  -5.20	  0.00	 -5.20	  0.00	 -5.20  0.00  8.53	 11.47
1:  -5.00	  0.00	 -5.00	  0.00	 -5.00  0.00  8.66	 11.34
1:  -4.80	  0.00	 -4.80	  0.00	 -4.80  0.00  8.76	 11.24
1:  -4.60	  0.00	 -4.60	  0.00	 -4.60  0.00  8.87	 11.13
1:  -4.40	  0.00	 -4.40	  0.00	 -4.40  0.00  8.97	 11.03
1:  -4.20	  0.00	 -4.20	  0.00	 -4.20  0.00  9.07	 10.93
1:  -4.00	  0.00	 -4.00	  0.00	 -4.00  0.00  9.16	 10.84
1:  -3.80	  0.00	 -3.80	  0.00	 -3.80  0.00  9.24	 10.76
1:  -3.60	  0.00	 -3.60	  0.00	 -3.60  0.00  9.32	 10.68
1:  -3.40	  0.00	 -3.40	  0.00	 -3.40  0.00  9.39	 10.61
1:  -3.20	  0.00	 -3.20	  0.00	 -3.20  0.00  9.47	 10.53
1:  -3.00	  0.00	 -3.00	  0.00	 -3.00  0.00  9.54	 10.46
1:  -2.80	  0.00	 -2.80	  0.00	 -2.80  0.00  9.59	 10.41
1:  -2.60	  0.00	 -2.60	  0.00	 -2.60  0.00  9.64	 10.36
1:  -2.40	  0.00	 -2.40	  0.00	 -2.40  0.00  9.70	 10.30
1:  -2.20	  0.00	 -2.20	  0.00	 -2.20  0.00  9.75	 10.25
1:  -2.00	  0.00	 -2.00	  0.00	 -2.00  0.00  9.80	 10.20
1:  -1.80	  0.00	 -1.80	  0.00	 -1.80  0.00  9.83	 10.17
1:  -1.60	  0.00	 -1.60	  0.00	 -1.60  0.00  9.86	 10.14
1:  -1.40	  0.00	 -1.40	  0.00	 -1.40  0.00  9.89	 10.11
1:  -1.20	  0.00	 -1.20	  0.00	 -1.20  0.00  9.92	 10.08
1:  -1.00	  0.00	 -1.00	  0.00	 -1.00  0.00  9.95	 10.05
1:  -0.80	  0.00	 -0.80	  0.00	 -0.80  0.00  9.96	 10.04
1:  -0.60	  0.00	 -0.60	  0.00	 -0.60  0.00  9.97	 10.03
1:  -0.40	  0.00	 -0.40	  0.00	 -0.40  0.00  9.98	 10.02
1:  -0.20	  0.00	 -0.20	  0.00	 -0.20  0.00  9.99	 10.01
1:   0.00	  0.00	  0.00	  0.00	  0.00  0.00 10.00	 10.00
1:   0.20	  0.00	  0.20	  0.00	  0.20  0.00  9.99	 10.01
1:   0.40	  0.00	  0.40	  0.00	  0.40  0.00  9.98	 10.02
1:   0.60	  0.00	  0.60	  0.00	  0.60  0.00  9.97	 10.03
1:   0.80	  0.00	  0.80	  0.00	  0.80  0.00  9.96	 10.04
1:   1.00	  0.00	  1.00	  0.00	  1.00  0.00  9.95	 10.05
1:   1.20	  0.00	  1.20	  0.00	  1.20  0.00  9.92	 10.08
1:   1.40	  0.00	  1.40	  0.00	  1.40  0.00  9.89	 10.11
1:   1.60	  0.00	  1.60	  0.00	  1.60  0.00  9.86	 10.14
1:   1.80	  0.00	  1.80	  0.00	  1.80  0.00  9.83	 10.17
1:   2.00	  0.00	  2.00	  0.00	  2.00  0.00  9.80	 10.20
1:   2.20	  0.00	  2.20	  0.00	  2.20  0.00  9.75	 10.25
1:   2.40	  0.00	  2.40	  0.00	  2.40  0.00  9.70	 10.30
1:   2.60	  0.00	  2.60	  0.00	  2.60  0.00  9.64	 10.36
1:   2.80	  0.00	  2.80	  0.00	  2.80  0.00  9.59	 10.41
1:   3.00	  0.00	  3.00	  0.00	  3.00  0.00  9.54	 10.46
1:   3.20	  0.00	  3.20	  0.00	  3.20  0.00  9.47	 10.53
1:   3.40	  0.00	  3.40	  0.00	  3.40  0.00  9.39	 10.61
1:   3.60	  0.00	  3.60	  0.00	  3.60  0.00  9.32	 10.68
1:   3.80	  0.00	  3.80	  0.00	  3.80  0.00  9.24	 10.76
1:   4.00	  0.00	  4.00	  0.00	  4.00  0.00  9.16	 10.84
1:   4.20	  0.00	  4.20	  0.00	  4.20  0.00  9.07	 10.93
1:   4.40	  0.00	  4.40	  0.00	  4.40  0.00  8.97	 11.03
1:   4.60	  0.00	  4.60	  0.00	  4.60  0.00  8.87	 11.13
1:   4.80	  0.00	  4.80	  0.00	  4.80  0.00  8.76	 11.24
1:   5.00	  0.00	  5.00	  0.00	  5.00  0.00  8.66	 11.34
1:   5.20	  0.00	  5.20	  0.00	  5.20  0.00  8.53	 11.47
1:   5.40	  0.00	  5.40	  0.00	  5.40  0.00  8.40	 11.60
1:   5.60	  0.00	  5.60	  0.00	  5.60  0.00  8.27	 11.73
1:   5.80	  0.00	  5.80	  0.00	  5.80  0.00  8.14	 11.86
1:   6.00	  0.00	  6.00	  0.00	  6.00  0.00  8.00	 12.00
1:   6.20	  0.00	  6.20	  0.00	  6.20  0.00  7.84	 12.16
1:   6.40	  0.00	  6.40	  0.00	  6.40  0.00  7.67	 12.33
1:   6.60	  0.00	  6.60	  0.00	  6.60  0.00  7.50	 12.50
1:   6.80	  0.00	  6.80	  0.00	  6.80  0.00  7.32	 12.68
1:   7.00	  0.00	  7.00	  0.00	  7.00  0.00  7.14	 12.86
1:   7.20	  0.00	  7.20	  0.00	  7.20  0.00  6.93	 13.07
1:   7.40	  0.00	  7.40	  0.00	  7.40  0.00  6.71	 13.29
1:   7.60	  0.00	  7.60	  0.00	  7.60  0.00  6.48	 13.52
1:   7.80	  0.00	  7.80	  0.00	  7.80  0.00  6.24	 13.76
1:   8.00	  0.00	  8.00	  0.00	  8.00  0.00  6.00	 14.00
1:   8.20	  0.00	  8.20	  0.00	  8.20  0.00  5.71	 14.29
1:   8.40	  0.00	  8.40	  0.00	  8.40  0.00  5.40	 14.60
1:   8.60	  0.00	  8.60	  0.00	  8.60  0.00  5.09	 14.91
1:   8.80	  0.00	  8.80	  0.00	  8.80  0.00  4.73	 15.27
1:   9.00	  0.00	  9.00	  0.00	  9.00  0.00  4.34	 15.66
1:   9.20	  0.00	  9.20	  0.00	  9.20  0.00  3.91	 16.09
1:   9.40	  0.00	  9.40	  0.00	  9.40  0.00  3.38	 16.62
1:   9.60	  0.00	  9.60	  0.00	  9.60  0.00  2.77	 17.23
1:   9.80	  0.00	  9.80	  0.00	  9.80  0.00  1.98	 18.02
1:  10.00	  0.00	 10.00	  0.00	 10.00  0.00  0.00	 20.00

Output for NanoVDB:

0: -10.00	  0.00	-10.00	  0.00	   -10     0   -13	-152017536.00
0:  -9.80	  0.00	 -9.80	  0.00	   -10     0   -13	-152017536.00
0:  -9.60	  0.00	 -9.60	  0.00	   -10     0   -13	-152017536.00
0:  -9.40	  0.00	 -9.40	  0.00	   -10     0   -13	-152017536.00
0:  -9.20	  0.00	 -9.20	  0.00	   -10     0   -13	-152017536.00
1:  -9.00	  0.00	 -9.00	  0.00	    -9     0     4	 15.00
1:  -8.80	  0.00	 -8.80	  0.00	    -9     0     4	 15.00
1:  -8.60	  0.00	 -8.60	  0.00	    -9     0     4	 15.00
1:  -8.40	  0.00	 -8.40	  0.00	    -9     0     4	 15.00
1:  -8.20	  0.00	 -8.20	  0.00	    -9     0     4	 15.00
1:  -8.00	  0.00	 -8.00	  0.00	    -8     0     5	 14.00
1:  -7.80	  0.00	 -7.80	  0.00	    -8     0     5	 14.00
1:  -7.60	  0.00	 -7.60	  0.00	    -8     0     5	 14.00
1:  -7.40	  0.00	 -7.40	  0.00	    -8     0     5	 14.00
1:  -7.20	  0.00	 -7.20	  0.00	    -8     0     5	 14.00
1:  -7.00	  0.00	 -7.00	  0.00	    -7     0     7	 12.00
1:  -6.80	  0.00	 -6.80	  0.00	    -7     0     7	 12.00
1:  -6.60	  0.00	 -6.60	  0.00	    -7     0     7	 12.00
1:  -6.40	  0.00	 -6.40	  0.00	    -7     0     7	 12.00
1:  -6.20	  0.00	 -6.20	  0.00	    -7     0     7	 12.00
1:  -6.00	  0.00	 -6.00	  0.00	    -6     0     7	 12.00
1:  -5.80	  0.00	 -5.80	  0.00	    -6     0     7	 12.00
1:  -5.60	  0.00	 -5.60	  0.00	    -6     0     7	 12.00
1:  -5.40	  0.00	 -5.40	  0.00	    -6     0     7	 12.00
1:  -5.20	  0.00	 -5.20	  0.00	    -6     0     7	 12.00
1:  -5.00	  0.00	 -5.00	  0.00	    -5     0     8	 11.00
1:  -4.80	  0.00	 -4.80	  0.00	    -5     0     8	 11.00
1:  -4.60	  0.00	 -4.60	  0.00	    -5     0     8	 11.00
1:  -4.40	  0.00	 -4.40	  0.00	    -5     0     8	 11.00
1:  -4.20	  0.00	 -4.20	  0.00	    -5     0     8	 11.00
1:  -4.00	  0.00	 -4.00	  0.00	    -4     0     9	 10.00
1:  -3.80	  0.00	 -3.80	  0.00	    -4     0     9	 10.00
1:  -3.60	  0.00	 -3.60	  0.00	    -4     0     9	 10.00
1:  -3.40	  0.00	 -3.40	  0.00	    -4     0     9	 10.00
1:  -3.20	  0.00	 -3.20	  0.00	    -4     0     9	 10.00
1:  -3.00	  0.00	 -3.00	  0.00	    -3     0     9	 10.00
1:  -2.80	  0.00	 -2.80	  0.00	    -3     0     9	 10.00
1:  -2.60	  0.00	 -2.60	  0.00	    -3     0     9	 10.00
1:  -2.40	  0.00	 -2.40	  0.00	    -3     0     9	 10.00
1:  -2.20	  0.00	 -2.20	  0.00	    -3     0     9	 10.00
1:  -2.00	  0.00	 -2.00	  0.00	    -2     0     9	 10.00
1:  -1.80	  0.00	 -1.80	  0.00	    -2     0     9	 10.00
1:  -1.60	  0.00	 -1.60	  0.00	    -2     0     9	 10.00
1:  -1.40	  0.00	 -1.40	  0.00	    -2     0     9	 10.00
1:  -1.20	  0.00	 -1.20	  0.00	    -2     0     9	 10.00
1:  -1.00	  0.00	 -1.00	  0.00	    -2     0     9	 10.00
1:  -0.80	  0.00	 -0.80	  0.00	    -1     0     9	 10.00
1:  -0.60	  0.00	 -0.60	  0.00	    -1     0     9	 10.00
1:  -0.40	  0.00	 -0.40	  0.00	    -1     0     9	 10.00
1:  -0.20	  0.00	 -0.20	  0.00	    -1     0     9	 10.00
1:   0.00	  0.00	  0.00	  0.00	     0     0     9	 10.00
1:   0.20	  0.00	  0.20	  0.00	     0     0     9	 10.00
1:   0.40	  0.00	  0.40	  0.00	     0     0     9	 10.00
1:   0.60	  0.00	  0.60	  0.00	     0     0     9	 10.00
1:   0.80	  0.00	  0.80	  0.00	     0     0     9	 10.00
1:   1.00	  0.00	  1.00	  0.00	     1     0     9	 10.00
1:   1.20	  0.00	  1.20	  0.00	     1     0     9	 10.00
1:   1.40	  0.00	  1.40	  0.00	     1     0     9	 10.00
1:   1.60	  0.00	  1.60	  0.00	     1     0     9	 10.00
1:   1.80	  0.00	  1.80	  0.00	     1     0     9	 10.00
1:   2.00	  0.00	  2.00	  0.00	     2     0     9	 10.00
1:   2.20	  0.00	  2.20	  0.00	     2     0     9	 10.00
1:   2.40	  0.00	  2.40	  0.00	     2     0     9	 10.00
1:   2.60	  0.00	  2.60	  0.00	     2     0     9	 10.00
1:   2.80	  0.00	  2.80	  0.00	     2     0     9	 10.00
1:   3.00	  0.00	  3.00	  0.00	     2     0     9	 10.00
1:   3.20	  0.00	  3.20	  0.00	     3     0     9	 10.00
1:   3.40	  0.00	  3.40	  0.00	     3     0     9	 10.00
1:   3.60	  0.00	  3.60	  0.00	     3     0     9	 10.00
1:   3.80	  0.00	  3.80	  0.00	     3     0     9	 10.00
1:   4.00	  0.00	  4.00	  0.00	     3     0     9	 10.00
1:   4.20	  0.00	  4.20	  0.00	     4     0     9	 10.00
1:   4.40	  0.00	  4.40	  0.00	     4     0     9	 10.00
1:   4.60	  0.00	  4.60	  0.00	     4     0     9	 10.00
1:   4.80	  0.00	  4.80	  0.00	     4     0     9	 10.00
1:   5.00	  0.00	  5.00	  0.00	     5     0     8	 11.00
1:   5.20	  0.00	  5.20	  0.00	     5     0     8	 11.00
1:   5.40	  0.00	  5.40	  0.00	     5     0     8	 11.00
1:   5.60	  0.00	  5.60	  0.00	     5     0     8	 11.00
1:   5.80	  0.00	  5.80	  0.00	     5     0     8	 11.00
1:   6.00	  0.00	  6.00	  0.00	     6     0     7	 12.00
1:   6.20	  0.00	  6.20	  0.00	     6     0     7	 12.00
1:   6.40	  0.00	  6.40	  0.00	     6     0     7	 12.00
1:   6.60	  0.00	  6.60	  0.00	     6     0     7	 12.00
1:   6.80	  0.00	  6.80	  0.00	     6     0     7	 12.00
1:   7.00	  0.00	  7.00	  0.00	     7     0     7	 12.00
1:   7.20	  0.00	  7.20	  0.00	     7     0     7	 12.00
1:   7.40	  0.00	  7.40	  0.00	     7     0     7	 12.00
1:   7.60	  0.00	  7.60	  0.00	     7     0     7	 12.00
1:   7.80	  0.00	  7.80	  0.00	     7     0     7	 12.00
1:   8.00	  0.00	  8.00	  0.00	     7     0     7	 12.00
1:   8.20	  0.00	  8.20	  0.00	     8     0     5	 14.00
1:   8.40	  0.00	  8.40	  0.00	     8     0     5	 14.00
1:   8.60	  0.00	  8.60	  0.00	     8     0     5	 14.00
1:   8.80	  0.00	  8.80	  0.00	     8     0     5	 14.00
1:   9.00	  0.00	  9.00	  0.00	     9     0     4	 15.00
1:   9.20	  0.00	  9.20	  0.00	     9     0     4	 15.00
1:   9.40	  0.00	  9.40	  0.00	     9     0     4	 15.00
1:   9.60	  0.00	  9.60	  0.00	     9     0     4	 15.00
1:   9.80	  0.00	  9.80	  0.00	     9     0     4	 15.00
0:  10.00	  0.00	 10.00	  0.00	    10     0   -13	 15.00

Expected behavior

As is clear from the CSV output, the intersector is not finding intersections for exactly matching rays (as confirmed by the first 5 columns).

In the NanoVDB result, the first 5 rays in the world-space x-range [-10.0, -9.20] fail to find any intersection at all, and the intersection times of all other rays are also off compared to the OpenVDB result. I would expect these rays to report an intersection and return the voxel index coordinate directly behind the surface intersection, and an intersection time that gives me the time at which the ray hits the voxel that contains the iso-surface. I would then use those to find the actual iso-surface intersection (if there is one, I guess the ray can also shear past the surface at <1 voxel distance) using root finding or sphere tracing.

One interesting piece of information is that the error in the results does not seem to be just an off-by one error, if I try to ray-march using the t0 returned by the math::ZeroCrossing function, I see some strange grid-dependent behavior.

I've attached a rendering of what happens when I try to take 2 index-space voxel steps back from the ijk reported by ZeroCrossing, sample the distance value there and at ijk, and check if they have different signs. The image is color-coded like this: light gray pixels are hit and a sign change was found, dark gray pixels are hit but no sign change was found, black pixels are not hit at all.

out nano cpu

@w0utert w0utert added the bug label Jun 11, 2024
@w0utert
Copy link
Author

w0utert commented Jun 12, 2024

Some additional info/correction:
The example program above was written against @kmuseth's feature/nanovdb_v32.7 branch, and not OpenVDB 11.0.1 as I initially reported. The problem is reproducible with OpenVDB 11.0.1 as well though.

Here's a modified version of the test program that works with OpenVDB 11.0.1:

#define NANOVDB_USE_OPENVDB

#include <openvdb/openvdb.h>


#include <openvdb/io/Stream.h>

#include <openvdb/tools/LevelSetSphere.h>
#include <openvdb/tools/RayIntersector.h>

#include <nanovdb/NanoVDB.h>
#include <nanovdb/util/Ray.h>
#include <nanovdb/util/HDDA.h>
#include <nanovdb/util/CreateNanoGrid.h>

#include <fmt/format-inl.h>

int main(int argc, char **argv)
{
  openvdb::initialize();


  std::ifstream in("/home/jbijlsma/tmp/box.rotated.vdb");

  openvdb::io::Stream stream(in);

  openvdb::FloatGrid::Ptr grid = openvdb::DynamicPtrCast<openvdb::FloatGrid>(stream.getGrids()->front());
  auto handle = nanovdb::createNanoGrid<openvdb::FloatGrid, float, nanovdb::HostBuffer>(*grid);

  nanovdb::NanoGrid<float> *nano_grid = handle.grid<float>();


  const auto vdb_voxel_size = grid->voxelSize();
  const auto nano_voxel_size = nano_grid->voxelSize();

  std::cerr << "OpenVDB voxel size: " << vdb_voxel_size << std::endl;
  std::cerr << "NanoVDB voxel size: " << nano_voxel_size[0] << "," << nano_voxel_size[1] << "," << nano_voxel_size[2] << std::endl;

  const double voxel_size = vdb_voxel_size.x();

  const openvdb::CoordBBox grid_bbox = grid->evalActiveVoxelBoundingBox();

  const double max_world_dim = std::max(std::max(grid_bbox.dim().x(), grid_bbox.dim().y()), grid_bbox.dim().z()) * voxel_size;

  const int image_width = 101;
  const int image_height = 101;

  const float viewport_width = 20.0f; 
  const double viewport_height = ((double) image_height / image_width) * viewport_width;


  {
    std::ofstream out("trace.nano.out");

    for (int j = 0; j < image_width; j++)
    {
      int i = 50;

      const float x = ((static_cast<float>(j) / static_cast<float>(image_width - 1)) - 0.5f) * viewport_width;
      const float y = ((static_cast<float>(image_height - i - 1) / static_cast<float>(image_height - 1)) - 0.5f) * viewport_height;

      const auto accessor = nano_grid->tree().getAccessor();

      const nanovdb::Ray<float> ray({ x, y, 20.0f }, { 0.0f, 0.0f, -1.0f });
      nanovdb::Ray<float> ray_index = ray.worldToIndexF(*nano_grid);

      float t0;
      nanovdb::Coord ijk;
      float v;

      const bool crossing = nanovdb::ZeroCrossing(ray_index, accessor, ijk, v, t0);

       out << fmt::format("{}: {:#6.2f}\t{:#6.2f}\t{:#6.2f}\t{:#6.2f}\t{:6d}{:6d}{:6d}\t{:#6.2f}\n",(int) crossing, x, y, ray_index.eye()[0], ray_index.eye()[1], ijk[0], ijk[1], ijk[2], t0);
    }
  }

  {
    std::ofstream out("trace.openvdb.out");

    for (int j = 0; j < image_width; j++)
    {
      int i = 50;

      const float x = ((static_cast<float>(j) / static_cast<float>(image_width - 1)) - 0.5f) * viewport_width;
      const float y = ((static_cast<float>(image_height - i - 1) / static_cast<float>(image_height - 1)) - 0.5f) * viewport_height;

      openvdb::tools::LevelSetRayIntersector<openvdb::FloatGrid, openvdb::tools::LinearSearchImpl<openvdb::FloatGrid, 2, double>> intersector(*grid);

      openvdb::Vec3d xyz;
      double t0;

      openvdb::math::Ray<double> ray{ { x, y, 20}, { 0.0f, 0.0f, -1.0f } };
      const openvdb::math::Ray<double> ray_index = ray.worldToIndex(*grid);

      const bool crossing = intersector.intersectsIS(ray, xyz, t0);

      out << fmt::format("{}: {:#6.2f}\t{:#6.2f}\t{:#6.2f}\t{:#6.2f}\t{:#6.2f}{:#6.2f}{:#6.2f}\t{:#6.2f}\n",(int) crossing, x, y, ray_index.eye()[0], ray_index.eye()[1], ray_index(t0).x(), ray_index(t0).y(), ray_index(t0).z(), t0);
    }
  }

  return 0;
}

This produces the exact same output as the previous progream with the feature/nonvdb_v32.7 branch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant