98 #ifndef OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED 99 #define OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED 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> 123 namespace p2ls_internal {
127 template<
typename VisibleT,
typename BlindT>
class BlindData;
131 template<
typename SdfGridT,
132 typename AttributeT = void,
137 typedef typename boost::is_void<AttributeT>::type
DisableT;
143 typedef typename boost::mpl::if_<DisableT, size_t, AttributeT>::type
AttType;
144 typedef typename SdfGridT::template ValueConverter<AttType>::Type
AttGridType;
146 BOOST_STATIC_ASSERT(boost::is_floating_point<SdfType>::value);
182 void finalize(
bool prune =
false);
224 template <
typename ParticleListT>
225 void rasterizeSpheres(
const ParticleListT& pa);
232 template <
typename ParticleListT>
233 void rasterizeSpheres(
const ParticleListT& pa,
Real radius);
251 template <
typename ParticleListT>
252 void rasterizeTrails(
const ParticleListT& pa,
Real delta=1.0);
256 typedef typename SdfGridT::template ValueConverter<BlindType>::Type BlindGridType;
259 template<
typename ParticleListT,
typename Gr
idT>
struct Raster;
261 SdfGridType* mSdfGrid;
262 typename AttGridType::Ptr mAttGrid;
263 BlindGridType* mBlindGrid;
264 InterrupterT* mInterrupter;
265 Real mDx, mHalfWidth;
267 size_t mMinCount, mMaxCount;
272 template<
typename SdfGr
idT,
typename AttributeT,
typename InterrupterT>
277 mInterrupter(interrupter),
278 mDx(grid.voxelSize()[0]),
279 mHalfWidth(grid.background()/mDx),
286 if (!mSdfGrid->hasUniformVoxels() ) {
288 "ParticlesToLevelSet only supports uniform voxels!");
292 "ParticlesToLevelSet only supports level sets!" 293 "\nUse Grid::setGridClass(openvdb::GRID_LEVEL_SET)");
296 if (!DisableT::value) {
297 mBlindGrid =
new BlindGridType(
BlindType(grid.background()));
298 mBlindGrid->setTransform(mSdfGrid->transform().copy());
302 template<
typename SdfGr
idT,
typename AttributeT,
typename InterrupterT>
303 template <
typename ParticleListT>
307 if (DisableT::value) {
308 Raster<ParticleListT, SdfGridT> r(*
this, mSdfGrid, pa);
309 r.rasterizeSpheres();
311 Raster<ParticleListT, BlindGridType> r(*
this, mBlindGrid, pa);
312 r.rasterizeSpheres();
316 template<
typename SdfGr
idT,
typename AttributeT,
typename InterrupterT>
317 template <
typename ParticleListT>
321 if (DisableT::value) {
322 Raster<ParticleListT, SdfGridT> r(*
this, mSdfGrid, pa);
323 r.rasterizeSpheres(radius/mDx);
325 Raster<ParticleListT, BlindGridType> r(*
this, mBlindGrid, pa);
326 r.rasterizeSpheres(radius/mDx);
330 template<
typename SdfGr
idT,
typename AttributeT,
typename InterrupterT>
331 template <
typename ParticleListT>
335 if (DisableT::value) {
336 Raster<ParticleListT, SdfGridT> r(*
this, mSdfGrid, pa);
337 r.rasterizeTrails(delta);
339 Raster<ParticleListT, BlindGridType> r(*
this, mBlindGrid, pa);
340 r.rasterizeTrails(delta);
344 template<
typename SdfGr
idT,
typename AttributeT,
typename InterrupterT>
348 if (mBlindGrid ==
nullptr) {
355 typedef typename SdfGridType::TreeType SdfTreeT;
356 typedef typename AttGridType::TreeType AttTreeT;
357 typedef typename BlindGridType::TreeType BlindTreeT;
359 const BlindTreeT& tree = mBlindGrid->tree();
362 typename SdfTreeT::Ptr sdfTree(
new SdfTreeT(
366 typename AttTreeT::Ptr attTree(
new AttTreeT(
368 mAttGrid =
typename AttGridType::Ptr(
new AttGridType(attTree));
369 mAttGrid->setTransform(mBlindGrid->transform().copy());
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;
382 SdfLeafT* sdfLeaf = sdfTree->probeLeaf(xyz);
383 AttLeafT* attLeaf = attTree->probeLeaf(xyz);
385 typename LeafT::ValueOnCIter m=leaf.cbeginValueOn();
389 sdfLeaf->setValueOnly(k, v.
visible());
390 attLeaf->setValueOnly(k, v.
blind());
396 sdfLeaf->setValueOnly(k, v.
visible());
397 attLeaf->setValueOnly(k, v.
blind());
404 if (mSdfGrid->empty()) {
405 mSdfGrid->setTree(sdfTree);
413 template<
typename SdfGr
idT,
typename AttributeT,
typename InterrupterT>
414 template<
typename ParticleListT,
typename Gr
idT>
417 typedef typename boost::is_void<AttributeT>::type
DisableT;
419 typedef typename ParticlesToLevelSetT::SdfType SdfT;
420 typedef typename ParticlesToLevelSetT::AttType AttT;
421 typedef typename GridT::ValueType ValueT;
422 typedef typename GridT::Accessor AccessorT;
423 typedef typename GridT::TreeType TreeT;
424 typedef typename TreeT::LeafNodeType LeafNodeT;
429 Raster(ParticlesToLevelSetT& parent, GridT* grid,
const ParticleListT& particles)
431 , mParticles(particles)
433 , mMap(*(mGrid->transform().baseMap()))
438 mPointPartitioner =
new PointPartitionerT();
439 mPointPartitioner->construct(particles, mGrid->transform());
443 Raster(Raster& other, tbb::split)
444 : mParent(other.mParent)
445 , mParticles(other.mParticles)
452 , mPointPartitioner(other.mPointPartitioner)
464 delete mPointPartitioner;
472 mMinCount = mMaxCount = 0;
473 if (mParent.mInterrupter) {
474 mParent.mInterrupter->start(
"Rasterizing particles to level set using spheres");
476 mTask = boost::bind(&Raster::rasterSpheres, _1, _2);
478 if (mParent.mInterrupter) mParent.mInterrupter->end();
485 mMinCount = radius < mParent.mRmin ? mParticles.size() : 0;
486 mMaxCount = radius > mParent.mRmax ? mParticles.size() : 0;
487 if (mMinCount>0 || mMaxCount>0) {
488 mParent.mMinCount = mMinCount;
489 mParent.mMaxCount = mMaxCount;
491 if (mParent.mInterrupter) {
492 mParent.mInterrupter->start(
493 "Rasterizing particles to level set using const spheres");
495 mTask = boost::bind(&Raster::rasterFixedSpheres, _1, _2, SdfT(radius));
497 if (mParent.mInterrupter) mParent.mInterrupter->end();
516 mMinCount = mMaxCount = 0;
517 if (mParent.mInterrupter) {
518 mParent.mInterrupter->start(
"Rasterizing particles to level set using trails");
520 mTask = boost::bind(&Raster::rasterTrails, _1, _2, SdfT(delta));
522 if (mParent.mInterrupter) mParent.mInterrupter->end();
526 void operator()(
const tbb::blocked_range<size_t>& r)
530 mParent.mMinCount = mMinCount;
531 mParent.mMaxCount = mMaxCount;
535 void join(Raster& other)
538 mMinCount += other.mMinCount;
539 mMaxCount += other.mMaxCount;
543 Raster& operator=(
const Raster&) {
return *
this; }
546 bool ignoreParticle(SdfT R)
548 if (R < mParent.mRmin) {
552 if (R > mParent.mRmax) {
562 void rasterSpheres(
const tbb::blocked_range<size_t>& r)
564 AccessorT acc = mGrid->getAccessor();
566 const SdfT invDx = SdfT(1/mParent.mDx);
572 for (
size_t n = r.begin(), N = r.end(); n < N; ++n) {
574 typename PointPartitionerT::IndexIterator iter = mPointPartitioner->indices(n);
575 for ( ; run && iter; ++iter) {
577 mParticles.getPosRad(
id, pos, rad);
578 const SdfT R = SdfT(invDx * rad);
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);
591 void rasterFixedSpheres(
const tbb::blocked_range<size_t>& r, SdfT R)
594 dx =
static_cast<SdfT
>(mParent.mDx),
595 w = static_cast<SdfT>(mParent.mHalfWidth);
596 AccessorT acc = mGrid->getAccessor();
597 const ValueT inside = -mGrid->background();
598 const SdfT
max = R + w;
607 for (
size_t n = r.begin(), N = r.end(); n < N; ++n) {
609 typename PointPartitionerT::IndexIterator iter = mPointPartitioner->indices(n);
610 for ( ; iter; ++iter) {
612 this->getAtt<DisableT>(id, att);
613 mParticles.getPos(
id, pos);
614 const Vec3R P = mMap.applyInverseMap(pos);
617 for (
Coord c = a; c.
x() <= b.
x(); ++c.x()) {
620 tbb::task::self().cancel_group_execution();
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
>(
629 if (x2y2z2 >= max2 || (!acc.probeValue(c,v) && v<ValueT(0)))
631 if (x2y2z2 <= min2) {
632 acc.setValueOff(c, inside);
636 const ValueT d=Merge(dx*(
math::Sqrt(x2y2z2) - R), att);
637 if (d < v) acc.setValue(c, d);
649 void rasterTrails(
const tbb::blocked_range<size_t>& r, SdfT delta)
651 AccessorT acc = mGrid->getAccessor();
656 const Vec3R origin = mMap.applyInverseMap(
Vec3R(0,0,0));
657 const SdfT Rmin = SdfT(mParent.mRmin), invDx = SdfT(1/mParent.mDx);
660 for (
size_t n = r.begin(), N = r.end(); n < N; ++n) {
662 typename PointPartitionerT::IndexIterator iter = mPointPartitioner->indices(n);
663 for ( ; run && iter; ++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;
671 const SdfT speed = SdfT(V.
length()), inv_speed = SdfT(1.0/speed);
672 const Vec3R Nrml = -V*inv_speed;
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;
678 d = SdfT((P-P0).length());
679 R = R0-(R0-Rmin)*d*inv_speed;
690 if (mParent.mGrainSize>0) {
691 tbb::parallel_reduce(
692 tbb::blocked_range<size_t>(0, bucketCount, mParent.mGrainSize), *
this);
694 (*this)(tbb::blocked_range<size_t>(0, bucketCount));
713 bool makeSphere(
const Vec3R &P, SdfT R,
const AttT& att, AccessorT& acc)
715 const ValueT inside = -mGrid->background();
716 const SdfT dx = SdfT(mParent.mDx), w = SdfT(mParent.mHalfWidth);
717 const SdfT
max = R + w;
724 for (
Coord c = a; c.
x() <= b.
x(); ++c.x() ) {
727 tbb::task::self().cancel_group_execution();
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]));
735 if (x2y2z2 >= max2 || (!acc.probeValue(c,v) && v<ValueT(0)))
737 if (x2y2z2 <= min2) {
738 acc.setValueOff(c, inside);
743 const ValueT d=Merge(dx*(
math::Sqrt(x2y2z2) - R), att);
744 if (d < v) acc.setValue(c, d);
750 typedef typename boost::function<void (Raster*, const tbb::blocked_range<size_t>&)> FuncType;
752 template <
typename DisableType>
753 typename boost::enable_if<DisableType>::type
754 getAtt(
size_t, AttT&)
const {;}
756 template <
typename DisableType>
757 typename boost::disable_if<DisableType>::type
758 getAtt(
size_t n, AttT& a)
const { mParticles.getAtt(n, a); }
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; }
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); }
768 ParticlesToLevelSetT& mParent;
769 const ParticleListT& mParticles;
772 size_t mMinCount, mMaxCount;
775 PointPartitionerT* mPointPartitioner;
781 namespace p2ls_internal {
786 template<
typename VisibleT,
typename BlindT>
796 BlindData(VisibleT v, BlindT b) : mVisible(v), mBlind(b) {}
799 const VisibleT&
visible()
const {
return mVisible; }
800 const BlindT&
blind()
const {
return mBlind; }
817 template<
typename VisibleT,
typename BlindT>
818 inline std::ostream& operator<<(std::ostream& ostr, const BlindData<VisibleT, BlindT>& rhs)
820 ostr << rhs.visible();
825 template<
typename VisibleT,
typename BlindT>
839 #endif // OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED 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
~ParticlesToLevelSet()
Destructor.
Definition: ParticlesToLevelSet.h:172
Int32 z() const
Definition: Coord.h:156
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
Functions to efficiently perform various compositing operations on grids.
Real getHalfWidth() const
Return the half-width of the narrow band in voxel units.
Definition: ParticlesToLevelSet.h:195
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:101
Int32 y() const
Definition: Coord.h:155
size_t getMinCount() const
Return number of small particles that were ignore due to Rmin.
Definition: ParticlesToLevelSet.h:205
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:94
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:48
Spatially partitions points using a parallel radix-based sorting algorithm.
Defined various multi-threaded utility functions for trees.
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
SdfGridT::ValueType SdfType
Definition: ParticlesToLevelSet.h:141
void setRmax(Real Rmax)
set the largest radius allowed in voxel units
Definition: ParticlesToLevelSet.h:212
Definition: Exceptions.h:90
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
Real getRmin() const
Return the smallest radius allowed in voxel units.
Definition: ParticlesToLevelSet.h:198
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...
int getGrainSize() const
Returns the grain-size used for multi-threading.
Definition: ParticlesToLevelSet.h:215
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
#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
SdfGridT SdfGridType
Definition: ParticlesToLevelSet.h:140
T length() const
Length of the vector.
Definition: Vec3.h:224
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
Int32 x() const
Definition: Coord.h:154
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition: Math.h:561
Real getRmax() const
Return the largest radius allowed in voxel units.
Definition: ParticlesToLevelSet.h:200
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
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
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
size_t getMaxCount() const
Return number of large particles that were ignore due to Rmax.
Definition: ParticlesToLevelSet.h:207
bool ignoredParticles() const
Return true if any particles were ignored due to their size.
Definition: ParticlesToLevelSet.h:203
bool operator>(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:186
Type Pow2(Type x)
Return .
Definition: Math.h:514
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
Real getVoxelSize() const
Return the size of a voxel in world units.
Definition: ParticlesToLevelSet.h:192
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