49 #ifndef OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED 50 #define OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED 52 #include <openvdb/Types.h> 53 #include <openvdb/Grid.h> 54 #include <openvdb/math/Math.h> 55 #include <openvdb/util/NullInterrupter.h> 56 #include <tbb/parallel_sort.h> 57 #include <tbb/parallel_for.h> 58 #include <boost/scoped_array.hpp> 66 template<
typename PointAccessorType,
67 typename RandomGenerator,
68 typename InterruptType = util::NullInterrupter>
109 template<
typename PointAccessorType,
110 typename RandomGenerator,
121 RandomGenerator& randGen,
122 InterruptType* interrupt = NULL)
123 : BaseT(points, randGen, interrupt)
124 , mTargetPointCount(pointCount)
125 , mPointsPerVolume(0.0f)
129 float pointsPerVolume,
130 RandomGenerator& randGen,
131 InterruptType* interrupt = NULL)
132 : BaseT(points, randGen, interrupt)
133 , mTargetPointCount(0)
134 , mPointsPerVolume(pointsPerVolume)
140 template<
typename Gr
idT>
143 mVoxelCount = grid.activeVoxelCount();
144 if (mVoxelCount == 0)
return false;
145 const Vec3d dim = grid.voxelSize();
146 if (mPointsPerVolume>0) {
147 BaseT::start(
"Uniform scattering with fixed point density");
148 mTargetPointCount =
Index64(mPointsPerVolume*dim[0]*dim[1]*dim[2])*mVoxelCount;
149 }
else if (mTargetPointCount>0) {
150 BaseT::start(
"Uniform scattering with fixed point count");
151 mPointsPerVolume = mTargetPointCount/float(dim[0]*dim[1]*dim[2] * mVoxelCount);
156 boost::scoped_array<Index64> list(
new Index64[mTargetPointCount]);
158 for (
Index64 i=0; i<mTargetPointCount; ++i) list[i] = rand();
159 tbb::parallel_sort(list.get(), list.get() + mTargetPointCount);
162 const Vec3R offset(0.5, 0.5, 0.5);
163 typename GridT::ValueOnCIter valueIter = grid.cbeginValueOn();
164 for (
Index64 i=0, n=valueIter.getVoxelCount() ; i != mTargetPointCount; ++i) {
165 if (BaseT::interrupt())
return false;
166 const Index64 voxelId = list[i];
167 while ( n <= voxelId ) {
169 n += valueIter.getVoxelCount();
171 if (valueIter.isVoxelValue()) {
172 BaseT::addPoint(grid, valueIter.getCoord() - offset);
174 valueIter.getBoundingBox(bbox);
175 BaseT::addPoint(grid, bbox.min() - offset, bbox.extents());
185 void print(
const std::string &name, std::ostream& os = std::cout)
const 187 os <<
"Uniformely scattered " << mPointCount <<
" points into " << mVoxelCount
188 <<
" active voxels in \"" << name <<
"\" corresponding to " 189 << mPointsPerVolume <<
" points per volume." << std::endl;
197 using BaseT::mPointCount;
198 using BaseT::mVoxelCount;
200 float mPointsPerVolume;
206 template<
typename PointAccessorType,
207 typename RandomGenerator,
217 float pointsPerVoxel,
218 RandomGenerator& randGen,
219 InterruptType* interrupt = NULL)
220 : BaseT(points, randGen, interrupt)
221 , mPointsPerVoxel(pointsPerVoxel)
226 template<
typename Gr
idT>
229 typedef typename GridT::ValueOnCIter ValueIter;
230 if (mPointsPerVoxel < 1.0e-6)
return false;
231 mVoxelCount = grid.activeVoxelCount();
232 if (mVoxelCount == 0)
return false;
233 BaseT::start(
"Dense uniform scattering with fixed point count");
235 const Vec3R offset(0.5, 0.5, 0.5);
238 const double delta = mPointsPerVoxel - ppv;
241 for (ValueIter iter = grid.cbeginValueOn(); iter; ++iter) {
242 if (BaseT::interrupt())
return false;
243 if (iter.isVoxelValue()) {
244 const Vec3R dmin = iter.getCoord() - offset;
245 for (
int n = 0; n != ppv; ++n) BaseT::addPoint(grid, dmin);
246 if (fractional && BaseT::getRand() < delta) BaseT::addPoint(grid, dmin);
248 iter.getBoundingBox(bbox);
250 const Vec3R dmin = bbox.
min() - offset;
251 const double d = mPointsPerVoxel * iter.getVoxelCount();
253 for (
int n = 0; n != m; ++n) BaseT::addPoint(grid, dmin, size);
254 if (BaseT::getRand() < d - m) BaseT::addPoint(grid, dmin, size);
264 void print(
const std::string &name, std::ostream& os = std::cout)
const 266 os <<
"Dense uniformly scattered " << mPointCount <<
" points into " << mVoxelCount
267 <<
" active voxels in \"" << name <<
"\" corresponding to " 268 << mPointsPerVoxel <<
" points per voxel." << std::endl;
274 using BaseT::mPointCount;
275 using BaseT::mVoxelCount;
276 float mPointsPerVoxel;
287 template<
typename PointAccessorType,
288 typename RandomGenerator,
298 float pointsPerVolume,
299 RandomGenerator& randGen,
300 InterruptType* interrupt = NULL)
301 : BaseT(points, randGen, interrupt)
302 , mPointsPerVolume(pointsPerVolume)
308 template<
typename Gr
idT>
311 if (mPointsPerVolume <= 0.0f)
return false;
312 mVoxelCount = grid.activeVoxelCount();
313 if (mVoxelCount == 0)
return false;
314 BaseT::start(
"Non-uniform scattering with local point density");
315 const Vec3d dim = grid.voxelSize();
316 const double volumePerVoxel = dim[0]*dim[1]*dim[2],
317 pointsPerVoxel = mPointsPerVolume * volumePerVoxel;
319 const Vec3R offset(0.5, 0.5, 0.5);
320 for (
typename GridT::ValueOnCIter iter = grid.cbeginValueOn(); iter; ++iter) {
321 if (BaseT::interrupt())
return false;
322 const double d = (*iter) * pointsPerVoxel * iter.getVoxelCount();
323 const int n = int(d);
324 if (iter.isVoxelValue()) {
325 const Vec3R dmin =iter.getCoord() - offset;
326 for (
int i = 0; i < n; ++i) BaseT::addPoint(grid, dmin);
327 if (BaseT::getRand() < (d - n)) BaseT::addPoint(grid, dmin);
329 iter.getBoundingBox(bbox);
331 const Vec3R dmin = bbox.
min() - offset;
332 for (
int i = 0; i < n; ++i) BaseT::addPoint(grid, dmin, size);
333 if (BaseT::getRand() < (d - n)) BaseT::addPoint(grid, dmin, size);
342 void print(
const std::string &name, std::ostream& os = std::cout)
const 344 os <<
"Non-uniformly scattered " << mPointCount <<
" points into " << mVoxelCount
345 <<
" active voxels in \"" << name <<
"\"." << std::endl;
351 using BaseT::mPointCount;
352 using BaseT::mVoxelCount;
353 float mPointsPerVolume;
358 template<
typename PointAccessorType,
359 typename RandomGenerator,
360 typename InterruptType>
372 RandomGenerator& randGen,
373 InterruptType* interrupt = NULL)
375 , mInterrupter(interrupt)
392 if (mInterrupter) mInterrupter->start(name);
397 if (mInterrupter) mInterrupter->end();
408 template <
typename Gr
idT>
411 const Vec3R pos(dmin[0] + this->getRand(),
412 dmin[1] + this->getRand(),
413 dmin[2] + this->getRand());
414 mPoints.add(grid.indexToWorld(pos));
418 template <
typename Gr
idT>
421 const Vec3R pos(dmin[0] + size[0]*this->getRand(),
422 dmin[1] + size[1]*this->getRand(),
423 dmin[2] + size[2]*this->getRand());
424 mPoints.add(grid.indexToWorld(pos));
433 #endif // OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:52
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:47
Simple random integer generator.
Definition: Math.h:179
uint64_t Index64
Definition: Types.h:57
#define OPENVDB_VERSION_NAME
Definition: version.h:43
Vec3< double > Vec3d
Definition: Vec3.h:651
Coord extents() const
Definition: Coord.h:365
Definition: Exceptions.h:39
const Coord & min() const
Definition: Coord.h:332
int Floor(float x)
Return the floor of x.
Definition: Math.h:814
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:259
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
Definition: Math.h:336
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76