openvdb
openvdb copied to clipboard
Value error when use csgBoolean
Hi, I created a simple example to try csgBoolean operation as follow:
#include <iostream>
#include <typeinfo>
#include <tuple>
#include <limits>
#include <openvdb/openvdb.h>
#include <openvdb/points/PointCount.h>
#include "openvdb/tools/GridTransformer.h"
#include "openvdb/tools/Interpolation.h"
#include "openvdb/util/Util.h"
#include <openvdb/tools/LevelSetFilter.h>
#include <openvdb/Exceptions.h>
#include <openvdb/Types.h>
#include <openvdb/tools/Filter.h>
#include <openvdb/tools/VolumeToMesh.h>
#include <openvdb/tools/LevelSetUtil.h>
using namespace std;
int main()
{
// Initialize the OpenVDB library. This must be called at least
// once per program and may safely be called multiple times.
openvdb::initialize();
// Create an empty floating-point grid with background value 0.
openvdb::FloatGrid::Ptr grid = openvdb::FloatGrid::create();
grid->setGridClass(openvdb::GRID_LEVEL_SET);
std::cout << "Testing random access:" << std::endl;
// Get an accessor for coordinate-based access to voxels.
openvdb::FloatGrid::Accessor accessor = grid->getAccessor();
// Define a coordinate with large signed indices.
openvdb::Coord xyz(30, -30, 30);
for (int z{ 0 }; z < 8; ++z) {
for (int y{ 0 }; y < 8; ++y) {
for (int x{ 0 }; x < 8; ++x) {
xyz.reset(x, y, z);
accessor.setValue(xyz, x);
}
}
}
for (int z{ 8 }; z < 16; ++z) {
for (int y{ 0 }; y < 8; ++y) {
for (int x{ 0 }; x < 8; ++x) {
xyz.reset(x, y, z);
accessor.setValue(xyz, numeric_limits<float>::infinity());
}
}
}
openvdb::FloatGrid::Ptr grid1;
openvdb::FloatGrid::Ptr grid2;
if (grid != NULL) {
grid1 = grid;
//std::cout << "not Null1" << std::endl;
}
if (grid != NULL) {
grid2 = grid;
//std::cout << "not Null2" << std::endl;
}
openvdb::tools::csgDifference(*grid1, *grid2, true);
std::cout << "Done" << std::endl;
}
but I have a problem with csgDifference function as shown below. Anyone know how to solve it?
Hi, without diving into this too much the csgDifference takes two grids and steals from the second. So as you are using the same grid for both, I imagine that is causing an issue as it is modifying what it is running over, you could deep copy the grid for grid2, or use csgDifferenceCopy(). Also CSG Difference expects two level set grids, so I wouldnt be surprised if the operation doesnt like inifinity() as that as that value isn't a valid distance value, but I'm not sure about this. What result are you expecting from this, I would assume an empty grid?
Thanks for your comment. This is just a test. I unintendedly used csgDifference. If I use csgUnion and/or deepCopy, I have the same error.
Try defining your grid as a true level-set. First, add the following line at the beginning: #include <openvdb/tools/LevelSetSphere.h>
. Then define your grid the following way:
const float r = 5.0f;
const Vec3f c(20.0f, 0.0f, 0.0f);
const float s = 0.5f, w = 2.0f;
FloatGrid::Ptr grid = tools::createLevelSetSphere<FloatGrid>(r, c, s, w);
As @richhones said, csgDifference
will steal from the second argument. So you can define the second grid as follow:
if (grid != NULL) {
grid2 = grid->deepCopy();
}
Then csgDifference
will 'work'. However, garbage in means garbage out. So stamping over level-set values with x
or infinity
will destroy the fact that they are level-sets.
Looking at this, it seems this error is probably coming from the levelset validation in validateLevelSet() as the background value is 0, which is not a valid levelset for csg operations using tools::csgUnion/Difference etc. If you get message from the error it should say 'expected grid [name] outside value > 0'. If you follow @apradhana's example to create a level set (and make sure to copy the grid/use different grids/use the const method) you may have more luck.
Closing, please re-open if this is still an issue