OpenVDB 3.2.0

PointScatter.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2016 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 <boost/scoped_array.hpp>
59
60 namespace openvdb {
61 OPENVDB_USE_VERSION_NAMESPACE
62 namespace OPENVDB_VERSION_NAME {
63 namespace tools {
64
66 template<typename PointAccessorType,
67 typename RandomGenerator,
68 typename InterruptType = util::NullInterrupter>
69 class BasePointScatter;
70
100
101
109 template<typename PointAccessorType,
110 typename RandomGenerator,
111 typename InterruptType = util::NullInterrupter>
112 class UniformPointScatter : public BasePointScatter<PointAccessorType,
113 RandomGenerator,
114 InterruptType>
115 {
116 public:
117 typedef BasePointScatter<PointAccessorType, RandomGenerator, InterruptType> BaseT;
118
119 UniformPointScatter(PointAccessorType& points,
120 Index64 pointCount,
121 RandomGenerator& randGen,
122 InterruptType* interrupt = NULL)
123 : BaseT(points, randGen, interrupt)
124 , mTargetPointCount(pointCount)
125 , mPointsPerVolume(0.0f)
126 {
127 }
128 UniformPointScatter(PointAccessorType& points,
129 float pointsPerVolume,
130 RandomGenerator& randGen,
131 InterruptType* interrupt = NULL)
132 : BaseT(points, randGen, interrupt)
133 , mTargetPointCount(0)
134 , mPointsPerVolume(pointsPerVolume)
135 {
136 }
137
140 template<typename GridT>
141 bool operator()(const GridT& grid)
142 {
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);
152 } else {
153 return false;
154 }
155
156 boost::scoped_array<Index64> list(new Index64[mTargetPointCount]);
157 math::RandInt<Index64, RandomGenerator> rand(BaseT::mRand01.engine(), 0, mVoxelCount-1);
158 for (Index64 i=0; i<mTargetPointCount; ++i) list[i] = rand();
159 tbb::parallel_sort(list.get(), list.get() + mTargetPointCount);
160
161 CoordBBox bbox;
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 ) {
168 ++valueIter;
169 n += valueIter.getVoxelCount();
170 }
171 if (valueIter.isVoxelValue()) {// a majority is expected to be voxels
172 BaseT::addPoint(grid, valueIter.getCoord() - offset);
173 } else {// tiles contain multiple (virtual) voxels
174 valueIter.getBoundingBox(bbox);
175 BaseT::addPoint(grid, bbox.min() - offset, bbox.extents());
176 }
177 }//loop over all the active voxels and tiles
178
179 BaseT::end();
180 return true;
181 }
182
183 // The following methods should only be called after the
184 // the operator() method was called
185 void print(const std::string &name, std::ostream& os = std::cout) const
186 {
187 os << "Uniformely scattered " << mPointCount << " points into " << mVoxelCount
188 << " active voxels in \"" << name << "\" corresponding to "
189 << mPointsPerVolume << " points per volume." << std::endl;
190 }
191
192 float getPointsPerVolume() const { return mPointsPerVolume; }
193 Index64 getTargetPointCount() const { return mTargetPointCount; }
194
195 private:
196
197 using BaseT::mPointCount;
198 using BaseT::mVoxelCount;
199 Index64 mTargetPointCount;
200 float mPointsPerVolume;
201
202 }; // class UniformPointScatter
203
206 template<typename PointAccessorType,
207 typename RandomGenerator,
208 typename InterruptType = util::NullInterrupter>
209 class DenseUniformPointScatter : public BasePointScatter<PointAccessorType,
210 RandomGenerator,
211 InterruptType>
212 {
213 public:
214 typedef BasePointScatter<PointAccessorType, RandomGenerator, InterruptType> BaseT;
215
216 DenseUniformPointScatter(PointAccessorType& points,
217 float pointsPerVoxel,
218 RandomGenerator& randGen,
219 InterruptType* interrupt = NULL)
220 : BaseT(points, randGen, interrupt)
221 , mPointsPerVoxel(pointsPerVoxel)
222 {
223 }
224
226 template<typename GridT>
227 bool operator()(const GridT& grid)
228 {
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");
234 CoordBBox bbox;
235 const Vec3R offset(0.5, 0.5, 0.5);
236
237 const int ppv = math::Floor(mPointsPerVoxel);
238 const double delta = mPointsPerVoxel - ppv;
239 const bool fractional = !math::isApproxZero(delta, 1.0e-6);
240
241 for (ValueIter iter = grid.cbeginValueOn(); iter; ++iter) {
242 if (BaseT::interrupt()) return false;
243 if (iter.isVoxelValue()) {// a majority is expected to be voxels
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);
247 } else {// tiles contain multiple (virtual) voxels
248 iter.getBoundingBox(bbox);
249 const Coord size(bbox.extents());
250 const Vec3R dmin = bbox.min() - offset;
251 const double d = mPointsPerVoxel * iter.getVoxelCount();
252 const int m = math::Floor(d);
253 for (int n = 0; n != m; ++n) BaseT::addPoint(grid, dmin, size);
254 if (BaseT::getRand() < d - m) BaseT::addPoint(grid, dmin, size);
255 }
256 }//loop over all the active voxels and tiles
257
258 BaseT::end();
259 return true;
260 }
261
262 // The following methods should only be called after the
263 // the operator() method was called
264 void print(const std::string &name, std::ostream& os = std::cout) const
265 {
266 os << "Dense uniformly scattered " << mPointCount << " points into " << mVoxelCount
267 << " active voxels in \"" << name << "\" corresponding to "
268 << mPointsPerVoxel << " points per voxel." << std::endl;
269 }
270
271 float getPointsPerVoxel() const { return mPointsPerVoxel; }
272
273 private:
274 using BaseT::mPointCount;
275 using BaseT::mVoxelCount;
276 float mPointsPerVoxel;
277 }; // class DenseUniformPointScatter
278
287 template<typename PointAccessorType,
288 typename RandomGenerator,
289 typename InterruptType = util::NullInterrupter>
290 class NonUniformPointScatter : public BasePointScatter<PointAccessorType,
291 RandomGenerator,
292 InterruptType>
293 {
294 public:
295 typedef BasePointScatter<PointAccessorType, RandomGenerator, InterruptType> BaseT;
296
297 NonUniformPointScatter(PointAccessorType& points,
298 float pointsPerVolume,
299 RandomGenerator& randGen,
300 InterruptType* interrupt = NULL)
301 : BaseT(points, randGen, interrupt)
302 , mPointsPerVolume(pointsPerVolume)//note this is merely a
303 //multiplier for the local point density
304 {
305 }
306
308 template<typename GridT>
309 bool operator()(const GridT& grid)
310 {
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;
318 CoordBBox bbox;
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()) { // a majority is expected to be voxels
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);
328 } else { // tiles contain multiple (virtual) voxels
329 iter.getBoundingBox(bbox);
330 const Coord size(bbox.extents());
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);
334 }
335 }//loop over all the active voxels and tiles
336 BaseT::end();
337 return true;
338 }
339
340 // The following methods should only be called after the
341 // the operator() method was called
342 void print(const std::string &name, std::ostream& os = std::cout) const
343 {
344 os << "Non-uniformly scattered " << mPointCount << " points into " << mVoxelCount
345 << " active voxels in \"" << name << "\"." << std::endl;
346 }
347
348 float getPointPerVolume() const { return mPointsPerVolume; }
349
350 private:
351 using BaseT::mPointCount;
352 using BaseT::mVoxelCount;
353 float mPointsPerVolume;
354
355 }; // class NonUniformPointScatter
356
358 template<typename PointAccessorType,
359 typename RandomGenerator,
360 typename InterruptType>
361 class BasePointScatter
362 {
363 public:
364
365 Index64 getPointCount() const { return mPointCount; }
366 Index64 getVoxelCount() const { return mVoxelCount; }
367
368 protected:
369
371 BasePointScatter(PointAccessorType& points,
372 RandomGenerator& randGen,
373 InterruptType* interrupt = NULL)
374 : mPoints(points)
375 , mInterrupter(interrupt)
376 , mPointCount(0)
377 , mVoxelCount(0)
378 , mInterruptCount(0)
379 , mRand01(randGen)
380 {
381 }
382
383 PointAccessorType& mPoints;
384 InterruptType* mInterrupter;
385 Index64 mPointCount;
386 Index64 mVoxelCount;
387 Index64 mInterruptCount;
388 math::Rand01<double, RandomGenerator> mRand01;
389
390 inline void start(const char* name)
391 {
392 if (mInterrupter) mInterrupter->start(name);
393 }
394
395 inline void end()
396 {
397 if (mInterrupter) mInterrupter->end();
398 }
399
400 inline bool interrupt()
401 {
402 //only check interrupter for every 32'th call
403 return !(mInterruptCount++ & ((1<<5)-1)) && util::wasInterrupted(mInterrupter);
404 }
405
406 inline double getRand() { return mRand01(); }
407
408 template <typename GridT>
409 inline void addPoint(const GridT &grid, const Vec3R &dmin)
410 {
411 const Vec3R pos(dmin[0] + this->getRand(),
412 dmin[1] + this->getRand(),
413 dmin[2] + this->getRand());
414 mPoints.add(grid.indexToWorld(pos));
415 ++mPointCount;
416 }
417
418 template <typename GridT>
419 inline void addPoint(const GridT &grid, const Vec3R &dmin, const Coord &size)
420 {
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));
425 ++mPointCount;
426 }
427 };// class BasePointScatter
428
429 } // namespace tools
430 } // namespace OPENVDB_VERSION_NAME
431 } // namespace openvdb
432
433 #endif // OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
434
435 // Copyright (c) 2012-2016 DreamWorks Animation LLC
436 // All rights reserved. This software is distributed under the
437 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
Types.h
openvdb::v3_2_0::tools::NonUniformPointScatter::print
void print(const std::string &name, std::ostream &os=std::cout) const
Definition: PointScatter.h:342
NullInterrupter.h
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
openvdb::v3_2_0::tools::BasePointScatter::mRand01
math::Rand01< double, RandomGenerator > mRand01
Definition: PointScatter.h:388
openvdb::v3_2_0::util::NullInterrupter
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:52
openvdb::v3_2_0::tools::NonUniformPointScatter::BaseT
BasePointScatter< PointAccessorType, RandomGenerator, InterruptType > BaseT
Definition: PointScatter.h:295
openvdb::v3_2_0::tools::BasePointScatter::mPointCount
Index64 mPointCount
Definition: PointScatter.h:385
openvdb::v3_2_0::tools::UniformPointScatter::UniformPointScatter
UniformPointScatter(PointAccessorType &points, Index64 pointCount, RandomGenerator &randGen, InterruptType *interrupt=NULL)
Definition: PointScatter.h:119
openvdb::v3_2_0::tools::BasePointScatter::mInterruptCount
Index64 mInterruptCount
Definition: PointScatter.h:387
openvdb::v3_2_0::math::Vec3< Real >
openvdb::v3_2_0::tools::BasePointScatter::addPoint
void addPoint(const GridT &grid, const Vec3R &dmin, const Coord &size)
Definition: PointScatter.h:419
openvdb::v3_2_0::math::Rand01< double, RandomGenerator >
openvdb::v3_2_0::tools::DenseUniformPointScatter::DenseUniformPointScatter
DenseUniformPointScatter(PointAccessorType &points, float pointsPerVoxel, RandomGenerator &randGen, InterruptType *interrupt=NULL)
Definition: PointScatter.h:216
openvdb::v3_2_0::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:47
openvdb::v3_2_0::tools::UniformPointScatter
The two point scatters UniformPointScatter and NonUniformPointScatter depend on the following two cla...
Definition: PointScatter.h:112
openvdb::v3_2_0::tools::DenseUniformPointScatter::getPointsPerVoxel
float getPointsPerVoxel() const
Definition: PointScatter.h:271
openvdb::v3_2_0::math::RandInt
Simple random integer generator.
Definition: Math.h:179
openvdb::v3_2_0::tools::DenseUniformPointScatter::operator()
bool operator()(const GridT &grid)
This is the main functor method implementing the actual scattering of points.
Definition: PointScatter.h:227
openvdb::v3_2_0::tools::BasePointScatter::mVoxelCount
Index64 mVoxelCount
Definition: PointScatter.h:386
openvdb::v3_2_0::tools::BasePointScatter::getVoxelCount
Index64 getVoxelCount() const
Definition: PointScatter.h:366
openvdb::v3_2_0::Index64
uint64_t Index64
Definition: Types.h:57
openvdb::v3_2_0::tools::DenseUniformPointScatter
Scatters a fixed (and integer) number of points in all active voxels and tiles.
Definition: PointScatter.h:209
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
Definition: version.h:43
openvdb::v3_2_0::tools::UniformPointScatter::BaseT
BasePointScatter< PointAccessorType, RandomGenerator, InterruptType > BaseT
Definition: PointScatter.h:117
openvdb::v3_2_0::math::Vec3d
Vec3< double > Vec3d
Definition: Vec3.h:651
openvdb::v3_2_0::tools::NonUniformPointScatter::NonUniformPointScatter
NonUniformPointScatter(PointAccessorType &points, float pointsPerVolume, RandomGenerator &randGen, InterruptType *interrupt=NULL)
Definition: PointScatter.h:297
openvdb::v3_2_0::tools::UniformPointScatter::getTargetPointCount
Index64 getTargetPointCount() const
Definition: PointScatter.h:193
openvdb::v3_2_0::tools::NonUniformPointScatter
Non-uniform scatters of point in the active voxels. The local point count is implicitly defined as a ...
Definition: PointScatter.h:290
openvdb::v3_2_0::tools::UniformPointScatter::operator()
bool operator()(const GridT &grid)
This is the main functor method implementing the actual scattering of points.
Definition: PointScatter.h:141
openvdb::v3_2_0::tools::BasePointScatter::BasePointScatter
BasePointScatter(PointAccessorType &points, RandomGenerator &randGen, InterruptType *interrupt=NULL)
This is a base class so the constructor is protected.
Definition: PointScatter.h:371
openvdb::v3_2_0::tools::DenseUniformPointScatter::BaseT
BasePointScatter< PointAccessorType, RandomGenerator, InterruptType > BaseT
Definition: PointScatter.h:214
openvdb::v3_2_0::math::CoordBBox::extents
Coord extents() const
Definition: Coord.h:365
openvdb::v3_2_0::tools::BasePointScatter::interrupt
bool interrupt()
Definition: PointScatter.h:400
openvdb::v3_2_0::tools::BasePointScatter::mPoints
PointAccessorType & mPoints
Definition: PointScatter.h:383
openvdb::v3_2_0::tools::NonUniformPointScatter::operator()
bool operator()(const GridT &grid)
This is the main functor method implementing the actual scattering of points.
Definition: PointScatter.h:309
openvdb
Definition: Exceptions.h:39
openvdb::v3_2_0::tools::BasePointScatter::getRand
double getRand()
Definition: PointScatter.h:406
openvdb::v3_2_0::tools::UniformPointScatter::getPointsPerVolume
float getPointsPerVolume() const
Definition: PointScatter.h:192
openvdb::v3_2_0::tools::BasePointScatter::mInterrupter
InterruptType * mInterrupter
Definition: PointScatter.h:384
openvdb::v3_2_0::tools::DenseUniformPointScatter::print
void print(const std::string &name, std::ostream &os=std::cout) const
Definition: PointScatter.h:264
openvdb::v3_2_0::tools::UniformPointScatter::UniformPointScatter
UniformPointScatter(PointAccessorType &points, float pointsPerVolume, RandomGenerator &randGen, InterruptType *interrupt=NULL)
Definition: PointScatter.h:128
openvdb::v3_2_0::tools::BasePointScatter::getPointCount
Index64 getPointCount() const
Definition: PointScatter.h:365
openvdb::v3_2_0::tools::BasePointScatter
Forward declaration of base class.
Definition: PointScatter.h:69
openvdb::v3_2_0::math::CoordBBox::min
const Coord & min() const
Definition: Coord.h:332
openvdb::v3_2_0::tools::UniformPointScatter::print
void print(const std::string &name, std::ostream &os=std::cout) const
Definition: PointScatter.h:185
openvdb::v3_2_0::math::Floor
int Floor(float x)
Return the floor of x.
Definition: Math.h:814
openvdb::v3_2_0::math::CoordBBox
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:259
Grid.h
openvdb::v3_2_0::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:336
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
openvdb::v3_2_0::tools::NonUniformPointScatter::getPointPerVolume
float getPointPerVolume() const
Definition: PointScatter.h:348
openvdb::v3_2_0::tools::BasePointScatter::end
void end()
Definition: PointScatter.h:395
openvdb::v3_2_0::tools::BasePointScatter::start
void start(const char *name)
Definition: PointScatter.h:390
openvdb::v3_2_0::tools::BasePointScatter::addPoint
void addPoint(const GridT &grid, const Vec3R &dmin)
Definition: PointScatter.h:409
openvdb::v3_2_0::util::wasInterrupted
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76