OpenVDB  2.3.0
PointScatter.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2013 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 //
32 
33 #ifndef OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
34 #define OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
35 
36 #include <openvdb/Types.h>
37 #include <openvdb/Grid.h>
38 #include <openvdb/util/NullInterrupter.h>
39 #include <boost/random/uniform_01.hpp>
40 
41 namespace openvdb {
43 namespace OPENVDB_VERSION_NAME {
44 namespace tools {
45 
75 
76 
84 template<typename PointAccessorType,
85  typename RandomGenerator,
86  typename InterruptType = openvdb::util::NullInterrupter>
88 {
89 public:
90  UniformPointScatter(PointAccessorType& points,
91  int pointCount,
92  RandomGenerator& randGen,
93  InterruptType* interrupt = NULL):
94  mPoints(points),
95  mInterrupter(interrupt),
96  mPointCount(pointCount),
97  mPointsPerVolume(0.0f),
98  mVoxelCount(0),
99  mRandomGen(randGen)
100  {
101  }
102  UniformPointScatter(PointAccessorType& points,
103  float pointsPerVolume,
104  RandomGenerator& randGen,
105  InterruptType* interrupt = NULL):
106  mPoints(points),
107  mInterrupter(interrupt),
108  mPointCount(0),
109  mPointsPerVolume(pointsPerVolume),
110  mVoxelCount(0),
111  mRandomGen(randGen)
112  {
113  }
114 
116  template<typename GridT>
117  void operator()(const GridT& grid)
118  {
119  mVoxelCount = grid.activeVoxelCount();
120  if (mVoxelCount == 0) return;
121  const openvdb::Index64 voxelId = mVoxelCount - 1;
122  const openvdb::Vec3d dim = grid.voxelSize();
123  if (mPointsPerVolume>0) {
124  if (mInterrupter) mInterrupter->start("Uniform scattering with fixed point density");
125  mPointCount = int(mPointsPerVolume * dim[0]*dim[1]*dim[2] * mVoxelCount);
126  } else if (mPointCount>0) {
127  if (mInterrupter) mInterrupter->start("Uniform scattering with fixed point count");
128  mPointsPerVolume = mPointCount/float(dim[0]*dim[1]*dim[2] * mVoxelCount);
129  } else {
130  return;
131  }
132  openvdb::CoordBBox bbox;
134  std::multiset<openvdb::Index64> mVoxelSet;
135  const double maxId = static_cast<double>(voxelId);
136  for (int i=0, chunks=100000; i<mPointCount; i += chunks) {
137  if (util::wasInterrupted(mInterrupter)) return;
139  for (int j=i, end=std::min(i+chunks, mPointCount); j<end; ++j) {
140  mVoxelSet.insert(openvdb::Index64(math::Round(maxId*getRand())));
141  }
142  }
143  std::multiset<openvdb::Index64>::iterator voxelIter =
144  mVoxelSet.begin(), voxelEnd = mVoxelSet.end();
145  typename GridT::ValueOnCIter valueIter = grid.cbeginValueOn();
146  mPointCount = 0;//addPoint increments this counter
147  size_t interruptCount = 0;
148  for (openvdb::Index64 n=valueIter.getVoxelCount(); voxelIter != voxelEnd; ++voxelIter) {
149  //only check interrupter for every 32'th particle
150  if (!(interruptCount++ & (1<<5)-1) && util::wasInterrupted(mInterrupter)) return;
151  while ( n <= *voxelIter ) {
152  ++valueIter;
153  n += valueIter.getVoxelCount();
154  }
155  if (valueIter.isVoxelValue()) {// a majorty is expected to be voxels
156  const openvdb::Coord min = valueIter.getCoord();
157  const openvdb::Vec3R dmin(min.x()-0.5, min.y()-0.5, min.z()-0.5);
158  this->addPoint(grid, dmin);
159  } else {// tiles contain multiple (virtual) voxels
160  valueIter.getBoundingBox(bbox);
161  const openvdb::Coord size(bbox.extents());
162  const openvdb::Vec3R dmin(bbox.min().x()-0.5,
163  bbox.min().y()-0.5,
164  bbox.min().z()-0.5);
165  this->addPoint(grid, dmin, size);
166  }
167  }
168  if (mInterrupter) mInterrupter->end();
169  }
170 
171  // The following methods should only be called after the
172  // the operator() method was called
173  void print(const std::string &name, std::ostream& os = std::cout) const
174  {
175  os << "Uniformely scattered " << mPointCount << " points into " << mVoxelCount
176  << " active voxels in \"" << name << "\" corresponding to "
177  << mPointsPerVolume << " points per volume." << std::endl;
178  }
179 
180  int getPointCount() const { return mPointCount; }
181  float getPointsPerVolume() const { return mPointsPerVolume; }
182  openvdb::Index64 getVoxelCount() const { return mVoxelCount; }
183 
184 private:
185  PointAccessorType& mPoints;
186  InterruptType* mInterrupter;
187  int mPointCount;
188  float mPointsPerVolume;
189  openvdb::Index64 mVoxelCount;
190  RandomGenerator& mRandomGen;
191  boost::uniform_01<double> mRandom;
192 
193  double getRand() { return mRandom(mRandomGen); }
194 
195  template <typename GridT>
196  inline void addPoint(const GridT &grid, const openvdb::Vec3R &pos, const openvdb::Vec3R &delta)
197  {
198  mPoints.add(grid.indexToWorld(pos + delta));
199  ++mPointCount;
200  }
201  template <typename GridT>
202  inline void addPoint(const GridT &grid, const openvdb::Vec3R &dmin)
203  {
204  this->addPoint(grid, dmin, openvdb::Vec3R(getRand(),getRand(),getRand()));
205  }
206  template <typename GridT>
207  inline void addPoint(const GridT &grid, const openvdb::Vec3R &dmin, const openvdb::Coord &size)
208  {
209  const openvdb::Vec3R d(size.x()*getRand(),size.y()*getRand(),size.z()*getRand());
210  this->addPoint(grid, dmin, d);
211  }
212 }; // class UniformPointScatter
213 
214 
222 template<typename PointAccessorType,
223  typename RandomGenerator,
224  typename InterruptType = openvdb::util::NullInterrupter>
226 {
227 public:
228  NonUniformPointScatter(PointAccessorType& points,
229  float pointsPerVolume,
230  RandomGenerator& randGen,
231  InterruptType* interrupt = NULL):
232  mPoints(points),
233  mInterrupter(interrupt),
234  mPointCount(0),
235  mPointsPerVolume(pointsPerVolume),//note this is NOT the local point density
236  mVoxelCount(0),
237  mRandomGen(randGen)
238  {
239  }
240 
242  template<typename GridT>
243  void operator()(const GridT& grid)
244  {
245  mVoxelCount = grid.activeVoxelCount();
246  if (mVoxelCount == 0) return;//throw std::runtime_error("No voxels in which to scatter points!");
247  if (mInterrupter) mInterrupter->start("Non-uniform scattering with local point density");
248  const openvdb::Vec3d dim = grid.voxelSize();
249  const double volumePerVoxel = dim[0]*dim[1]*dim[2],
250  pointsPerVoxel = mPointsPerVolume * volumePerVoxel;
251  openvdb::CoordBBox bbox;
252  size_t interruptCount = 0;
253  for (typename GridT::ValueOnCIter iter = grid.cbeginValueOn(); iter; ++iter) {
254  //only check interrupter for every 32'th active value
255  if (!(interruptCount++ & (1<<5)-1) && util::wasInterrupted(mInterrupter)) return;
256  const double d = (*iter) * pointsPerVoxel * iter.getVoxelCount();
257  const int n = int(d);
258  if (iter.isVoxelValue()) { // a majorty is expected to be voxels
259  const openvdb::Coord min = iter.getCoord();
260  const openvdb::Vec3R dmin(min.x()-0.5, min.y()-0.5, min.z()-0.5);
261  for (int i = 0; i < n; ++i) this->addPoint(grid, dmin);
262  if (getRand() < (d - n)) this->addPoint(grid, dmin);
263  } else { // tiles contain multiple (virtual) voxels
264  iter.getBoundingBox(bbox);
265  const openvdb::Coord size(bbox.extents());
266  const openvdb::Vec3R dmin(bbox.min().x()-0.5,
267  bbox.min().y()-0.5,
268  bbox.min().z()-0.5);
269  for (int i = 0; i < n; ++i) this->addPoint(grid, dmin, size);
270  if (getRand() < (d - n)) this->addPoint(grid, dmin, size);
271  }
272  }//loop over the active values
273  if (mInterrupter) mInterrupter->end();
274  }
275 
276  // The following methods should only be called after the
277  // the operator() method was called
278  void print(const std::string &name, std::ostream& os = std::cout) const
279  {
280  os << "Non-uniformely scattered " << mPointCount << " points into " << mVoxelCount
281  << " active voxels in \"" << name << "\"." << std::endl;
282  }
283 
284  int getPointCount() const { return mPointCount; }
285  openvdb::Index64 getVoxelCount() const { return mVoxelCount; }
286 
287 private:
288  PointAccessorType& mPoints;
289  InterruptType* mInterrupter;
290  int mPointCount;
291  float mPointsPerVolume;
292  openvdb::Index64 mVoxelCount;
293  RandomGenerator& mRandomGen;
294  boost::uniform_01<double> mRandom;
295 
296  double getRand() { return mRandom(mRandomGen); }
297 
298  template <typename GridT>
299  inline void addPoint(const GridT &grid, const openvdb::Vec3R &pos, const openvdb::Vec3R &delta)
300  {
301  mPoints.add(grid.indexToWorld(pos + delta));
302  ++mPointCount;
303  }
304  template <typename GridT>
305  inline void addPoint(const GridT &grid, const openvdb::Vec3R &dmin)
306  {
307  this->addPoint(grid, dmin, openvdb::Vec3R(getRand(),getRand(),getRand()));
308  }
309  template <typename GridT>
310  inline void addPoint(const GridT &grid, const openvdb::Vec3R &dmin, const openvdb::Coord &size)
311  {
312  const openvdb::Vec3R d(size.x()*getRand(),size.y()*getRand(),size.z()*getRand());
313  this->addPoint(grid, dmin, d);
314  }
315 
316 }; // class NonUniformPointScatter
317 
318 } // namespace tools
319 } // namespace OPENVDB_VERSION_NAME
320 } // namespace openvdb
321 
322 #endif // OPENVDB_TOOLS_POINT_SCATTER_HAS_BEEN_INCLUDED
323 
324 // Copyright (c) 2012-2013 DreamWorks Animation LLC
325 // All rights reserved. This software is distributed under the
326 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
Type Round(Type x)
Return x rounded down to the nearest integer.
Definition: Math.h:698
void operator()(const GridT &grid)
This is the main functor method implementing the actual scattering of points.
Definition: PointScatter.h:117
UniformPointScatter(PointAccessorType &points, int pointCount, RandomGenerator &randGen, InterruptType *interrupt=NULL)
Definition: PointScatter.h:90
void operator()(const GridT &grid)
This is the main functor method implementing the actual scattering of points.
Definition: PointScatter.h:243
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
openvdb::Index64 getVoxelCount() const
Definition: PointScatter.h:182
void print(const std::string &name, std::ostream &os=std::cout) const
Definition: PointScatter.h:278
uint64_t Index64
Definition: Types.h:56
#define OPENVDB_VERSION_NAME
Definition: version.h:45
float getPointsPerVolume() const
Definition: PointScatter.h:181
void print(const std::string &name, std::ostream &os=std::cout) const
Definition: PointScatter.h:173
UniformPointScatter(PointAccessorType &points, float pointsPerVolume, RandomGenerator &randGen, InterruptType *interrupt=NULL)
Definition: PointScatter.h:102
Vec3< double > Vec3d
Definition: Vec3.h:625
int getPointCount() const
Definition: PointScatter.h:284
NonUniformPointScatter(PointAccessorType &points, float pointsPerVolume, RandomGenerator &randGen, InterruptType *interrupt=NULL)
Definition: PointScatter.h:228
The two point scatters UniformPointScatter and NonUniformPointScatter depend on the following two cla...
Definition: PointScatter.h:87
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:67
openvdb::Index64 getVoxelCount() const
Definition: PointScatter.h:285
Non-uniform scatters of point in the active voxels. The local point count is implicitly defined as a ...
Definition: PointScatter.h:225
int getPointCount() const
Definition: PointScatter.h:180