openvdb
openvdb copied to clipboard
Dense allocation for VDB that contains only one voxel point
Environment
Operating System: Ubuntu 20.04 Version / Commit SHA: I installed the library from an Ubuntu PPA (Debian v6.2.1-8ubuntu1.1 500) Other: gcc with C++14
Describe the bug
I have implemented a program that creates an OpenVDB (regular node configuration <5,4,3>) with a custom Voxel type, and resolution 7.5cm. Additionally, I implemented visualization primitives to render voxel/node centroids as points. This visualization covers:
- Internal octree nodes (accessed through Grid::Tree::NodeCIter iterator) a. Root (Color: Red) b. Internal nodes level 1 (Color: Green) c. Internal nodes level 2 (Color: Blue) d. Lead nodes level 2 (Color: White)
- Voxel-carrying nodes (accessed through Grid::ValueAllCIter iterator) a. Active voxels (Color: Yellow) a. Inactive voxels (Color: Pink-ish)
During a test, I add one point manually, at (x=1, y=1, z=1)
.
When I rendered the corresponding centroids, I noticed that while the internal nodes of VDB are quite sparse (literally only one active):
The inactive voxel-carrying nodes (internal nodes level 2 and leaf nodes) close to the leafs seem to be plenty:
Upon zooming out and increasing the visualization marker size, I could see the same pattern on internal nodes level 1 and 2:
Furthermore, I collected some metrics:
As you can see, the bounding box is minimal, only containing the point I added to the tree, and the voxel count is 1. Nonetheless, 1.6MB of memory for such a sparse tree (only one element) seems like quite a bit.
To Reproduce
Steps to reproduce the behavior:
- Build the following snippet:
// Type aliases.
using Coord = openvdb::math::Coord;
using Vec3f = openvdb::Vec3s;
using Vec4i = openvdb::Vec4i;
using DataTree = openvdb::tree::Tree4<DataContainer, 5, 4, 3>::Type;
using DataGrid = openvdb::Grid<DataTree>;
// Custom voxel struct.
struct DataContainer
{
using Vec3f = openvdb::Vec3s;
using Vec4i = openvdb::Vec4i;
Vec3f position_{0, 0, 0};
Vec3f normals_{0, 0, 0};
Vec4i color_{0, 0, 0, 0};
...
};
const float resolution{0.075};
// Init VDB.
openvdb::initialize();
if (!DataGrid::isRegistered())
{
DataGrid::registerGrid();
}
DataContainer defaultValues;
DataGrid::Ptr map = DataGrid::create(defaultValues);
map->setGridClass(openvdb::GRID_LEVEL_SET);
map->setTransform(openvdb::math::Transform::createLinearTransform(m_resolution));
// Add data to map.
auto acc = map->getUnsafeAccessor();
const Coord ptIndexCoordinates{1, 1, 1};
DataContainer data{{1, 1, 1}, {0, 0, 0}, {0, 0, 0,0}};
acc.setValue(ptIndexCoordinates, data);
acc.setActiveState(ptIndexCoordinates, true);
- Run it.
- Visualize inactive voxels and tree nodes.
Expected behavior
VDB seems to be allocating a whole sub-branch where we would store the voxel of interest. Although these nodes don't have 'data' per se, the tree topology is still present in memory, and has a noticeable footprint for a 1-point dataset.
I would expect that upon adding a point to VDB, only a subset of tree voxels are instantiated. This would keep the memory footprint of the structure minimal.
Questions
- Am I doing something wrong?
- Is there any way to configure VDB so that it allocates tree nodes more sparsely? I can see the current allocation strategies becoming a bottleneck for my application of interest.
Additional context
I am evaluating OpenVDB for 3D mapping applications. After an evaluation of multiple representations for volumetric data, I think that VDB combines the characteristics of the S.O.T.A. in this field: sparse voxel octrees and voxel hashing.
hi, can you provide more detail about the test code, I run the code you snippet, but I got some error messages. thank you!
If you don't mind, you can send a copy to my mail:[email protected]. Thank you!