49 #ifndef OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED 50 #define OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED 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,
123 InterruptType* interrupt = NULL)
124 : BaseT(points, randGen, spread, interrupt)
125 , mTargetPointCount(pointCount)
126 , mPointsPerVolume(0.0f)
130 float pointsPerVolume,
131 RandomGenerator& randGen,
133 InterruptType* interrupt = NULL)
134 : BaseT(points, randGen, spread, interrupt)
135 , mTargetPointCount(0)
136 , mPointsPerVolume(pointsPerVolume)
142 template<
typename Gr
idT>
145 mVoxelCount = grid.activeVoxelCount();
146 if (mVoxelCount == 0)
return false;
147 const Vec3d dim = grid.voxelSize();
148 if (mPointsPerVolume>0) {
149 BaseT::start(
"Uniform scattering with fixed point density");
150 mTargetPointCount =
Index64(mPointsPerVolume*dim[0]*dim[1]*dim[2])*mVoxelCount;
151 }
else if (mTargetPointCount>0) {
152 BaseT::start(
"Uniform scattering with fixed point count");
153 mPointsPerVolume = mTargetPointCount/float(dim[0]*dim[1]*dim[2] * mVoxelCount);
158 boost::scoped_array<Index64> list(
new Index64[mTargetPointCount]);
160 for (
Index64 i=0; i<mTargetPointCount; ++i) list[i] = rand();
161 tbb::parallel_sort(list.get(), list.get() + mTargetPointCount);
164 const Vec3R offset(0.5, 0.5, 0.5);
165 typename GridT::ValueOnCIter valueIter = grid.cbeginValueOn();
167 for (
Index64 i=0, n=valueIter.getVoxelCount() ; i != mTargetPointCount; ++i) {
168 if (BaseT::interrupt())
return false;
169 const Index64 voxelId = list[i];
170 while ( n <= voxelId ) {
172 n += valueIter.getVoxelCount();
174 if (valueIter.isVoxelValue()) {
175 BaseT::addPoint(grid, valueIter.getCoord() - offset);
177 valueIter.getBoundingBox(bbox);
178 BaseT::addPoint(grid, bbox.min() - offset, bbox.extents());
189 void print(
const std::string &name, std::ostream& os = std::cout)
const 191 os <<
"Uniformely scattered " << mPointCount <<
" points into " << mVoxelCount
192 <<
" active voxels in \"" << name <<
"\" corresponding to " 193 << mPointsPerVolume <<
" points per volume." << std::endl;
201 using BaseT::mPointCount;
202 using BaseT::mVoxelCount;
204 float mPointsPerVolume;
210 template<
typename PointAccessorType,
211 typename RandomGenerator,
221 float pointsPerVoxel,
222 RandomGenerator& randGen,
224 InterruptType* interrupt = NULL)
225 : BaseT(points, randGen, spread, interrupt)
226 , mPointsPerVoxel(pointsPerVoxel)
231 template<
typename Gr
idT>
234 typedef typename GridT::ValueOnCIter ValueIter;
235 if (mPointsPerVoxel < 1.0e-6)
return false;
236 mVoxelCount = grid.activeVoxelCount();
237 if (mVoxelCount == 0)
return false;
238 BaseT::start(
"Dense uniform scattering with fixed point count");
240 const Vec3R offset(0.5, 0.5, 0.5);
243 const double delta = mPointsPerVoxel - ppv;
246 for (ValueIter iter = grid.cbeginValueOn(); iter; ++iter) {
247 if (BaseT::interrupt())
return false;
248 if (iter.isVoxelValue()) {
249 const Vec3R dmin = iter.getCoord() - offset;
250 for (
int n = 0; n != ppv; ++n) BaseT::addPoint(grid, dmin);
251 if (fractional && BaseT::getRand01() < delta) BaseT::addPoint(grid, dmin);
253 iter.getBoundingBox(bbox);
254 const Coord size(bbox.extents());
255 const Vec3R dmin = bbox.min() - offset;
256 const double d = mPointsPerVoxel * iter.getVoxelCount();
258 for (
int n = 0; n != m; ++n) BaseT::addPoint(grid, dmin, size);
259 if (BaseT::getRand01() < d - m) BaseT::addPoint(grid, dmin, size);
269 void print(
const std::string &name, std::ostream& os = std::cout)
const 271 os <<
"Dense uniformly scattered " << mPointCount <<
" points into " << mVoxelCount
272 <<
" active voxels in \"" << name <<
"\" corresponding to " 273 << mPointsPerVoxel <<
" points per voxel." << std::endl;
279 using BaseT::mPointCount;
280 using BaseT::mVoxelCount;
281 float mPointsPerVoxel;
292 template<
typename PointAccessorType,
293 typename RandomGenerator,
303 float pointsPerVolume,
304 RandomGenerator& randGen,
306 InterruptType* interrupt = NULL)
307 : BaseT(points, randGen, spread, interrupt)
308 , mPointsPerVolume(pointsPerVolume)
314 template<
typename Gr
idT>
317 if (mPointsPerVolume <= 0.0f)
return false;
318 mVoxelCount = grid.activeVoxelCount();
319 if (mVoxelCount == 0)
return false;
320 BaseT::start(
"Non-uniform scattering with local point density");
321 const Vec3d dim = grid.voxelSize();
322 const double volumePerVoxel = dim[0]*dim[1]*dim[2],
323 pointsPerVoxel = mPointsPerVolume * volumePerVoxel;
325 const Vec3R offset(0.5, 0.5, 0.5);
326 for (
typename GridT::ValueOnCIter iter = grid.cbeginValueOn(); iter; ++iter) {
327 if (BaseT::interrupt())
return false;
328 const double d = (*iter) * pointsPerVoxel * iter.getVoxelCount();
329 const int n = int(d);
330 if (iter.isVoxelValue()) {
331 const Vec3R dmin =iter.getCoord() - offset;
332 for (
int i = 0; i < n; ++i) BaseT::addPoint(grid, dmin);
333 if (BaseT::getRand01() < (d - n)) BaseT::addPoint(grid, dmin);
335 iter.getBoundingBox(bbox);
336 const Coord size(bbox.extents());
337 const Vec3R dmin = bbox.min() - offset;
338 for (
int i = 0; i < n; ++i) BaseT::addPoint(grid, dmin, size);
339 if (BaseT::getRand01() < (d - n)) BaseT::addPoint(grid, dmin, size);
348 void print(
const std::string &name, std::ostream& os = std::cout)
const 350 os <<
"Non-uniformly scattered " << mPointCount <<
" points into " << mVoxelCount
351 <<
" active voxels in \"" << name <<
"\"." << std::endl;
357 using BaseT::mPointCount;
358 using BaseT::mVoxelCount;
359 float mPointsPerVolume;
364 template<
typename PointAccessorType,
365 typename RandomGenerator,
366 typename InterruptType>
386 RandomGenerator& randGen,
388 InterruptType* interrupt = NULL)
390 , mInterrupter(interrupt)
394 , mSpread(math::
Clamp01(spread))
401 if (mInterrupter) mInterrupter->start(name);
406 if (mInterrupter) mInterrupter->end();
419 inline double getRand() {
return 0.5 + mSpread * (mRand01() - 0.5); }
421 template <
typename Gr
idT>
424 const Vec3R pos(dmin[0] + this->getRand(),
425 dmin[1] + this->getRand(),
426 dmin[2] + this->getRand());
427 mPoints.add(grid.indexToWorld(pos));
431 template <
typename Gr
idT>
432 inline void addPoint(
const GridT &grid,
const Vec3R &dmin,
const Coord &size)
434 const Vec3R pos(dmin[0] + size[0]*this->getRand(),
435 dmin[1] + size[1]*this->getRand(),
436 dmin[2] + size[2]*this->getRand());
437 mPoints.add(grid.indexToWorld(pos));
446 #endif // OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
int Floor(float x)
Return the floor of x.
Definition: Math.h:814
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
#define OPENVDB_VERSION_NAME
Definition: version.h:43
Vec3< double > Vec3d
Definition: Vec3.h:708
Simple random integer generator.
Definition: Math.h:179
Definition: Exceptions.h:39
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
Type Clamp01(Type x)
Return x clamped to [0, 1].
Definition: Math.h:256
Index64 pointCount(const PointDataTreeT &tree, const bool inCoreOnly=false)
Total points in the PointDataTree.
Definition: PointCount.h:198
uint64_t Index64
Definition: Types.h:56
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
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:52
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71