OpenVDB  2.1.0
ParticlesToLevelSet.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 //
96 
97 #ifndef OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
98 #define OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
99 
100 #include <tbb/parallel_reduce.h>
101 #include <tbb/blocked_range.h>
102 #include <boost/bind.hpp>
103 #include <boost/function.hpp>
104 #include <boost/type_traits/is_floating_point.hpp>
105 #include <boost/utility/enable_if.hpp>
106 #include <boost/mpl/if.hpp>
107 #include <openvdb/util/Util.h>
108 #include <openvdb/Types.h>
109 #include <openvdb/Grid.h>
110 #include <openvdb/math/Math.h>
111 #include <openvdb/math/Transform.h>
112 #include <openvdb/util/NullInterrupter.h>
113 #include "Composite.h" // for csgUnion()
114 
115 namespace openvdb {
117 namespace OPENVDB_VERSION_NAME {
118 namespace tools {
119 
120 
121 // This is a simple type that combines a distance value and a particle
122 // attribute. It's required for attribute transfer which is performed
123 // in the ParticlesToLevelSet::Raster memberclass defined below.
124 namespace local {template <typename VisibleT, typename BlindT> class BlindData;}
125 
126 template<typename SdfGridT,
127  typename AttributeT = void,
128  typename InterrupterT = util::NullInterrupter>
130 {
131 public:
132 
133  typedef typename boost::is_void<AttributeT>::type DisableT;
134  typedef InterrupterT InterrupterType;
135 
136  typedef SdfGridT SdfGridType;
137  typedef typename SdfGridT::ValueType SdfType;
138 
139  typedef typename boost::mpl::if_<DisableT, size_t, AttributeT>::type AttType;
140  typedef typename SdfGridT::template ValueConverter<AttType>::Type AttGridType;
141 
142  BOOST_STATIC_ASSERT(boost::is_floating_point<SdfType>::value);
143 
165  explicit ParticlesToLevelSet(SdfGridT& grid, InterrupterT* interrupt = NULL);
166 
168  ~ParticlesToLevelSet() { delete mBlindGrid; }
169 
177  void finalize();
178 
184  typename AttGridType::Ptr attributeGrid() { return mAttGrid; }
185 
187  Real getVoxelSize() const { return mDx; }
188 
190  Real getHalfWidth() const { return mHalfWidth; }
191 
193  Real getRmin() const { return mRmin; }
195  Real getRmax() const { return mRmax; }
196 
198  bool ignoredParticles() const { return mMinCount>0 || mMaxCount>0; }
200  size_t getMinCount() const { return mMinCount; }
202  size_t getMaxCount() const { return mMaxCount; }
203 
205  void setRmin(Real Rmin) { mRmin = math::Max(Real(0),Rmin); }
207  void setRmax(Real Rmax) { mRmax = math::Max(mRmin,Rmax); }
208 
210  int getGrainSize() const { return mGrainSize; }
213  void setGrainSize(int grainSize) { mGrainSize = grainSize; }
214 
219  template <typename ParticleListT>
220  void rasterizeSpheres(const ParticleListT& pa);
221 
227  template <typename ParticleListT>
228  void rasterizeSpheres(const ParticleListT& pa, Real radius);
229 
246  template <typename ParticleListT>
247  void rasterizeTrails(const ParticleListT& pa, Real delta=1.0);
248 
249 private:
250 
251  typedef local::BlindData<SdfType, AttType> BlindType;
252  typedef typename SdfGridT::template ValueConverter<BlindType>::Type BlindGridType;
253 
255  template<typename ParticleListT, typename GridT> struct Raster;
256 
257  SdfGridType* mSdfGrid;
258  typename AttGridType::Ptr mAttGrid;
259  BlindGridType* mBlindGrid;
260  InterrupterT* mInterrupter;
261  Real mDx, mHalfWidth;
262  Real mRmin, mRmax;//ignore particles outside this range of radii in voxel
263  size_t mMinCount, mMaxCount;//counters for ignored particles!
264  int mGrainSize;
265 
266 };//end of ParticlesToLevelSet class
267 
268 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
269 inline ParticlesToLevelSet<SdfGridT, AttributeT, InterrupterT>::
270 ParticlesToLevelSet(SdfGridT& grid, InterrupterT* interrupter) :
271  mSdfGrid(&grid),
272  mBlindGrid(NULL),
273  mInterrupter(interrupter),
274  mDx(grid.voxelSize()[0]),
275  mHalfWidth(grid.background()/mDx),
276  mRmin(1.5),// corresponds to the Nyquist grid sampling frequency
277  mRmax(100.0),// corresponds to a huge particle (probably too large!)
278  mMinCount(0),
279  mMaxCount(0),
280  mGrainSize(1)
281 {
282  if (!mSdfGrid->hasUniformVoxels() ) {
284  "ParticlesToLevelSet only supports uniform voxels!");
285  }
286  if (mSdfGrid->getGridClass() != GRID_LEVEL_SET) {
288  "ParticlesToLevelSet only supports level sets!"
289  "\nUse Grid::setGridClass(openvdb::GRID_LEVEL_SET)");
290  }
291 
292  if (!DisableT::value) {
293  mBlindGrid = new BlindGridType(BlindType(grid.background()));
294  mBlindGrid->setTransform(mSdfGrid->transform().copy());
295  }
296 }
297 
298 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
299 template <typename ParticleListT>
301 rasterizeSpheres(const ParticleListT& pa)
302 {
303  if (DisableT::value) {
304  Raster<ParticleListT, SdfGridT> r(*this, mSdfGrid, pa);
305  r.rasterizeSpheres();
306  } else {
307  Raster<ParticleListT, BlindGridType> r(*this, mBlindGrid, pa);
308  r.rasterizeSpheres();
309  }
310 }
311 
312 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
313 template <typename ParticleListT>
315 rasterizeSpheres(const ParticleListT& pa, Real radius)
316 {
317  if (DisableT::value) {
318  Raster<ParticleListT, SdfGridT> r(*this, mSdfGrid, pa);
319  r.rasterizeSpheres(radius/mDx);
320  } else {
321  Raster<ParticleListT, BlindGridType> r(*this, mBlindGrid, pa);
322  r.rasterizeSpheres(radius/mDx);
323  }
324 }
325 
326 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
327 template <typename ParticleListT>
329 rasterizeTrails(const ParticleListT& pa, Real delta)
330 {
331  if (DisableT::value) {
332  Raster<ParticleListT, SdfGridT> r(*this, mSdfGrid, pa);
333  r.rasterizeTrails(delta);
334  } else {
335  Raster<ParticleListT, BlindGridType> r(*this, mBlindGrid, pa);
336  r.rasterizeTrails(delta);
337  }
338 }
339 
340 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
341 inline void
343 {
344  if (mBlindGrid==NULL) return;
345 
346  typedef typename SdfGridType::TreeType SdfTreeT;
347  typedef typename AttGridType::TreeType AttTreeT;
348  typedef typename BlindGridType::TreeType BlindTreeT;
349  // Use topology copy constructors since output grids have the same topology as mBlindDataGrid
350  const BlindTreeT& tree = mBlindGrid->tree();
351 
352  // New level set tree
353  typename SdfTreeT::Ptr sdfTree(new SdfTreeT(
354  tree, tree.background().visible(), openvdb::TopologyCopy()));
355 
356  // Note this overwrites any existing attribute grids!
357  typename AttTreeT::Ptr attTree(new AttTreeT(
358  tree, tree.background().blind(), openvdb::TopologyCopy()));
359  mAttGrid = typename AttGridType::Ptr(new AttGridType(attTree));
360  mAttGrid->setTransform(mBlindGrid->transform().copy());
361 
362  // Extract the level set and IDs from mBlindDataGrid. We will
363  // explore the fact that by design active values always live
364  // at the leaf node level, i.e. no active tiles exist in level sets
365  typedef typename BlindTreeT::LeafCIter LeafIterT;
366  typedef typename BlindTreeT::LeafNodeType LeafT;
367  typedef typename SdfTreeT::LeafNodeType SdfLeafT;
368  typedef typename AttTreeT::LeafNodeType AttLeafT;
369  for (LeafIterT n = tree.cbeginLeaf(); n; ++n) {
370  const LeafT& leaf = *n;
371  const openvdb::Coord xyz = leaf.origin();
372  // Get leafnodes that were allocated during topology contruction!
373  SdfLeafT* sdfLeaf = sdfTree->probeLeaf(xyz);
374  AttLeafT* attLeaf = attTree->probeLeaf(xyz);
375  for (typename LeafT::ValueOnCIter m=leaf.cbeginValueOn(); m; ++m) {
376  // Use linear offset (vs coordinate) access for better performance!
377  const openvdb::Index k = m.pos();
378  const BlindType& v = *m;
379  sdfLeaf->setValueOnly(k, v.visible());
380  attLeaf->setValueOnly(k, v.blind());
381  }
382  }
383  sdfTree->signedFloodFill();//required since we only transferred active voxels!
384 
385  if (mSdfGrid->empty()) {
386  mSdfGrid->setTree(sdfTree);
387  } else {
388  tools::csgUnion(mSdfGrid->tree(), *sdfTree, /*prune=*/true);
389  }
390 }
391 
393 
394 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
395 template<typename ParticleListT, typename GridT>
396 struct ParticlesToLevelSet<SdfGridT, AttributeT, InterrupterT>::Raster
397 {
398  typedef typename boost::is_void<AttributeT>::type DisableT;
399  typedef ParticlesToLevelSet<SdfGridT, AttributeT, InterrupterT> ParticlesToLevelSetT;
400  typedef typename ParticlesToLevelSetT::SdfType SdfT;//type of signed distance values
401  typedef typename ParticlesToLevelSetT::AttType AttT;//type of particle attribute
402  typedef typename GridT::ValueType ValueT;
403  typedef typename GridT::Accessor AccessorT;
404 
406  Raster(ParticlesToLevelSetT& parent, GridT* grid, const ParticleListT& particles)
407  : mParent(parent),
408  mParticles(particles),
409  mGrid(grid),
410  mMap(*(mGrid->transform().baseMap())),
411  mMinCount(0),
412  mMaxCount(0),
413  mOwnsGrid(false)
414  {
415  }
416 
418  Raster(Raster& other, tbb::split)
419  : mParent(other.mParent),
420  mParticles(other.mParticles),
421  mGrid(new GridT(*other.mGrid, openvdb::ShallowCopy())),
422  mMap(other.mMap),
423  mMinCount(0),
424  mMaxCount(0),
425  mTask(other.mTask),
426  mOwnsGrid(true)
427  {
428  mGrid->newTree();
429  }
430 
431  virtual ~Raster() { if (mOwnsGrid) delete mGrid; }
432 
435  void rasterizeSpheres()
436  {
437  mMinCount = mMaxCount = 0;
438  if (mParent.mInterrupter) {
439  mParent.mInterrupter->start("Rasterizing particles to level set using spheres");
440  }
441  mTask = boost::bind(&Raster::rasterSpheres, _1, _2);
442  this->cook();
443  if (mParent.mInterrupter) mParent.mInterrupter->end();
444  }
448  void rasterizeSpheres(Real radius)
449  {
450  mMinCount = radius < mParent.mRmin ? mParticles.size() : 0;
451  mMaxCount = radius > mParent.mRmax ? mParticles.size() : 0;
452  if (mMinCount>0 || mMaxCount>0) {//skipping all particles!
453  mParent.mMinCount = mMinCount;
454  mParent.mMaxCount = mMaxCount;
455  } else {
456  if (mParent.mInterrupter) {
457  mParent.mInterrupter->start(
458  "Rasterizing particles to level set using const spheres");
459  }
460  mTask = boost::bind(&Raster::rasterFixedSpheres, _1, _2, SdfT(radius));
461  this->cook();
462  if (mParent.mInterrupter) mParent.mInterrupter->end();
463  }
464  }
479  void rasterizeTrails(Real delta=1.0)
480  {
481  mMinCount = mMaxCount = 0;
482  if (mParent.mInterrupter) {
483  mParent.mInterrupter->start("Rasterizing particles to level set using trails");
484  }
485  mTask = boost::bind(&Raster::rasterTrails, _1, _2, SdfT(delta));
486  this->cook();
487  if (mParent.mInterrupter) mParent.mInterrupter->end();
488  }
489 
491  void operator()(const tbb::blocked_range<size_t>& r)
492  {
493  assert(mTask);
494  mTask(this, r);
495  mParent.mMinCount = mMinCount;
496  mParent.mMaxCount = mMaxCount;
497  }
498 
500  void join(Raster& other)
501  {
502  tools::csgUnion(*mGrid, *other.mGrid, /*prune=*/true);
503  mMinCount += other.mMinCount;
504  mMaxCount += other.mMaxCount;
505  }
506 private:
508  Raster& operator=(const Raster& other) { return *this; }
509 
511  bool ignoreParticle(SdfT R)
512  {
513  if (R < mParent.mRmin) {// below the cutoff radius
514  ++mMinCount;
515  return true;
516  }
517  if (R > mParent.mRmax) {// above the cutoff radius
518  ++mMaxCount;
519  return true;
520  }
521  return false;
522  }
527  void rasterSpheres(const tbb::blocked_range<size_t>& r)
528  {
529  AccessorT acc = mGrid->getAccessor(); // local accessor
530  bool run = true;
531  const SdfT invDx = 1/mParent.mDx;
532  AttT att;
533  Vec3R pos;
534  Real rad;
535  for (Index32 id = r.begin(), e=r.end(); run && id != e; ++id) {
536  mParticles.getPosRad(id, pos, rad);
537  const SdfT R = invDx * rad;// in voxel units
538  if (this->ignoreParticle(R)) continue;
539  const Vec3R P = mMap.applyInverseMap(pos);
540  this->getAtt<DisableT>(id, att);
541  run = this->makeSphere(P, R, att, acc);
542  }//end loop over particles
543  }
548  void rasterFixedSpheres(const tbb::blocked_range<size_t>& r, SdfT R)
549  {
550  const SdfT dx = mParent.mDx, w = mParent.mHalfWidth;// in voxel units
551  AccessorT acc = mGrid->getAccessor(); // local accessor
552  const ValueT inside = -mGrid->background();
553  const SdfT max = R + w;// maximum distance in voxel units
554  const SdfT max2 = math::Pow2(max);//square of maximum distance in voxel units
555  const SdfT min2 = math::Pow2(math::Max(SdfT(0), R - w));//square of minimum distance
556  ValueT v;
557  size_t count = 0;
558  AttT att;
559  Vec3R pos;
560  for (size_t id = r.begin(), e=r.end(); id != e; ++id) {
561  this->getAtt<DisableT>(id, att);
562  mParticles.getPos(id, pos);
563  const Vec3R P = mMap.applyInverseMap(pos);
564  const Coord a(math::Floor(P[0]-max),math::Floor(P[1]-max),math::Floor(P[2]-max));
565  const Coord b(math::Ceil( P[0]+max),math::Ceil( P[1]+max),math::Ceil( P[2]+max));
566  for ( Coord c = a; c.x() <= b.x(); ++c.x() ) {
567  //only check interrupter every 32'th scan in x
568  if (!(count++ & (1<<5)-1) && util::wasInterrupted(mParent.mInterrupter)) {
569  tbb::task::self().cancel_group_execution();
570  return;
571  }
572  SdfT x2 = math::Pow2( c.x() - P[0] );
573  for ( c.y() = a.y(); c.y() <= b.y(); ++c.y() ) {
574  SdfT x2y2 = x2 + math::Pow2( c.y() - P[1] );
575  for ( c.z() = a.z(); c.z() <= b.z(); ++c.z() ) {
576  SdfT x2y2z2 = x2y2 + math::Pow2(c.z()- P[2]);//square distance from c to P
577  if ( x2y2z2 >= max2 || (!acc.probeValue(c,v) && v<ValueT(0)) )
578  continue;//outside narrow band of particle or inside existing level set
579  if ( x2y2z2 <= min2 ) {//inside narrow band of the particle.
580  acc.setValueOff(c, inside);
581  continue;
582  }
583  // convert signed distance from voxel units to world units
584  const ValueT d=Merge(dx*(math::Sqrt(x2y2z2) - R), att);
585  if (d < v) acc.setValue(c, d);//CSG union
586  }//end loop over z
587  }//end loop over y
588  }//end loop over x
589  }//end loop over particles
590  }
595  void rasterTrails(const tbb::blocked_range<size_t>& r, SdfT delta)
596  {
597  AccessorT acc = mGrid->getAccessor(); // local accessor
598  bool run = true;
599  AttT att;
600  Vec3R pos, vel;
601  Real rad;
602  const Vec3R origin = mMap.applyInverseMap(Vec3R(0,0,0));
603  const SdfT Rmin = mParent.mRmin, invDx = 1/mParent.mDx;
604  for (size_t id = r.begin(), e=r.end(); run && id != e; ++id) {
605  mParticles.getPosRadVel(id, pos, rad, vel);
606  const SdfT R0 = invDx*rad;
607  if (this->ignoreParticle(R0)) continue;
608  this->getAtt<DisableT>(id, att);
609  const Vec3R P0 = mMap.applyInverseMap(pos);
610  const Vec3R V = mMap.applyInverseMap(vel) - origin;//exclude translation
611  const SdfT speed = V.length(), inv_speed=1.0/speed;
612  const Vec3R N = -V*inv_speed;// inverse normalized direction
613  Vec3R P = P0;// local position of instance
614  SdfT R = R0, d=0;// local radius and length of trail
615  for (size_t m=0; run && d <= speed ; ++m) {
616  run = this->makeSphere(P, R, att, acc);
617  P += 0.5*delta*R*N;// adaptive offset along inverse velocity direction
618  d = (P-P0).length();// current length of trail
619  R = R0-(R0-Rmin)*d*inv_speed;// R = R0 -> mRmin(e.g. 1.5)
620  }//end loop over sphere instances
621  }//end loop over particles
622  }
623 
624  void cook()
625  {
626  if (mParent.mGrainSize>0) {
627  tbb::parallel_reduce(
628  tbb::blocked_range<size_t>(0,mParticles.size(),mParent.mGrainSize), *this);
629  } else {
630  (*this)(tbb::blocked_range<size_t>(0, mParticles.size()));
631  }
632  }
633 
649  bool makeSphere(const Vec3R &P, SdfT R, const AttT& att, AccessorT& acc)
650  {
651  const ValueT inside = -mGrid->background();
652  const SdfT dx = mParent.mDx, w = mParent.mHalfWidth;
653  const SdfT max = R + w;// maximum distance in voxel units
654  const Coord a(math::Floor(P[0]-max),math::Floor(P[1]-max),math::Floor(P[2]-max));
655  const Coord b(math::Ceil( P[0]+max),math::Ceil( P[1]+max),math::Ceil( P[2]+max));
656  const SdfT max2 = math::Pow2(max);//square of maximum distance in voxel units
657  const SdfT min2 = math::Pow2(math::Max(SdfT(0), R - w));//square of minimum distance
658  ValueT v;
659  size_t count = 0;
660  for ( Coord c = a; c.x() <= b.x(); ++c.x() ) {
661  //only check interrupter every 32'th scan in x
662  if (!(count++ & (1<<5)-1) && util::wasInterrupted(mParent.mInterrupter)) {
663  tbb::task::self().cancel_group_execution();
664  return false;
665  }
666  SdfT x2 = math::Pow2( c.x() - P[0] );
667  for ( c.y() = a.y(); c.y() <= b.y(); ++c.y() ) {
668  SdfT x2y2 = x2 + math::Pow2( c.y() - P[1] );
669  for ( c.z() = a.z(); c.z() <= b.z(); ++c.z() ) {
670  SdfT x2y2z2 = x2y2 + math::Pow2( c.z() - P[2] );//square distance from c to P
671  if ( x2y2z2 >= max2 || (!acc.probeValue(c,v) && v<ValueT(0)) )
672  continue;//outside narrow band of the particle or inside existing level set
673  if ( x2y2z2 <= min2 ) {//inside narrow band of the particle.
674  acc.setValueOff(c, inside);
675  continue;
676  }
677  // convert signed distance from voxel units to world units
678  //const ValueT d=dx*(math::Sqrt(x2y2z2) - R);
679  const ValueT d=Merge(dx*(math::Sqrt(x2y2z2) - R), att);
680  if (d < v) acc.setValue(c, d);//CSG union
681  }//end loop over z
682  }//end loop over y
683  }//end loop over x
684  return true;
685  }
686  typedef typename boost::function<void (Raster*, const tbb::blocked_range<size_t>&)> FuncType;
687 
688  template <typename DisableType>
689  typename boost::enable_if<DisableType>::type
690  getAtt(size_t, AttT&) const {;}
691 
692  template <typename DisableType>
693  typename boost::disable_if<DisableType>::type
694  getAtt(size_t n, AttT& a) const {mParticles.getAtt(n, a);}
695 
696  template <typename T>
697  typename boost::enable_if<boost::is_same<T,ValueT>, ValueT>::type
698  Merge(T s, const AttT&) const { return s; }
699 
700  template <typename T>
701  typename boost::disable_if<boost::is_same<T,ValueT>, ValueT>::type
702  Merge(T s, const AttT& a) const { return ValueT(s,a); }
703 
704  ParticlesToLevelSetT& mParent;
705  const ParticleListT& mParticles;//list of particles
706  GridT* mGrid;
707  const math::MapBase& mMap;
708  size_t mMinCount, mMaxCount;//counters for ignored particles!
709  FuncType mTask;
710  const bool mOwnsGrid;
711 };//end of Raster struct
712 
713 
715 
716 namespace local {
717 // This is a simple type that combines a distance value and a particle
718 // attribute. It's required for attribute transfer which is defined in the
719 // Raster class above.
720 template <typename VisibleT, typename BlindT>
721 class BlindData
722 {
723  public:
724  typedef VisibleT type;
725  typedef VisibleT VisibleType;
726  typedef BlindT BlindType;
727  explicit BlindData() {}
728  explicit BlindData(VisibleT v) : mVisible(v) {}
729  BlindData(VisibleT v, BlindT b) : mVisible(v), mBlind(b) {}
731  {
732  mVisible = rhs.mVisible;
733  mBlind = rhs.mBlind;
734  return *this;
735  }
736  const VisibleT& visible() const { return mVisible; }
737  const BlindT& blind() const { return mBlind; }
738  bool operator==(const BlindData& rhs) const { return mVisible == rhs.mVisible; }
739  bool operator< (const BlindData& rhs) const { return mVisible < rhs.mVisible; };
740  bool operator> (const BlindData& rhs) const { return mVisible > rhs.mVisible; };
741  BlindData operator+(const BlindData& rhs) const { return BlindData(mVisible + rhs.mVisible); };
742  BlindData operator+(const VisibleT& rhs) const { return BlindData(mVisible + rhs); };
743  BlindData operator-(const BlindData& rhs) const { return BlindData(mVisible - rhs.mVisible); };
744  BlindData operator-() const { return BlindData(-mVisible, mBlind); }
745 protected:
746  VisibleT mVisible;
747  BlindT mBlind;
748 };
749 // Required by several of the tree nodes
750 template <typename VisibleT, typename BlindT>
751 inline std::ostream& operator<<(std::ostream& ostr, const BlindData<VisibleT, BlindT>& rhs)
752 {
753  ostr << rhs.visible();
754  return ostr;
755 }
756 // Required by math::Abs
757 template <typename VisibleT, typename BlindT>
759 {
760  return BlindData<VisibleT, BlindT>(math::Abs(x.visible()), x.blind());
761 }
762 }// local namespace
763 
765 
766 } // namespace tools
767 } // namespace OPENVDB_VERSION_NAME
768 } // namespace openvdb
769 
770 #endif // OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
771 
772 // Copyright (c) 2012-2013 DreamWorks Animation LLC
773 // All rights reserved. This software is distributed under the
774 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
Real getRmin() const
Return the smallest radius allowed in voxel units.
Definition: ParticlesToLevelSet.h:193
void setGrainSize(int grainSize)
Set the grain-size used for multi-threading.
Definition: ParticlesToLevelSet.h:213
VisibleT type
Definition: ParticlesToLevelSet.h:724
BlindData & operator=(const BlindData &rhs)
Definition: ParticlesToLevelSet.h:730
const MapT & mMap
Definition: GridOperators.h:384
int Floor(float x)
Return the floor of x.
Definition: Math.h:727
math::Vec3< Real > Vec3R
Definition: Types.h:74
BlindData operator+(const VisibleT &rhs) const
Definition: ParticlesToLevelSet.h:742
Functions to efficiently perform various compositing operations on grids.
VisibleT mVisible
Definition: ParticlesToLevelSet.h:746
bool operator<(const BlindData &rhs) const
Definition: ParticlesToLevelSet.h:739
const VisibleT & visible() const
Definition: ParticlesToLevelSet.h:736
bool ignoredParticles() const
Return true if any particles were ignored due to their size.
Definition: ParticlesToLevelSet.h:198
Definition: Types.h:137
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
int32_t Abs(int32_t i)
Return the absolute value of the given quantity.
Definition: Math.h:253
void setRmin(Real Rmin)
set the smallest radius allowed in voxel units
Definition: ParticlesToLevelSet.h:205
Type Pow2(Type x)
Return .
Definition: Math.h:467
Index32 Index
Definition: Types.h:56
BlindData()
Definition: ParticlesToLevelSet.h:727
int getGrainSize() const
Rreturn the grain-size used for multi-threading.
Definition: ParticlesToLevelSet.h:210
Real getHalfWidth() const
Return the half-width of the narrow band in voxel units.
Definition: ParticlesToLevelSet.h:190
Definition: ParticlesToLevelSet.h:129
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:655
Definition: Types.h:343
boost::mpl::if_< DisableT, size_t, AttributeT >::type AttType
Definition: ParticlesToLevelSet.h:139
Definition: Exceptions.h:86
void setRmax(Real Rmax)
set the largest radius allowed in voxel units
Definition: ParticlesToLevelSet.h:207
#define OPENVDB_VERSION_NAME
Definition: version.h:45
BlindT BlindType
Definition: ParticlesToLevelSet.h:726
BlindData< VisibleT, BlindT > Abs(const BlindData< VisibleT, BlindT > &x)
Definition: ParticlesToLevelSet.h:758
size_t getMaxCount() const
Return number of large particles that were ignore due to Rmax.
Definition: ParticlesToLevelSet.h:202
BlindData operator+(const BlindData &rhs) const
Definition: ParticlesToLevelSet.h:741
SdfGridT::ValueType SdfType
Definition: ParticlesToLevelSet.h:137
uint32_t Index32
Definition: Types.h:54
const BlindT & blind() const
Definition: ParticlesToLevelSet.h:737
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
InterrupterT InterrupterType
Definition: ParticlesToLevelSet.h:134
BlindData operator-() const
Definition: ParticlesToLevelSet.h:744
OPENVDB_STATIC_SPECIALIZATION void csgUnion(GridOrTreeT &a, GridOrTreeT &b, bool prune=true)
Given two level set grids, replace the A grid with the union of A and B.
Definition: Composite.h:510
BlindData(VisibleT v, BlindT b)
Definition: ParticlesToLevelSet.h:729
~ParticlesToLevelSet()
Destructor.
Definition: ParticlesToLevelSet.h:168
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:52
void finalize()
This methods syncs up the level set and attribute grids and therefore needs to be called before any o...
Definition: ParticlesToLevelSet.h:342
SdfGridT SdfGridType
Definition: ParticlesToLevelSet.h:136
double Real
Definition: Types.h:62
int Ceil(float x)
Return the ceiling of x.
Definition: Math.h:735
Real getVoxelSize() const
Return the size of a voxel in world units.
Definition: ParticlesToLevelSet.h:187
VisibleT VisibleType
Definition: ParticlesToLevelSet.h:725
BlindT mBlind
Definition: ParticlesToLevelSet.h:747
Definition: Types.h:346
bool operator>(const BlindData &rhs) const
Definition: ParticlesToLevelSet.h:740
bool operator==(const BlindData &rhs) const
Definition: ParticlesToLevelSet.h:738
Definition: ParticlesToLevelSet.h:124
BlindData(VisibleT v)
Definition: ParticlesToLevelSet.h:728
boost::is_void< AttributeT >::type DisableT
Definition: ParticlesToLevelSet.h:133
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:67
Real getRmax() const
Return the largest radius allowed in voxel units.
Definition: ParticlesToLevelSet.h:195
SdfGridT::template ValueConverter< AttType >::Type AttGridType
Definition: ParticlesToLevelSet.h:140
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
size_t getMinCount() const
Return number of small particles that were ignore due to Rmin.
Definition: ParticlesToLevelSet.h:200
void rasterizeTrails(const ParticleListT &pa, Real delta=1.0)
Rasterize a trail per particle derived from their position, radius and velocity. Each trail is genera...
Definition: ParticlesToLevelSet.h:329
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition: Math.h:514
AttGridType::Ptr attributeGrid()
Return a shared pointer to the grid containing the (optional) attribute.
Definition: ParticlesToLevelSet.h:184
void rasterizeSpheres(const ParticleListT &pa)
Rasterize a sphere per particle derived from their position and radius. All spheres are CSG unioned...
Definition: ParticlesToLevelSet.h:301
BlindData operator-(const BlindData &rhs) const
Definition: ParticlesToLevelSet.h:743