Matteo Ragni Matteo Ragni - 20 days ago 4
C++ Question

Transformation and CSG Operations on grid in OpenVDB

OpenVDB seems really amazing, and the addressing of the nodes is really smart. There are some operations that I don't understand, in particular CSG operations. This is a example code. It takes as input two arguments:


  • a vdb input file with only one grid, representing a level set created starting from a triangular mesh,

  • a vdb output that stores the results of the operations.



The algorithm should take the input,


  1. creates a deepCopy in gridA

  2. creates a deepCopy in gridB

  3. rotates gridB along Y axiz of M_PI/4.0f

  4. performs the csgUnion between gridA and gridB

  5. saves all grids in a vdb output file.



I'm trying to use VDB grids as data container in place of classicaloctree algorithm, for physical simulations that needs an high level of detail in collisions.

I understand the concept of transformation between world coordinates and grid coordinates, what I cannot understand is how to perform a transformation of data inside the tree, like translate or rotate the level-sets, like a rigid object. In the example, I think I'm only changing the transformation between world and lattice.

This is the result (the same for level-set and volume):gridA should be the original loaded gridInitial GridgridB is the grid rotated of 45 degrees, and in fact it isTrasformed grid, it seems that the rotation is performed...result grid with the union... but no luck...no final result?

Do you have suggestions?

Attached: one example and a link to the LINK REMOVED that I'm using (sorry, it is 133MB...)

#include <cmath>
#include "openvdb/openvdb.h"
#include "openvdb/util/Util.h"
#include "openvdb/io/Stream.h"
#include "openvdb/tools/Composite.h"

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

openvdb::io::File file(argv[1]);
file.open();

GridBase::Ptr baseGrid;
for (openvdb::io::File::NameIterator nameIter = file.beginName();
nameIter != file.endName(); ++nameIter)
{ baseGrid = file.readGrid(nameIter.gridName()); }

file.close();
FloatGrid::Ptr gridA = gridPtrCast<FloatGrid>(baseGrid);
FloatGrid::Ptr gridB = gridA->deepCopy();
FloatGrid::Ptr result = gridA ->deepCopy();

gridB->transform().postRotate(M_PI/4.0f, math::Y_AXIS);

tools::csgUnion(*result, *gridB);

openvdb::io::File file_out(argv[2]);
GridPtrVec grids;

grids.push_back(gridA);
grids.push_back(gridB);
grids.push_back(result);

file_out.write(grids);
file_out.close();

return 0;
}

Answer

The solution of my answer, thanks to VDB support in OpenVDB forum, is:

  1. Execute a simple metadata copy of the initial grid
  2. Execute the transformation (like the rotation in my code)
  3. reinterpolate data form the initial grid in the new transformed grid, using tools::resampleToMatch, choosing one of the interpolator (in my case tools::BoxSample) available.
  4. continue with csg operations

FYI, there is an extreme difference in execution time using optimization flag -O3 (400% time reduction).

#include "openvdb/io/Stream.h"
#include "openvdb/openvdb.h"
#include "openvdb/tools/Composite.h"
#include "openvdb/tools/GridTransformer.h"
#include "openvdb/tools/Interpolation.h"
#include "openvdb/util/Util.h"

#include <cmath>

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

  openvdb::io::File file(argv[1]);
  file.open();

  GridBase::Ptr baseGrid;
  for (openvdb::io::File::NameIterator nameIter = file.beginName();
       nameIter != file.endName(); ++nameIter) {
    baseGrid = file.readGrid(nameIter.gridName());
  }

  file.close();
  FloatGrid::Ptr gridA = gridPtrCast<FloatGrid>(baseGrid);
  FloatGrid::Ptr gridB = gridA->copy(CP_NEW);
  gridB->setTransform(gridA->transform().copy());
  gridB->transform().postRotate(M_PI / 4.0f, math::Y_AXIS);

  tools::resampleToMatch<tools::BoxSampler>(*gridA, *gridB);

  FloatGrid::Ptr result = gridA->deepCopy();
  FloatGrid::Ptr gridB2 = gridB->deepCopy();

  tools::csgUnion(*result, *gridB);

  openvdb::io::File file_out(argv[2]);
  GridPtrVec grids;

  grids.push_back(gridA);
  grids.push_back(gridB2);
  grids.push_back(result);

  file_out.write(grids);
  file_out.close();

  return 0;
}

Reference: OpenVDB Forum