OpenVDB: PointScatter.h Source File

OpenVDB 6.1.0

tools/PointScatter.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2018 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 //
48
49 #ifndef OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
50 #define OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
51
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 <iostream>
59 #include <memory>
60 #include <string>
61
62 namespace openvdb {
63 OPENVDB_USE_VERSION_NAMESPACE
64 namespace OPENVDB_VERSION_NAME {
65 namespace tools {
66
68 template<typename PointAccessorType,
69 typename RandomGenerator,
70 typename InterruptType = util::NullInterrupter>
71 class BasePointScatter;
72
102
103
111 template<typename PointAccessorType,
112 typename RandomGenerator,
113 typename InterruptType = util::NullInterrupter>
114 class UniformPointScatter : public BasePointScatter<PointAccessorType,
115 RandomGenerator,
116 InterruptType>
117 {
118 public:
119 using BaseT = BasePointScatter<PointAccessorType, RandomGenerator, InterruptType>;
120
121 UniformPointScatter(PointAccessorType& points,
122 Index64 pointCount,
123 RandomGenerator& randGen,
124 double spread = 1.0,
125 InterruptType* interrupt = nullptr)
126 : BaseT(points, randGen, spread, interrupt)
127 , mTargetPointCount(pointCount)
128 , mPointsPerVolume(0.0f)
129 {
130 }
131 UniformPointScatter(PointAccessorType& points,
132 float pointsPerVolume,
133 RandomGenerator& randGen,
134 double spread = 1.0,
135 InterruptType* interrupt = nullptr)
136 : BaseT(points, randGen, spread, interrupt)
137 , mTargetPointCount(0)
138 , mPointsPerVolume(pointsPerVolume)
139 {
140 }
141
143 template<typename GridT>
144 bool operator()(const GridT& grid)
145 {
146 mVoxelCount = grid.activeVoxelCount();
147 if (mVoxelCount == 0) return false;
148
149 const auto voxelVolume = grid.transform().voxelVolume();
150 if (mPointsPerVolume > 0) {
151 BaseT::start("Uniform scattering with fixed point density");
152 mTargetPointCount = Index64(mPointsPerVolume * voxelVolume * double(mVoxelCount));
153 } else if (mTargetPointCount > 0) {
154 BaseT::start("Uniform scattering with fixed point count");
155 mPointsPerVolume = float(mTargetPointCount) / float(voxelVolume * double(mVoxelCount));
156 } else {
157 return false;
158 }
159
160 std::unique_ptr<Index64[]> idList{new Index64[mTargetPointCount]};
161 math::RandInt<Index64, RandomGenerator> rand(BaseT::mRand01.engine(), 0, mVoxelCount-1);
162 for (Index64 i=0; i<mTargetPointCount; ++i) idList[i] = rand();
163 tbb::parallel_sort(idList.get(), idList.get() + mTargetPointCount);
164
165 CoordBBox bbox;
166 const Vec3R offset(0.5, 0.5, 0.5);
167 typename GridT::ValueOnCIter valueIter = grid.cbeginValueOn();
168
169 for (Index64 i=0, n=valueIter.getVoxelCount() ; i != mTargetPointCount; ++i) {
170 if (BaseT::interrupt()) return false;
171 const Index64 voxelId = idList[i];
172 while ( n <= voxelId ) {
173 ++valueIter;
174 n += valueIter.getVoxelCount();
175 }
176 if (valueIter.isVoxelValue()) {// a majority is expected to be voxels
177 BaseT::addPoint(grid, valueIter.getCoord() - offset);
178 } else {// tiles contain multiple (virtual) voxels
179 valueIter.getBoundingBox(bbox);
180 BaseT::addPoint(grid, bbox.min() - offset, bbox.extents());
181 }
182 }//loop over all the active voxels and tiles
183 //}
184
185 BaseT::end();
186 return true;
187 }
188
189 // The following methods should only be called after the
190 // the operator() method was called
191 void print(const std::string &name, std::ostream& os = std::cout) const
192 {
193 os << "Uniformly scattered " << mPointCount << " points into " << mVoxelCount
194 << " active voxels in \"" << name << "\" corresponding to "
195 << mPointsPerVolume << " points per volume." << std::endl;
196 }
197
198 float getPointsPerVolume() const { return mPointsPerVolume; }
199 Index64 getTargetPointCount() const { return mTargetPointCount; }
200
201 private:
202
203 using BaseT::mPointCount;
204 using BaseT::mVoxelCount;
205 Index64 mTargetPointCount;
206 float mPointsPerVolume;
207
208 }; // class UniformPointScatter
209
212 template<typename PointAccessorType,
213 typename RandomGenerator,
214 typename InterruptType = util::NullInterrupter>
215 class DenseUniformPointScatter : public BasePointScatter<PointAccessorType,
216 RandomGenerator,
217 InterruptType>
218 {
219 public:
220 using BaseT = BasePointScatter<PointAccessorType, RandomGenerator, InterruptType>;
221
222 DenseUniformPointScatter(PointAccessorType& points,
223 float pointsPerVoxel,
224 RandomGenerator& randGen,
225 double spread = 1.0,
226 InterruptType* interrupt = nullptr)
227 : BaseT(points, randGen, spread, interrupt)
228 , mPointsPerVoxel(pointsPerVoxel)
229 {
230 }
231
233 template<typename GridT>
234 bool operator()(const GridT& grid)
235 {
236 using ValueIter = typename GridT::ValueOnCIter;
237 if (mPointsPerVoxel < 1.0e-6) return false;
238 mVoxelCount = grid.activeVoxelCount();
239 if (mVoxelCount == 0) return false;
240 BaseT::start("Dense uniform scattering with fixed point count");
241 CoordBBox bbox;
242 const Vec3R offset(0.5, 0.5, 0.5);
243
244 const int ppv = math::Floor(mPointsPerVoxel);
245 const double delta = mPointsPerVoxel - float(ppv);
246 const bool fractional = !math::isApproxZero(delta, 1.0e-6);
247
248 for (ValueIter iter = grid.cbeginValueOn(); iter; ++iter) {
249 if (BaseT::interrupt()) return false;
250 if (iter.isVoxelValue()) {// a majority is expected to be voxels
251 const Vec3R dmin = iter.getCoord() - offset;
252 for (int n = 0; n != ppv; ++n) BaseT::addPoint(grid, dmin);
253 if (fractional && BaseT::getRand01() < delta) BaseT::addPoint(grid, dmin);
254 } else {// tiles contain multiple (virtual) voxels
255 iter.getBoundingBox(bbox);
256 const Coord size(bbox.extents());
257 const Vec3R dmin = bbox.min() - offset;
258 const double d = mPointsPerVoxel * float(iter.getVoxelCount());
259 const int m = math::Floor(d);
260 for (int n = 0; n != m; ++n) BaseT::addPoint(grid, dmin, size);
261 if (BaseT::getRand01() < d - m) BaseT::addPoint(grid, dmin, size);
262 }
263 }//loop over all the active voxels and tiles
264 //}
265 BaseT::end();
266 return true;
267 }
268
269 // The following methods should only be called after the
270 // the operator() method was called
271 void print(const std::string &name, std::ostream& os = std::cout) const
272 {
273 os << "Dense uniformly scattered " << mPointCount << " points into " << mVoxelCount
274 << " active voxels in \"" << name << "\" corresponding to "
275 << mPointsPerVoxel << " points per voxel." << std::endl;
276 }
277
278 float getPointsPerVoxel() const { return mPointsPerVoxel; }
279
280 private:
281 using BaseT::mPointCount;
282 using BaseT::mVoxelCount;
283 float mPointsPerVoxel;
284 }; // class DenseUniformPointScatter
285
294 template<typename PointAccessorType,
295 typename RandomGenerator,
296 typename InterruptType = util::NullInterrupter>
297 class NonUniformPointScatter : public BasePointScatter<PointAccessorType,
298 RandomGenerator,
299 InterruptType>
300 {
301 public:
302 using BaseT = BasePointScatter<PointAccessorType, RandomGenerator, InterruptType>;
303
304 NonUniformPointScatter(PointAccessorType& points,
305 float pointsPerVolume,
306 RandomGenerator& randGen,
307 double spread = 1.0,
308 InterruptType* interrupt = nullptr)
309 : BaseT(points, randGen, spread, interrupt)
310 , mPointsPerVolume(pointsPerVolume)//note this is merely a
311 //multiplier for the local point density
312 {
313 }
314
316 template<typename GridT>
317 bool operator()(const GridT& grid)
318 {
319 if (mPointsPerVolume <= 0.0f) return false;
320 mVoxelCount = grid.activeVoxelCount();
321 if (mVoxelCount == 0) return false;
322 BaseT::start("Non-uniform scattering with local point density");
323 const Vec3d dim = grid.voxelSize();
324 const double volumePerVoxel = dim[0]*dim[1]*dim[2],
325 pointsPerVoxel = mPointsPerVolume * volumePerVoxel;
326 CoordBBox bbox;
327 const Vec3R offset(0.5, 0.5, 0.5);
328 for (typename GridT::ValueOnCIter iter = grid.cbeginValueOn(); iter; ++iter) {
329 if (BaseT::interrupt()) return false;
330 const double d = double(*iter) * pointsPerVoxel * double(iter.getVoxelCount());
331 const int n = int(d);
332 if (iter.isVoxelValue()) { // a majority is expected to be voxels
333 const Vec3R dmin =iter.getCoord() - offset;
334 for (int i = 0; i < n; ++i) BaseT::addPoint(grid, dmin);
335 if (BaseT::getRand01() < (d - n)) BaseT::addPoint(grid, dmin);
336 } else { // tiles contain multiple (virtual) voxels
337 iter.getBoundingBox(bbox);
338 const Coord size(bbox.extents());
339 const Vec3R dmin = bbox.min() - offset;
340 for (int i = 0; i < n; ++i) BaseT::addPoint(grid, dmin, size);
341 if (BaseT::getRand01() < (d - n)) BaseT::addPoint(grid, dmin, size);
342 }
343 }//loop over all the active voxels and tiles
344 BaseT::end();
345 return true;
346 }
347
348 // The following methods should only be called after the
349 // the operator() method was called
350 void print(const std::string &name, std::ostream& os = std::cout) const
351 {
352 os << "Non-uniformly scattered " << mPointCount << " points into " << mVoxelCount
353 << " active voxels in \"" << name << "\"." << std::endl;
354 }
355
356 float getPointPerVolume() const { return mPointsPerVolume; }
357
358 private:
359 using BaseT::mPointCount;
360 using BaseT::mVoxelCount;
361 float mPointsPerVolume;
362
363 }; // class NonUniformPointScatter
364
366 template<typename PointAccessorType,
367 typename RandomGenerator,
368 typename InterruptType>
369 class BasePointScatter
370 {
371 public:
372
373 Index64 getPointCount() const { return mPointCount; }
374 Index64 getVoxelCount() const { return mVoxelCount; }
375
376 protected:
377
378 PointAccessorType& mPoints;
379 InterruptType* mInterrupter;
380 Index64 mPointCount;
381 Index64 mVoxelCount;
382 Index64 mInterruptCount;
383 const double mSpread;
384 math::Rand01<double, RandomGenerator> mRand01;
385
387 BasePointScatter(PointAccessorType& points,
388 RandomGenerator& randGen,
389 double spread,
390 InterruptType* interrupt = nullptr)
391 : mPoints(points)
392 , mInterrupter(interrupt)
393 , mPointCount(0)
394 , mVoxelCount(0)
395 , mInterruptCount(0)
396 , mSpread(math::Clamp01(spread))
397 , mRand01(randGen)
398 {
399 }
400
401 inline void start(const char* name)
402 {
403 if (mInterrupter) mInterrupter->start(name);
404 }
405
406 inline void end()
407 {
408 if (mInterrupter) mInterrupter->end();
409 }
410
411 inline bool interrupt()
412 {
413 //only check interrupter for every 32'th call
414 return !(mInterruptCount++ & ((1<<5)-1)) && util::wasInterrupted(mInterrupter);
415 }
416
418 inline double getRand01() { return mRand01(); }
419
421 inline double getRand() { return 0.5 + mSpread * (mRand01() - 0.5); }
422
423 template <typename GridT>
424 inline void addPoint(const GridT &grid, const Vec3R &dmin)
425 {
426 const Vec3R pos(dmin[0] + this->getRand(),
427 dmin[1] + this->getRand(),
428 dmin[2] + this->getRand());
429 mPoints.add(grid.indexToWorld(pos));
430 ++mPointCount;
431 }
432
433 template <typename GridT>
434 inline void addPoint(const GridT &grid, const Vec3R &dmin, const Coord &size)
435 {
436 const Vec3R pos(dmin[0] + size[0]*this->getRand(),
437 dmin[1] + size[1]*this->getRand(),
438 dmin[2] + size[2]*this->getRand());
439 mPoints.add(grid.indexToWorld(pos));
440 ++mPointCount;
441 }
442 };// class BasePointScatter
443
444 } // namespace tools
445 } // namespace OPENVDB_VERSION_NAME
446 } // namespace openvdb
447
448 #endif // OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
449
450 // Copyright (c) 2012-2018 DreamWorks Animation LLC
451 // All rights reserved. This software is distributed under the
452 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
openvdb::v6_1::tools::UniformPointScatter::UniformPointScatter
UniformPointScatter(PointAccessorType &points, Index64 pointCount, RandomGenerator &randGen, double spread=1.0, InterruptType *interrupt=nullptr)
Definition: tools/PointScatter.h:121
openvdb::v6_1::tools::BasePointScatter::mVoxelCount
Index64 mVoxelCount
Definition: tools/PointScatter.h:381
Types.h
openvdb::v6_1::tools::BasePointScatter::getRand01
double getRand01()
Return a random floating point number between zero and one.
Definition: tools/PointScatter.h:418
NullInterrupter.h
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
openvdb::v6_1::tools::DenseUniformPointScatter::getPointsPerVoxel
float getPointsPerVoxel() const
Definition: tools/PointScatter.h:278
openvdb::v6_1::tools::BasePointScatter::getRand
double getRand()
Return a random floating point number between 0.5 -+ mSpread/2.
Definition: tools/PointScatter.h:421
openvdb::v6_1::tools::BasePointScatter::BasePointScatter
BasePointScatter(PointAccessorType &points, RandomGenerator &randGen, double spread, InterruptType *interrupt=nullptr)
This is a base class so the constructor is protected.
Definition: tools/PointScatter.h:387
openvdb::v6_1::tools::BasePointScatter::getPointCount
Index64 getPointCount() const
Definition: tools/PointScatter.h:373
openvdb::v6_1::tools::BasePointScatter::start
void start(const char *name)
Definition: tools/PointScatter.h:401
openvdb::v6_1::tools::BasePointScatter::mPointCount
Index64 mPointCount
Definition: tools/PointScatter.h:380
openvdb::v6_1::tools::DenseUniformPointScatter::operator()
bool operator()(const GridT &grid)
This is the main functor method implementing the actual scattering of points.
Definition: tools/PointScatter.h:234
openvdb::v6_1::tools::BasePointScatter::mRand01
math::Rand01< double, RandomGenerator > mRand01
Definition: tools/PointScatter.h:384
openvdb::v6_1::math::Rand01< double, RandomGenerator >
openvdb::v6_1::tools::UniformPointScatter::print
void print(const std::string &name, std::ostream &os=std::cout) const
Definition: tools/PointScatter.h:191
openvdb::v6_1::util::wasInterrupted
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
openvdb::v6_1::math::Vec3d
Vec3< double > Vec3d
Definition: Vec3.h:689
openvdb::v6_1::tools::UniformPointScatter::operator()
bool operator()(const GridT &grid)
This is the main functor method implementing the actual scattering of points.
Definition: tools/PointScatter.h:144
openvdb::v6_1::tools::BasePointScatter
Forward declaration of base class.
Definition: tools/PointScatter.h:71
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:125
openvdb::v6_1::math::CoordBBox::extents
Coord extents() const
Definition: Coord.h:403
openvdb::v6_1::tools::BasePointScatter::getVoxelCount
Index64 getVoxelCount() const
Definition: tools/PointScatter.h:374
openvdb::v6_1::tools::BasePointScatter::addPoint
void addPoint(const GridT &grid, const Vec3R &dmin)
Definition: tools/PointScatter.h:424
openvdb::v6_1::tools::BasePointScatter::end
void end()
Definition: tools/PointScatter.h:406
openvdb::v6_1::Index64
uint64_t Index64
Definition: Types.h:60
openvdb::v6_1::tools::BasePointScatter::addPoint
void addPoint(const GridT &grid, const Vec3R &dmin, const Coord &size)
Definition: tools/PointScatter.h:434
openvdb::v6_1::tools::NonUniformPointScatter::print
void print(const std::string &name, std::ostream &os=std::cout) const
Definition: tools/PointScatter.h:350
openvdb::v6_1::tools::BasePointScatter::mInterrupter
InterruptType * mInterrupter
Definition: tools/PointScatter.h:379
openvdb
Definition: Exceptions.h:40
openvdb::v6_1::tools::DenseUniformPointScatter
Scatters a fixed (and integer) number of points in all active voxels and tiles.
Definition: tools/PointScatter.h:215
openvdb::v6_1::tools::NonUniformPointScatter
Non-uniform scatters of point in the active voxels. The local point count is implicitly defined as a ...
Definition: tools/PointScatter.h:297
openvdb::v6_1::math::CoordBBox
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:271
openvdb::v6_1::math::Vec3< Real >
openvdb::v6_1::tools::NonUniformPointScatter::operator()
bool operator()(const GridT &grid)
This is the main functor method implementing the actual scattering of points.
Definition: tools/PointScatter.h:317
openvdb::v6_1::tools::BasePointScatter::interrupt
bool interrupt()
Definition: tools/PointScatter.h:411
openvdb::v6_1::util::NullInterrupter
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:52
openvdb::v6_1::tools::BasePointScatter::mPoints
PointAccessorType & mPoints
Definition: tools/PointScatter.h:378
openvdb::v6_1::math::CoordBBox::min
const Coord & min() const
Definition: Coord.h:344
openvdb::v6_1::points::pointCount
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:115
openvdb::v6_1::tools::UniformPointScatter::getTargetPointCount
Index64 getTargetPointCount() const
Definition: tools/PointScatter.h:199
openvdb::v6_1::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:52
openvdb::v6_1::math::Floor
int Floor(float x)
Return the floor of x.
Definition: Math.h:802
openvdb::v6_1::tools::NonUniformPointScatter::NonUniformPointScatter
NonUniformPointScatter(PointAccessorType &points, float pointsPerVolume, RandomGenerator &randGen, double spread=1.0, InterruptType *interrupt=nullptr)
Definition: tools/PointScatter.h:304
openvdb::v6_1::tools::BasePointScatter::mInterruptCount
Index64 mInterruptCount
Definition: tools/PointScatter.h:382
Grid.h
openvdb::v6_1::math::RandInt
Simple random integer generator.
Definition: Math.h:171
openvdb::v6_1::tools::DenseUniformPointScatter::print
void print(const std::string &name, std::ostream &os=std::cout) const
Definition: tools/PointScatter.h:271
openvdb::v6_1::math::Clamp01
Type Clamp01(Type x)
Return x clamped to [0, 1].
Definition: Math.h:240
openvdb::v6_1::math::isApproxZero
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance.
Definition: Math.h:320
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:177
openvdb::v6_1::tools::UniformPointScatter
The two point scatters UniformPointScatter and NonUniformPointScatter depend on the following two cla...
Definition: tools/PointScatter.h:114
openvdb::v6_1::tools::BasePointScatter::mSpread
const double mSpread
Definition: tools/PointScatter.h:383
openvdb::v6_1::tools::DenseUniformPointScatter::DenseUniformPointScatter
DenseUniformPointScatter(PointAccessorType &points, float pointsPerVoxel, RandomGenerator &randGen, double spread=1.0, InterruptType *interrupt=nullptr)
Definition: tools/PointScatter.h:222
openvdb::v6_1::tools::NonUniformPointScatter::getPointPerVolume
float getPointPerVolume() const
Definition: tools/PointScatter.h:356
openvdb::v6_1::tools::UniformPointScatter::getPointsPerVolume
float getPointsPerVolume() const
Definition: tools/PointScatter.h:198
openvdb::v6_1::tools::UniformPointScatter::UniformPointScatter
UniformPointScatter(PointAccessorType &points, float pointsPerVolume, RandomGenerator &randGen, double spread=1.0, InterruptType *interrupt=nullptr)
Definition: tools/PointScatter.h:131