OpenVDB  4.0.1
ParticlesToLevelSet.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2017 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 
97 
98 #ifndef OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
99 #define OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
100 
101 #include <tbb/parallel_reduce.h>
102 #include <tbb/blocked_range.h>
103 #include <boost/bind.hpp>
104 #include <boost/function.hpp>
105 #include <boost/type_traits/is_floating_point.hpp>
106 #include <boost/utility/enable_if.hpp>
107 #include <boost/mpl/if.hpp>
108 #include <openvdb/Types.h>
109 #include <openvdb/Grid.h>
110 #include <openvdb/math/Math.h>
111 #include <openvdb/math/Transform.h>
113 #include "Composite.h" // for csgUnion()
114 #include "PointPartitioner.h"
115 #include "Prune.h"
116 #include "SignedFloodFill.h"
117 
118 namespace openvdb {
120 namespace OPENVDB_VERSION_NAME {
121 namespace tools {
122 
123 namespace p2ls_internal {
124 // This is a simple type that combines a distance value and a particle
125 // attribute. It's required for attribute transfer which is performed
126 // in the ParticlesToLevelSet::Raster member class defined below.
127 template<typename VisibleT, typename BlindT> class BlindData;
128 }// namespace p2ls_internal
129 
130 
131 template<typename SdfGridT,
132  typename AttributeT = void,
133  typename InterrupterT = util::NullInterrupter>
135 {
136 public:
137  typedef typename boost::is_void<AttributeT>::type DisableT;
138  typedef InterrupterT InterrupterType;
139 
140  typedef SdfGridT SdfGridType;
141  typedef typename SdfGridT::ValueType SdfType;
142 
143  typedef typename boost::mpl::if_<DisableT, size_t, AttributeT>::type AttType;
144  typedef typename SdfGridT::template ValueConverter<AttType>::Type AttGridType;
145 
146  BOOST_STATIC_ASSERT(boost::is_floating_point<SdfType>::value);
147 
169  explicit ParticlesToLevelSet(SdfGridT& grid, InterrupterT* interrupt = nullptr);
170 
172  ~ParticlesToLevelSet() { delete mBlindGrid; }
173 
182  void finalize(bool prune = false);
183 
189  typename AttGridType::Ptr attributeGrid() { return mAttGrid; }
190 
192  Real getVoxelSize() const { return mDx; }
193 
195  Real getHalfWidth() const { return mHalfWidth; }
196 
198  Real getRmin() const { return mRmin; }
200  Real getRmax() const { return mRmax; }
201 
203  bool ignoredParticles() const { return mMinCount>0 || mMaxCount>0; }
205  size_t getMinCount() const { return mMinCount; }
207  size_t getMaxCount() const { return mMaxCount; }
208 
210  void setRmin(Real Rmin) { mRmin = math::Max(Real(0),Rmin); }
212  void setRmax(Real Rmax) { mRmax = math::Max(mRmin,Rmax); }
213 
215  int getGrainSize() const { return mGrainSize; }
218  void setGrainSize(int grainSize) { mGrainSize = grainSize; }
219 
224  template <typename ParticleListT>
225  void rasterizeSpheres(const ParticleListT& pa);
226 
232  template <typename ParticleListT>
233  void rasterizeSpheres(const ParticleListT& pa, Real radius);
234 
251  template <typename ParticleListT>
252  void rasterizeTrails(const ParticleListT& pa, Real delta=1.0);
253 
254 private:
256  typedef typename SdfGridT::template ValueConverter<BlindType>::Type BlindGridType;
257 
259  template<typename ParticleListT, typename GridT> struct Raster;
260 
261  SdfGridType* mSdfGrid;
262  typename AttGridType::Ptr mAttGrid;
263  BlindGridType* mBlindGrid;
264  InterrupterT* mInterrupter;
265  Real mDx, mHalfWidth;
266  Real mRmin, mRmax;//ignore particles outside this range of radii in voxel
267  size_t mMinCount, mMaxCount;//counters for ignored particles!
268  int mGrainSize;
269 
270 };//end of ParticlesToLevelSet class
271 
272 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
274 ParticlesToLevelSet(SdfGridT& grid, InterrupterT* interrupter) :
275  mSdfGrid(&grid),
276  mBlindGrid(nullptr),
277  mInterrupter(interrupter),
278  mDx(grid.voxelSize()[0]),
279  mHalfWidth(grid.background()/mDx),
280  mRmin(1.5),// corresponds to the Nyquist grid sampling frequency
281  mRmax(100.0),// corresponds to a huge particle (probably too large!)
282  mMinCount(0),
283  mMaxCount(0),
284  mGrainSize(1)
285 {
286  if (!mSdfGrid->hasUniformVoxels() ) {
288  "ParticlesToLevelSet only supports uniform voxels!");
289  }
290  if (mSdfGrid->getGridClass() != GRID_LEVEL_SET) {
292  "ParticlesToLevelSet only supports level sets!"
293  "\nUse Grid::setGridClass(openvdb::GRID_LEVEL_SET)");
294  }
295 
296  if (!DisableT::value) {
297  mBlindGrid = new BlindGridType(BlindType(grid.background()));
298  mBlindGrid->setTransform(mSdfGrid->transform().copy());
299  }
300 }
301 
302 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
303 template <typename ParticleListT>
305 rasterizeSpheres(const ParticleListT& pa)
306 {
307  if (DisableT::value) {
308  Raster<ParticleListT, SdfGridT> r(*this, mSdfGrid, pa);
309  r.rasterizeSpheres();
310  } else {
311  Raster<ParticleListT, BlindGridType> r(*this, mBlindGrid, pa);
312  r.rasterizeSpheres();
313  }
314 }
315 
316 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
317 template <typename ParticleListT>
319 rasterizeSpheres(const ParticleListT& pa, Real radius)
320 {
321  if (DisableT::value) {
322  Raster<ParticleListT, SdfGridT> r(*this, mSdfGrid, pa);
323  r.rasterizeSpheres(radius/mDx);
324  } else {
325  Raster<ParticleListT, BlindGridType> r(*this, mBlindGrid, pa);
326  r.rasterizeSpheres(radius/mDx);
327  }
328 }
329 
330 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
331 template <typename ParticleListT>
333 rasterizeTrails(const ParticleListT& pa, Real delta)
334 {
335  if (DisableT::value) {
336  Raster<ParticleListT, SdfGridT> r(*this, mSdfGrid, pa);
337  r.rasterizeTrails(delta);
338  } else {
339  Raster<ParticleListT, BlindGridType> r(*this, mBlindGrid, pa);
340  r.rasterizeTrails(delta);
341  }
342 }
343 
344 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
345 inline void
347 {
348  if (mBlindGrid == nullptr) {
349  if (prune) tools::pruneLevelSet(mSdfGrid->tree());
350  return;
351  } else {
352  if (prune) tools::prune(mBlindGrid->tree());
353  }
354 
355  typedef typename SdfGridType::TreeType SdfTreeT;
356  typedef typename AttGridType::TreeType AttTreeT;
357  typedef typename BlindGridType::TreeType BlindTreeT;
358  // Use topology copy constructors since output grids have the same topology as mBlindDataGrid
359  const BlindTreeT& tree = mBlindGrid->tree();
360 
361  // New level set tree
362  typename SdfTreeT::Ptr sdfTree(new SdfTreeT(
363  tree, tree.background().visible(), openvdb::TopologyCopy()));
364 
365  // Note this overwrites any existing attribute grids!
366  typename AttTreeT::Ptr attTree(new AttTreeT(
367  tree, tree.background().blind(), openvdb::TopologyCopy()));
368  mAttGrid = typename AttGridType::Ptr(new AttGridType(attTree));
369  mAttGrid->setTransform(mBlindGrid->transform().copy());
370 
371  // Extract the level set and IDs from mBlindDataGrid. We will
372  // explore the fact that by design active values always live
373  // at the leaf node level, i.e. level sets have no active tiles!
374  typedef typename BlindTreeT::LeafCIter LeafIterT;
375  typedef typename BlindTreeT::LeafNodeType LeafT;
376  typedef typename SdfTreeT::LeafNodeType SdfLeafT;
377  typedef typename AttTreeT::LeafNodeType AttLeafT;
378  for (LeafIterT n = tree.cbeginLeaf(); n; ++n) {
379  const LeafT& leaf = *n;
380  const openvdb::Coord xyz = leaf.origin();
381  // Get leafnodes that were allocated during topology construction!
382  SdfLeafT* sdfLeaf = sdfTree->probeLeaf(xyz);
383  AttLeafT* attLeaf = attTree->probeLeaf(xyz);
384  // Use linear offset (vs coordinate) access for better performance!
385  typename LeafT::ValueOnCIter m=leaf.cbeginValueOn();
386  if (!m) {//no active values in leaf node so copy everything
387  for (openvdb::Index k = 0; k!=LeafT::SIZE; ++k) {
388  const BlindType& v = leaf.getValue(k);
389  sdfLeaf->setValueOnly(k, v.visible());
390  attLeaf->setValueOnly(k, v.blind());
391  }
392  } else {//only copy active values (using flood fill for the inactive values)
393  for(; m; ++m) {
394  const openvdb::Index k = m.pos();
395  const BlindType& v = *m;
396  sdfLeaf->setValueOnly(k, v.visible());
397  attLeaf->setValueOnly(k, v.blind());
398  }
399  }
400  }
401 
402  tools::signedFloodFill(*sdfTree);//required since we only transferred active voxels!
403 
404  if (mSdfGrid->empty()) {
405  mSdfGrid->setTree(sdfTree);
406  } else {
407  tools::csgUnion(mSdfGrid->tree(), *sdfTree, /*prune=*/true);
408  }
409 }
410 
412 
413 template<typename SdfGridT, typename AttributeT, typename InterrupterT>
414 template<typename ParticleListT, typename GridT>
415 struct ParticlesToLevelSet<SdfGridT, AttributeT, InterrupterT>::Raster
416 {
417  typedef typename boost::is_void<AttributeT>::type DisableT;
418  typedef ParticlesToLevelSet<SdfGridT, AttributeT, InterrupterT> ParticlesToLevelSetT;
419  typedef typename ParticlesToLevelSetT::SdfType SdfT;//type of signed distance values
420  typedef typename ParticlesToLevelSetT::AttType AttT;//type of particle attribute
421  typedef typename GridT::ValueType ValueT;
422  typedef typename GridT::Accessor AccessorT;
423  typedef typename GridT::TreeType TreeT;
424  typedef typename TreeT::LeafNodeType LeafNodeT;
425  typedef PointPartitioner<Index32, LeafNodeT::LOG2DIM> PointPartitionerT;
426 
427 
429  Raster(ParticlesToLevelSetT& parent, GridT* grid, const ParticleListT& particles)
430  : mParent(parent)
431  , mParticles(particles)
432  , mGrid(grid)
433  , mMap(*(mGrid->transform().baseMap()))
434  , mMinCount(0)
435  , mMaxCount(0)
436  , mIsCopy(false)
437  {
438  mPointPartitioner = new PointPartitionerT();
439  mPointPartitioner->construct(particles, mGrid->transform());
440  }
441 
443  Raster(Raster& other, tbb::split)
444  : mParent(other.mParent)
445  , mParticles(other.mParticles)
446  , mGrid(new GridT(*other.mGrid, openvdb::ShallowCopy()))
447  , mMap(other.mMap)
448  , mMinCount(0)
449  , mMaxCount(0)
450  , mTask(other.mTask)
451  , mIsCopy(true)
452  , mPointPartitioner(other.mPointPartitioner)
453  {
454  mGrid->newTree();
455  }
456 
457  virtual ~Raster() {
458 
459  // Copies construct temporary grids that have to be deleted
460  // but the original has ownership of the bucket array
461  if (mIsCopy) {
462  delete mGrid;
463  } else {
464  delete mPointPartitioner;
465  }
466  }
467 
470  void rasterizeSpheres()
471  {
472  mMinCount = mMaxCount = 0;
473  if (mParent.mInterrupter) {
474  mParent.mInterrupter->start("Rasterizing particles to level set using spheres");
475  }
476  mTask = boost::bind(&Raster::rasterSpheres, _1, _2);
477  this->cook();
478  if (mParent.mInterrupter) mParent.mInterrupter->end();
479  }
483  void rasterizeSpheres(Real radius)
484  {
485  mMinCount = radius < mParent.mRmin ? mParticles.size() : 0;
486  mMaxCount = radius > mParent.mRmax ? mParticles.size() : 0;
487  if (mMinCount>0 || mMaxCount>0) {//skipping all particles!
488  mParent.mMinCount = mMinCount;
489  mParent.mMaxCount = mMaxCount;
490  } else {
491  if (mParent.mInterrupter) {
492  mParent.mInterrupter->start(
493  "Rasterizing particles to level set using const spheres");
494  }
495  mTask = boost::bind(&Raster::rasterFixedSpheres, _1, _2, SdfT(radius));
496  this->cook();
497  if (mParent.mInterrupter) mParent.mInterrupter->end();
498  }
499  }
514  void rasterizeTrails(Real delta=1.0)
515  {
516  mMinCount = mMaxCount = 0;
517  if (mParent.mInterrupter) {
518  mParent.mInterrupter->start("Rasterizing particles to level set using trails");
519  }
520  mTask = boost::bind(&Raster::rasterTrails, _1, _2, SdfT(delta));
521  this->cook();
522  if (mParent.mInterrupter) mParent.mInterrupter->end();
523  }
524 
526  void operator()(const tbb::blocked_range<size_t>& r)
527  {
528  assert(mTask);
529  mTask(this, r);
530  mParent.mMinCount = mMinCount;
531  mParent.mMaxCount = mMaxCount;
532  }
533 
535  void join(Raster& other)
536  {
537  tools::csgUnion(*mGrid, *other.mGrid, /*prune=*/true);
538  mMinCount += other.mMinCount;
539  mMaxCount += other.mMaxCount;
540  }
541 private:
543  Raster& operator=(const Raster&) { return *this; }
544 
546  bool ignoreParticle(SdfT R)
547  {
548  if (R < mParent.mRmin) {// below the cutoff radius
549  ++mMinCount;
550  return true;
551  }
552  if (R > mParent.mRmax) {// above the cutoff radius
553  ++mMaxCount;
554  return true;
555  }
556  return false;
557  }
562  void rasterSpheres(const tbb::blocked_range<size_t>& r)
563  {
564  AccessorT acc = mGrid->getAccessor(); // local accessor
565  bool run = true;
566  const SdfT invDx = SdfT(1/mParent.mDx);
567  AttT att;
568  Vec3R pos;
569  Real rad;
570 
571  // Loop over buckets
572  for (size_t n = r.begin(), N = r.end(); n < N; ++n) {
573  // Loop over particles in bucket n.
574  typename PointPartitionerT::IndexIterator iter = mPointPartitioner->indices(n);
575  for ( ; run && iter; ++iter) {
576  const Index32& id = *iter;
577  mParticles.getPosRad(id, pos, rad);
578  const SdfT R = SdfT(invDx * rad);// in voxel units
579  if (this->ignoreParticle(R)) continue;
580  const Vec3R P = mMap.applyInverseMap(pos);
581  this->getAtt<DisableT>(id, att);
582  run = this->makeSphere(P, R, att, acc);
583  }//end loop over particles
584  }//end loop over buckets
585  }
586 
591  void rasterFixedSpheres(const tbb::blocked_range<size_t>& r, SdfT R)
592  {
593  const SdfT
594  dx = static_cast<SdfT>(mParent.mDx),
595  w = static_cast<SdfT>(mParent.mHalfWidth); // in voxel units
596  AccessorT acc = mGrid->getAccessor(); // local accessor
597  const ValueT inside = -mGrid->background();
598  const SdfT max = R + w;// maximum distance in voxel units
599  const SdfT max2 = math::Pow2(max);//square of maximum distance in voxel units
600  const SdfT min2 = math::Pow2(math::Max(SdfT(0), R - w));//square of minimum distance
601  ValueT v;
602  size_t count = 0;
603  AttT att;
604  Vec3R pos;
605 
606  // Loop over buckets
607  for (size_t n = r.begin(), N = r.end(); n < N; ++n) {
608  // Loop over particles in bucket n.
609  typename PointPartitionerT::IndexIterator iter = mPointPartitioner->indices(n);
610  for ( ; iter; ++iter) {
611  const Index32& id = *iter;
612  this->getAtt<DisableT>(id, att);
613  mParticles.getPos(id, pos);
614  const Vec3R P = mMap.applyInverseMap(pos);
615  const Coord a(math::Floor(P[0]-max),math::Floor(P[1]-max),math::Floor(P[2]-max));
616  const Coord b(math::Ceil( P[0]+max),math::Ceil( P[1]+max),math::Ceil( P[2]+max));
617  for (Coord c = a; c.x() <= b.x(); ++c.x()) {
618  //only check interrupter every 32'th scan in x
619  if (!(count++ & ((1<<5)-1)) && util::wasInterrupted(mParent.mInterrupter)) {
620  tbb::task::self().cancel_group_execution();
621  return;
622  }
623  SdfT x2 = static_cast<SdfT>(math::Pow2(c.x() - P[0]));
624  for (c.y() = a.y(); c.y() <= b.y(); ++c.y()) {
625  SdfT x2y2 = static_cast<SdfT>(x2 + math::Pow2(c.y() - P[1]));
626  for (c.z() = a.z(); c.z() <= b.z(); ++c.z()) {
627  SdfT x2y2z2 = static_cast<SdfT>(
628  x2y2 + math::Pow2(c.z()- P[2])); // square distance from c to P
629  if (x2y2z2 >= max2 || (!acc.probeValue(c,v) && v<ValueT(0)))
630  continue;//outside narrow band of particle or inside existing level set
631  if (x2y2z2 <= min2) {//inside narrow band of the particle.
632  acc.setValueOff(c, inside);
633  continue;
634  }
635  // convert signed distance from voxel units to world units
636  const ValueT d=Merge(dx*(math::Sqrt(x2y2z2) - R), att);
637  if (d < v) acc.setValue(c, d);//CSG union
638  }//end loop over z
639  }//end loop over y
640  }//end loop over x
641  }//end loop over particles
642  }// end loop over buckts
643  }
644 
649  void rasterTrails(const tbb::blocked_range<size_t>& r, SdfT delta)
650  {
651  AccessorT acc = mGrid->getAccessor(); // local accessor
652  bool run = true;
653  AttT att;
654  Vec3R pos, vel;
655  Real rad;
656  const Vec3R origin = mMap.applyInverseMap(Vec3R(0,0,0));
657  const SdfT Rmin = SdfT(mParent.mRmin), invDx = SdfT(1/mParent.mDx);
658 
659  // Loop over buckets
660  for (size_t n = r.begin(), N = r.end(); n < N; ++n) {
661  // Loop over particles in bucket n.
662  typename PointPartitionerT::IndexIterator iter = mPointPartitioner->indices(n);
663  for ( ; run && iter; ++iter) {
664  const Index32& id = *iter;
665  mParticles.getPosRadVel(id, pos, rad, vel);
666  const SdfT R0 = SdfT(invDx*rad);
667  if (this->ignoreParticle(R0)) continue;
668  this->getAtt<DisableT>(id, att);
669  const Vec3R P0 = mMap.applyInverseMap(pos);
670  const Vec3R V = mMap.applyInverseMap(vel) - origin;//exclude translation
671  const SdfT speed = SdfT(V.length()), inv_speed = SdfT(1.0/speed);
672  const Vec3R Nrml = -V*inv_speed;// inverse normalized direction
673  Vec3R P = P0;// local position of instance
674  SdfT R = R0, d=0;// local radius and length of trail
675  for (size_t m=0; run && d <= speed ; ++m) {
676  run = this->makeSphere(P, R, att, acc);
677  P += 0.5*delta*R*Nrml;// adaptive offset along inverse velocity direction
678  d = SdfT((P-P0).length());// current length of trail
679  R = R0-(R0-Rmin)*d*inv_speed;// R = R0 -> mRmin(e.g. 1.5)
680  }//end loop over sphere instances
681  }//end loop over particles
682  }//end loop over buckets
683  }
684 
685  void cook()
686  {
687  // parallelize over the point buckets
688  const Index32 bucketCount = Index32(mPointPartitioner->size());
689 
690  if (mParent.mGrainSize>0) {
691  tbb::parallel_reduce(
692  tbb::blocked_range<size_t>(0, bucketCount, mParent.mGrainSize), *this);
693  } else {
694  (*this)(tbb::blocked_range<size_t>(0, bucketCount));
695  }
696  }
697 
713  bool makeSphere(const Vec3R &P, SdfT R, const AttT& att, AccessorT& acc)
714  {
715  const ValueT inside = -mGrid->background();
716  const SdfT dx = SdfT(mParent.mDx), w = SdfT(mParent.mHalfWidth);
717  const SdfT max = R + w;// maximum distance in voxel units
718  const Coord a(math::Floor(P[0]-max),math::Floor(P[1]-max),math::Floor(P[2]-max));
719  const Coord b(math::Ceil( P[0]+max),math::Ceil( P[1]+max),math::Ceil( P[2]+max));
720  const SdfT max2 = math::Pow2(max);//square of maximum distance in voxel units
721  const SdfT min2 = math::Pow2(math::Max(SdfT(0), R - w));//square of minimum distance
722  ValueT v;
723  size_t count = 0;
724  for ( Coord c = a; c.x() <= b.x(); ++c.x() ) {
725  //only check interrupter every 32'th scan in x
726  if (!(count++ & ((1<<5)-1)) && util::wasInterrupted(mParent.mInterrupter)) {
727  tbb::task::self().cancel_group_execution();
728  return false;
729  }
730  SdfT x2 = SdfT(math::Pow2(c.x() - P[0]));
731  for (c.y() = a.y(); c.y() <= b.y(); ++c.y()) {
732  SdfT x2y2 = SdfT(x2 + math::Pow2(c.y() - P[1]));
733  for (c.z() = a.z(); c.z() <= b.z(); ++c.z()) {
734  SdfT x2y2z2 = SdfT(x2y2 + math::Pow2(c.z()-P[2]));//square distance from c to P
735  if (x2y2z2 >= max2 || (!acc.probeValue(c,v) && v<ValueT(0)))
736  continue;//outside narrow band of the particle or inside existing level set
737  if (x2y2z2 <= min2) {//inside narrow band of the particle.
738  acc.setValueOff(c, inside);
739  continue;
740  }
741  // convert signed distance from voxel units to world units
742  //const ValueT d=dx*(math::Sqrt(x2y2z2) - R);
743  const ValueT d=Merge(dx*(math::Sqrt(x2y2z2) - R), att);
744  if (d < v) acc.setValue(c, d);//CSG union
745  }//end loop over z
746  }//end loop over y
747  }//end loop over x
748  return true;
749  }
750  typedef typename boost::function<void (Raster*, const tbb::blocked_range<size_t>&)> FuncType;
751 
752  template <typename DisableType>
753  typename boost::enable_if<DisableType>::type
754  getAtt(size_t, AttT&) const {;}
755 
756  template <typename DisableType>
757  typename boost::disable_if<DisableType>::type
758  getAtt(size_t n, AttT& a) const { mParticles.getAtt(n, a); }
759 
760  template <typename T>
761  typename boost::enable_if<boost::is_same<T,ValueT>, ValueT>::type
762  Merge(T s, const AttT&) const { return s; }
763 
764  template <typename T>
765  typename boost::disable_if<boost::is_same<T,ValueT>, ValueT>::type
766  Merge(T s, const AttT& a) const { return ValueT(s,a); }
767 
768  ParticlesToLevelSetT& mParent;
769  const ParticleListT& mParticles;//list of particles
770  GridT* mGrid;
771  const math::MapBase& mMap;
772  size_t mMinCount, mMaxCount;//counters for ignored particles!
773  FuncType mTask;
774  const bool mIsCopy;
775  PointPartitionerT* mPointPartitioner;
776 };//end of Raster struct
777 
778 
780 
781 namespace p2ls_internal {
782 
783 // This is a simple type that combines a distance value and a particle
784 // attribute. It's required for attribute transfer which is defined in the
785 // Raster class above.
786 template<typename VisibleT, typename BlindT>
787 class BlindData
788 {
789 public:
790  typedef VisibleT type;
791  typedef VisibleT VisibleType;
792  typedef BlindT BlindType;
793 
795  explicit BlindData(VisibleT v) : mVisible(v), mBlind(zeroVal<BlindType>()) {}
796  BlindData(VisibleT v, BlindT b) : mVisible(v), mBlind(b) {}
797  BlindData(const BlindData&) = default;
798  BlindData& operator=(const BlindData&) = default;
799  const VisibleT& visible() const { return mVisible; }
800  const BlindT& blind() const { return mBlind; }
802  bool operator==(const BlindData& rhs) const { return mVisible == rhs.mVisible; }
804  bool operator< (const BlindData& rhs) const { return mVisible < rhs.mVisible; }
805  bool operator> (const BlindData& rhs) const { return mVisible > rhs.mVisible; }
806  BlindData operator+(const BlindData& rhs) const { return BlindData(mVisible + rhs.mVisible); }
807  BlindData operator+(const VisibleT& rhs) const { return BlindData(mVisible + rhs); }
808  BlindData operator-(const BlindData& rhs) const { return BlindData(mVisible - rhs.mVisible); }
809  BlindData operator-() const { return BlindData(-mVisible, mBlind); }
810 
811 protected:
812  VisibleT mVisible;
813  BlindT mBlind;
814 };
815 
816 // Required by several of the tree nodes
817 template<typename VisibleT, typename BlindT>
818 inline std::ostream& operator<<(std::ostream& ostr, const BlindData<VisibleT, BlindT>& rhs)
819 {
820  ostr << rhs.visible();
821  return ostr;
822 }
823 
824 // Required by math::Abs
825 template<typename VisibleT, typename BlindT>
827 {
828  return BlindData<VisibleT, BlindT>(math::Abs(x.visible()), x.blind());
829 }
830 
831 } // namespace p2ls_internal
832 
834 
835 } // namespace tools
836 } // namespace OPENVDB_VERSION_NAME
837 } // namespace openvdb
838 
839 #endif // OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
840 
841 // Copyright (c) 2012-2017 DreamWorks Animation LLC
842 // All rights reserved. This software is distributed under the
843 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
int Floor(float x)
Return the floor of x.
Definition: Math.h:814
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:503
uint32_t Index32
Definition: Types.h:55
Definition: ParticlesToLevelSet.h:127
~ParticlesToLevelSet()
Destructor.
Definition: ParticlesToLevelSet.h:172
Real getRmin() const
Return the smallest radius allowed in voxel units.
Definition: ParticlesToLevelSet.h:198
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Coord Abs(const Coord &xyz)
Definition: Coord.h:254
double Real
Definition: Types.h:63
BlindData()
Definition: ParticlesToLevelSet.h:794
Functions to efficiently perform various compositing operations on grids.
VisibleT VisibleType
Definition: ParticlesToLevelSet.h:791
const BlindT & blind() const
Definition: ParticlesToLevelSet.h:800
T length() const
Length of the vector.
Definition: Vec3.h:224
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:101
void pruneLevelSet(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing nodes whose values are all inactive with inactive ...
Definition: Prune.h:416
bool ignoredParticles() const
Return true if any particles were ignored due to their size.
Definition: ParticlesToLevelSet.h:203
BlindData operator-() const
Definition: ParticlesToLevelSet.h:809
Real getVoxelSize() const
Return the size of a voxel in world units.
Definition: ParticlesToLevelSet.h:192
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:94
OPENVDB_NO_FP_EQUALITY_WARNING_BEGIN bool operator==(const BlindData &rhs) const
Definition: ParticlesToLevelSet.h:802
BlindT mBlind
Definition: ParticlesToLevelSet.h:813
Definition: PointPartitioner.h:106
int getGrainSize() const
Returns the grain-size used for multi-threading.
Definition: ParticlesToLevelSet.h:215
Spatially partitions points using a parallel radix-based sorting algorithm.
Defined various multi-threaded utility functions for trees.
size_t getMaxCount() const
Return number of large particles that were ignore due to Rmax.
Definition: ParticlesToLevelSet.h:207
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:333
MeshToVoxelEdgeData::EdgeData Abs(const MeshToVoxelEdgeData::EdgeData &x)
Definition: MeshToVolume.h:3664
SdfGridT::ValueType SdfType
Definition: ParticlesToLevelSet.h:141
void setRmax(Real Rmax)
set the largest radius allowed in voxel units
Definition: ParticlesToLevelSet.h:212
void prune(TreeT &tree, typename TreeT::ValueType tolerance=zeroVal< typename TreeT::ValueType >(), bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with tiles any nodes whose values are all the same...
Definition: Prune.h:361
Definition: Exceptions.h:90
BlindData(VisibleT v)
Definition: ParticlesToLevelSet.h:795
void rasterizeSpheres(const ParticleListT &pa)
Rasterize a sphere per particle derived from their position and radius. All spheres are CSG unioned...
Definition: ParticlesToLevelSet.h:305
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:727
Tag dispatch class that distinguishes shallow copy constructors from deep copy constructors.
Definition: Types.h:500
#define OPENVDB_VERSION_NAME
Definition: version.h:43
Propagates the sign of distance values from the active voxels in the narrow band to the inactive valu...
BlindData operator+(const VisibleT &rhs) const
Definition: ParticlesToLevelSet.h:807
AttGridType::Ptr attributeGrid()
Return a shared pointer to the grid containing the (optional) attribute.
Definition: ParticlesToLevelSet.h:189
Definition: Exceptions.h:39
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
BlindData operator+(const BlindData &rhs) const
Definition: ParticlesToLevelSet.h:806
const boost::disable_if_c< VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:132
#define OPENVDB_NO_FP_EQUALITY_WARNING_END
Definition: Math.h:83
void setGrainSize(int grainSize)
Set the grain-size used for multi-threading.
Definition: ParticlesToLevelSet.h:218
BlindData operator-(const BlindData &rhs) const
Definition: ParticlesToLevelSet.h:808
SdfGridT SdfGridType
Definition: ParticlesToLevelSet.h:140
InterrupterT InterrupterType
Definition: ParticlesToLevelSet.h:138
math::Vec3< Real > Vec3R
Definition: Types.h:75
#define OPENVDB_NO_FP_EQUALITY_WARNING_BEGIN
Definition: Math.h:82
BlindT BlindType
Definition: ParticlesToLevelSet.h:792
Real getRmax() const
Return the largest radius allowed in voxel units.
Definition: ParticlesToLevelSet.h:200
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition: Math.h:561
void setRmin(Real Rmin)
set the smallest radius allowed in voxel units
Definition: ParticlesToLevelSet.h:210
Abstract base class for maps.
Definition: Maps.h:158
Real getHalfWidth() const
Return the half-width of the narrow band in voxel units.
Definition: ParticlesToLevelSet.h:195
boost::mpl::if_< DisableT, size_t, AttributeT >::type AttType
Definition: ParticlesToLevelSet.h:143
bool operator<(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:174
const VisibleT & visible() const
Definition: ParticlesToLevelSet.h:799
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:52
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
boost::is_void< AttributeT >::type DisableT
Definition: ParticlesToLevelSet.h:137
Index32 Index
Definition: Types.h:57
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:1022
BlindData(VisibleT v, BlindT b)
Definition: ParticlesToLevelSet.h:796
size_t getMinCount() const
Return number of small particles that were ignore due to Rmin.
Definition: ParticlesToLevelSet.h:205
VisibleT mVisible
Definition: ParticlesToLevelSet.h:812
VisibleT type
Definition: ParticlesToLevelSet.h:790
bool operator>(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:186
Definition: Types.h:264
Type Pow2(Type x)
Return .
Definition: Math.h:514
void signedFloodFill(TreeOrLeafManagerT &tree, bool threaded=true, size_t grainSize=1, Index minLevel=0)
Set the values of all inactive voxels and tiles of a narrow-band level set from the signs of the acti...
Definition: SignedFloodFill.h:294
SdfGridT::template ValueConverter< AttType >::Type AttGridType
Definition: ParticlesToLevelSet.h:144
int Ceil(float x)
Return the ceiling of x.
Definition: Math.h:822
Definition: ParticlesToLevelSet.h:134
void finalize(bool prune=false)
This methods syncs up the level set and attribute grids and therefore needs to be called before any o...
Definition: ParticlesToLevelSet.h:346