22 #ifndef OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED 23 #define OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED 29 #include <tbb/parallel_sort.h> 30 #include <tbb/parallel_for.h> 41 template<
typename PointAccessorType,
42 typename RandomGenerator,
43 typename InterruptType = util::NullInterrupter>
84 template<
typename PointAccessorType,
85 typename RandomGenerator,
96 RandomGenerator& randGen,
98 InterruptType* interrupt =
nullptr)
99 :
BaseT(points, randGen, spread, interrupt)
100 , mTargetPointCount(pointCount)
101 , mPointsPerVolume(0.0f)
105 float pointsPerVolume,
106 RandomGenerator& randGen,
108 InterruptType* interrupt =
nullptr)
109 :
BaseT(points, randGen, spread, interrupt)
110 , mTargetPointCount(0)
111 , mPointsPerVolume(pointsPerVolume)
116 template<
typename Gr
idT>
119 mVoxelCount = grid.activeVoxelCount();
120 if (mVoxelCount == 0)
return false;
122 const auto voxelVolume = grid.transform().voxelVolume();
123 if (mPointsPerVolume > 0) {
124 BaseT::start(
"Uniform scattering with fixed point density");
125 mTargetPointCount =
Index64(mPointsPerVolume * voxelVolume *
double(mVoxelCount));
126 }
else if (mTargetPointCount > 0) {
127 BaseT::start(
"Uniform scattering with fixed point count");
128 mPointsPerVolume = float(mTargetPointCount) / float(voxelVolume *
double(mVoxelCount));
133 std::unique_ptr<Index64[]> idList{
new Index64[mTargetPointCount]};
135 for (
Index64 i=0; i<mTargetPointCount; ++i) idList[i] = rand();
136 tbb::parallel_sort(idList.get(), idList.get() + mTargetPointCount);
139 const Vec3R offset(0.5, 0.5, 0.5);
140 typename GridT::ValueOnCIter valueIter = grid.cbeginValueOn();
142 for (
Index64 i=0, n=valueIter.getVoxelCount() ; i != mTargetPointCount; ++i) {
143 if (BaseT::interrupt())
return false;
144 const Index64 voxelId = idList[i];
145 while ( n <= voxelId ) {
147 n += valueIter.getVoxelCount();
149 if (valueIter.isVoxelValue()) {
150 BaseT::addPoint(grid, valueIter.getCoord() - offset);
152 valueIter.getBoundingBox(bbox);
153 BaseT::addPoint(grid, bbox.min() - offset, bbox.extents());
164 void print(
const std::string &name, std::ostream& os = std::cout)
const 166 os <<
"Uniformly scattered " << mPointCount <<
" points into " << mVoxelCount
167 <<
" active voxels in \"" << name <<
"\" corresponding to " 168 << mPointsPerVolume <<
" points per volume." << std::endl;
176 using BaseT::mPointCount;
177 using BaseT::mVoxelCount;
179 float mPointsPerVolume;
185 template<
typename PointAccessorType,
186 typename RandomGenerator,
196 float pointsPerVoxel,
197 RandomGenerator& randGen,
199 InterruptType* interrupt =
nullptr)
200 :
BaseT(points, randGen, spread, interrupt)
201 , mPointsPerVoxel(pointsPerVoxel)
206 template<
typename Gr
idT>
209 using ValueIter =
typename GridT::ValueOnCIter;
210 if (mPointsPerVoxel < 1.0e-6)
return false;
211 mVoxelCount = grid.activeVoxelCount();
212 if (mVoxelCount == 0)
return false;
213 BaseT::start(
"Dense uniform scattering with fixed point count");
215 const Vec3R offset(0.5, 0.5, 0.5);
218 const double delta = mPointsPerVoxel - float(ppv);
221 for (ValueIter iter = grid.cbeginValueOn(); iter; ++iter) {
222 if (BaseT::interrupt())
return false;
223 if (iter.isVoxelValue()) {
224 const Vec3R dmin = iter.getCoord() - offset;
225 for (
int n = 0; n != ppv; ++n) BaseT::addPoint(grid, dmin);
226 if (fractional && BaseT::getRand01() < delta) BaseT::addPoint(grid, dmin);
228 iter.getBoundingBox(bbox);
229 const Coord size(bbox.extents());
230 const Vec3R dmin = bbox.min() - offset;
231 const double d = mPointsPerVoxel * float(iter.getVoxelCount());
233 for (
int n = 0; n != m; ++n) BaseT::addPoint(grid, dmin, size);
234 if (BaseT::getRand01() < d - m) BaseT::addPoint(grid, dmin, size);
244 void print(
const std::string &name, std::ostream& os = std::cout)
const 246 os <<
"Dense uniformly scattered " << mPointCount <<
" points into " << mVoxelCount
247 <<
" active voxels in \"" << name <<
"\" corresponding to " 248 << mPointsPerVoxel <<
" points per voxel." << std::endl;
254 using BaseT::mPointCount;
255 using BaseT::mVoxelCount;
256 float mPointsPerVoxel;
267 template<
typename PointAccessorType,
268 typename RandomGenerator,
278 float pointsPerVolume,
279 RandomGenerator& randGen,
281 InterruptType* interrupt =
nullptr)
282 :
BaseT(points, randGen, spread, interrupt)
283 , mPointsPerVolume(pointsPerVolume)
289 template<
typename Gr
idT>
292 if (mPointsPerVolume <= 0.0f)
return false;
293 mVoxelCount = grid.activeVoxelCount();
294 if (mVoxelCount == 0)
return false;
295 BaseT::start(
"Non-uniform scattering with local point density");
296 const Vec3d dim = grid.voxelSize();
297 const double volumePerVoxel = dim[0]*dim[1]*dim[2],
298 pointsPerVoxel = mPointsPerVolume * volumePerVoxel;
300 const Vec3R offset(0.5, 0.5, 0.5);
301 for (
typename GridT::ValueOnCIter iter = grid.cbeginValueOn(); iter; ++iter) {
302 if (BaseT::interrupt())
return false;
303 const double d = double(*iter) * pointsPerVoxel * double(iter.getVoxelCount());
304 const int n = int(d);
305 if (iter.isVoxelValue()) {
306 const Vec3R dmin =iter.getCoord() - offset;
307 for (
int i = 0; i < n; ++i) BaseT::addPoint(grid, dmin);
308 if (BaseT::getRand01() < (d - n)) BaseT::addPoint(grid, dmin);
310 iter.getBoundingBox(bbox);
311 const Coord size(bbox.extents());
312 const Vec3R dmin = bbox.min() - offset;
313 for (
int i = 0; i < n; ++i) BaseT::addPoint(grid, dmin, size);
314 if (BaseT::getRand01() < (d - n)) BaseT::addPoint(grid, dmin, size);
323 void print(
const std::string &name, std::ostream& os = std::cout)
const 325 os <<
"Non-uniformly scattered " << mPointCount <<
" points into " << mVoxelCount
326 <<
" active voxels in \"" << name <<
"\"." << std::endl;
332 using BaseT::mPointCount;
333 using BaseT::mVoxelCount;
334 float mPointsPerVolume;
339 template<
typename PointAccessorType,
340 typename RandomGenerator,
341 typename InterruptType>
361 RandomGenerator& randGen,
363 InterruptType* interrupt =
nullptr)
365 , mInterrupter(interrupt)
369 , mSpread(math::
Clamp01(spread))
376 if (mInterrupter) mInterrupter->start(name);
381 if (mInterrupter) mInterrupter->end();
394 inline double getRand() {
return 0.5 + mSpread * (mRand01() - 0.5); }
396 template <
typename Gr
idT>
399 const Vec3R pos(dmin[0] + this->getRand(),
400 dmin[1] + this->getRand(),
401 dmin[2] + this->getRand());
402 mPoints.add(grid.indexToWorld(pos));
406 template <
typename Gr
idT>
407 inline void addPoint(
const GridT &grid,
const Vec3R &dmin,
const Coord &size)
409 const Vec3R pos(dmin[0] + size[0]*this->getRand(),
410 dmin[1] + size[1]*this->getRand(),
411 dmin[2] + size[2]*this->getRand());
412 mPoints.add(grid.indexToWorld(pos));
421 #endif // OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:49
Simple random integer generator.
Definition: Math.h:201
Index64 pointCount(const PointDataTreeT &tree, const FilterT &filter=NullFilter(), const bool inCoreOnly=false, const bool threaded=true)
Count the total number of points in a PointDataTree.
Definition: PointCount.h:88
Type Clamp01(Type x)
Return x clamped to [0, 1].
Definition: Math.h:270
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Base class for interrupters.
Definition: NullInterrupter.h:25
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
Definition: Math.h:350
int Floor(float x)
Return the floor of x.
Definition: Math.h:851
BBox< Coord > CoordBBox
Definition: NanoVDB.h:1658
uint64_t Index64
Definition: Types.h:53
Definition: Exceptions.h:13
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202