AcademySoftwareFoundation / openvdb

OpenVDB - Sparse volume data structure and tools
http://www.openvdb.org/
Mozilla Public License 2.0
2.62k stars 647 forks source link

[BUG] NanoVDB NanoGrid returns incorrect voxel size when initialized from VDB with transform #1840

Open w0utert opened 3 months ago

w0utert commented 3 months ago

Environment

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

Describe the bug

When loading a level set from a .vdb that has a transform that is not a simple linear scale, then creating a NanoGrid from it, it appears the voxel size for the resulting NanoGrid is not set correctly.

In my case I'm loading a VDB that contains a unit box with voxel size 0.1 and a Transform that rotates 45 degrees around the z-axis. I created this VDB using vdb_tool:

vdb_tool -platonic faces=6 scale=1 voxel=0.1 -transform rotate='(0,0,0.78539816339744830961566084581988)' vdb=0 -write box.rotated.vdb

The x, y, x components of the voxel size returned by NanoGrid<T>::voxelSize() appear to be initialized not from the length of the transform axes, but by just taking their corresponding component from the rotated basis vectors (or something along those lines).

To Reproduce

The following small program reproduces this behavior:

#include <openvdb/openvdb.h>
#include <openvdb/io/Stream.h>
#include <nanovdb/tools/CreateNanoGrid.h>

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

  std::ifstream in("box.rotated.vdb");

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

  openvdb::FloatGrid::Ptr grid = openvdb::DynamicPtrCast<openvdb::FloatGrid>(stream.getGrids()->front());

  auto handle = nanovdb::tools::createNanoGrid<openvdb::FloatGrid, float, GpuBufferT>(*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;
}

When I build & run this program on the attached vdb file it prints:

OpenVDB voxel_size: [0.1, 0.1, 0.1]
NanoVDB voxel_size: 1.38778e-17, 0.141421, 0.1

Expected behavior

I would expect NanoGrid<T>::voxelSize() to return the same vector as FloatGrid::voxelSize() for a NanoVDB grid created from an OpenVDB grid.