Hello,
One way to do this is to create the Bool Grid as a post-process step after you obtain a level-set (openvdb::FloatGrid) from converting your mesh to an SDF. For example, you can do the following to get a Bool Grid where voxel values near the zero iso-contour are true:
openvdb::FloatGrid::Ptr sdf = ... ;
auto voxelSize = sdf->voxelSize();
// Create a boolgrid that is true near the zero iso-contour of the level-set
openvdb::BoolGrid::Ptr bGrid = openvdb::BoolGrid::create(false);
bGrid->tree().topologyUnion(sdf->tree());
openvdb::tree::NodeManager<openvdb::BoolTree> nodeManager(bGrid->tree());
TrueNearZeroKernel op(voxelSize.length(), sdf);
nodeManager.foreachTopDown(op, true /* = threaded*/, 1 /* = grainSize*/);
bGrid->setTransform(sdf->transform().copy());
// Write boolgrid to a file
openvdb::io::File file("boolgrid.vdb");
openvdb::GridPtrVec grids;
grids.push_back(bGrid);
file.write(grids);
file.close();
Here's the definition of the kernel used in the example:
struct TrueNearZeroKernel {
TrueNearZeroKernel(float epsilon, openvdb::FloatGrid::Ptr sdf) : mEpsilon(epsilon), mSdf(sdf) {}
// Root node, internal nodes, and leaf nodes
template<typename NodeT>
void operator()(NodeT& node, size_t = 1) const
{
openvdb::FloatGrid::Accessor acc = mSdf->getAccessor();
for (auto iter = node.beginValueAll(); iter; ++iter) {
auto const ijk = iter.getCoord();
if (std::abs(acc.getValue(ijk)) < mEpsilon) {
iter.setValue(true);
} else {
iter.setValue(false);
}
}
}
float mEpsilon;
openvdb::FloatGrid::Ptr mSdf;
};// TrueNearZeroKernel
Note that you need to include #include <openvdb/tree/NodeManager.h>.