97 #ifndef OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
98 #define OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
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>
124 namespace local {
template <
typename VisibleT,
typename BlindT>
class BlindData;}
126 template<
typename SdfGridT,
127 typename AttributeT = void,
133 typedef typename boost::is_void<AttributeT>::type
DisableT;
139 typedef typename boost::mpl::if_<DisableT, size_t, AttributeT>::type
AttType;
140 typedef typename SdfGridT::template ValueConverter<AttType>::Type
AttGridType;
142 BOOST_STATIC_ASSERT(boost::is_floating_point<SdfType>::value);
219 template <
typename ParticleListT>
220 void rasterizeSpheres(
const ParticleListT& pa);
227 template <
typename ParticleListT>
228 void rasterizeSpheres(
const ParticleListT& pa,
Real radius);
246 template <
typename ParticleListT>
247 void rasterizeTrails(
const ParticleListT& pa,
Real delta=1.0);
252 typedef typename SdfGridT::template ValueConverter<BlindType>::Type BlindGridType;
255 template<
typename ParticleListT,
typename Gr
idT>
struct Raster;
257 SdfGridType* mSdfGrid;
258 typename AttGridType::Ptr mAttGrid;
259 BlindGridType* mBlindGrid;
260 InterrupterT* mInterrupter;
261 Real mDx, mHalfWidth;
263 size_t mMinCount, mMaxCount;
268 template<
typename SdfGr
idT,
typename AttributeT,
typename InterrupterT>
269 inline ParticlesToLevelSet<SdfGridT, AttributeT, InterrupterT>::
270 ParticlesToLevelSet(SdfGridT& grid, InterrupterT* interrupter) :
273 mInterrupter(interrupter),
274 mDx(grid.voxelSize()[0]),
275 mHalfWidth(grid.background()/mDx),
282 if (!mSdfGrid->hasUniformVoxels() ) {
284 "ParticlesToLevelSet only supports uniform voxels!");
288 "ParticlesToLevelSet only supports level sets!"
289 "\nUse Grid::setGridClass(openvdb::GRID_LEVEL_SET)");
292 if (!DisableT::value) {
293 mBlindGrid =
new BlindGridType(
BlindType(grid.background()));
294 mBlindGrid->setTransform(mSdfGrid->transform().copy());
298 template<
typename SdfGr
idT,
typename AttributeT,
typename InterrupterT>
299 template <
typename ParticleListT>
303 if (DisableT::value) {
304 Raster<ParticleListT, SdfGridT> r(*
this, mSdfGrid, pa);
305 r.rasterizeSpheres();
307 Raster<ParticleListT, BlindGridType> r(*
this, mBlindGrid, pa);
308 r.rasterizeSpheres();
312 template<
typename SdfGr
idT,
typename AttributeT,
typename InterrupterT>
313 template <
typename ParticleListT>
317 if (DisableT::value) {
318 Raster<ParticleListT, SdfGridT> r(*
this, mSdfGrid, pa);
319 r.rasterizeSpheres(radius/mDx);
321 Raster<ParticleListT, BlindGridType> r(*
this, mBlindGrid, pa);
322 r.rasterizeSpheres(radius/mDx);
326 template<
typename SdfGr
idT,
typename AttributeT,
typename InterrupterT>
327 template <
typename ParticleListT>
331 if (DisableT::value) {
332 Raster<ParticleListT, SdfGridT> r(*
this, mSdfGrid, pa);
333 r.rasterizeTrails(delta);
335 Raster<ParticleListT, BlindGridType> r(*
this, mBlindGrid, pa);
336 r.rasterizeTrails(delta);
340 template<
typename SdfGr
idT,
typename AttributeT,
typename InterrupterT>
344 if (mBlindGrid==NULL)
return;
346 typedef typename SdfGridType::TreeType SdfTreeT;
347 typedef typename AttGridType::TreeType AttTreeT;
348 typedef typename BlindGridType::TreeType BlindTreeT;
350 const BlindTreeT& tree = mBlindGrid->tree();
353 typename SdfTreeT::Ptr sdfTree(
new SdfTreeT(
357 typename AttTreeT::Ptr attTree(
new AttTreeT(
359 mAttGrid =
typename AttGridType::Ptr(
new AttGridType(attTree));
360 mAttGrid->setTransform(mBlindGrid->transform().copy());
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();
373 SdfLeafT* sdfLeaf = sdfTree->probeLeaf(xyz);
374 AttLeafT* attLeaf = attTree->probeLeaf(xyz);
375 for (
typename LeafT::ValueOnCIter m=leaf.cbeginValueOn(); m; ++m) {
379 sdfLeaf->setValueOnly(k, v.
visible());
380 attLeaf->setValueOnly(k, v.
blind());
383 sdfTree->signedFloodFill();
385 if (mSdfGrid->empty()) {
386 mSdfGrid->setTree(sdfTree);
394 template<
typename SdfGr
idT,
typename AttributeT,
typename InterrupterT>
395 template<
typename ParticleListT,
typename Gr
idT>
398 typedef typename boost::is_void<AttributeT>::type
DisableT;
400 typedef typename ParticlesToLevelSetT::SdfType SdfT;
401 typedef typename ParticlesToLevelSetT::AttType AttT;
402 typedef typename GridT::ValueType ValueT;
403 typedef typename GridT::Accessor AccessorT;
406 Raster(ParticlesToLevelSetT& parent, GridT* grid,
const ParticleListT& particles)
408 mParticles(particles),
410 mMap(*(mGrid->transform().baseMap())),
418 Raster(Raster& other, tbb::split)
419 : mParent(other.mParent),
420 mParticles(other.mParticles),
421 mGrid(new GridT(*other.mGrid, openvdb::
ShallowCopy())),
431 virtual ~Raster() {
if (mOwnsGrid)
delete mGrid; }
437 mMinCount = mMaxCount = 0;
438 if (mParent.mInterrupter) {
439 mParent.mInterrupter->start(
"Rasterizing particles to level set using spheres");
441 mTask = boost::bind(&Raster::rasterSpheres, _1, _2);
443 if (mParent.mInterrupter) mParent.mInterrupter->end();
450 mMinCount = radius < mParent.mRmin ? mParticles.size() : 0;
451 mMaxCount = radius > mParent.mRmax ? mParticles.size() : 0;
452 if (mMinCount>0 || mMaxCount>0) {
453 mParent.mMinCount = mMinCount;
454 mParent.mMaxCount = mMaxCount;
456 if (mParent.mInterrupter) {
457 mParent.mInterrupter->start(
458 "Rasterizing particles to level set using const spheres");
460 mTask = boost::bind(&Raster::rasterFixedSpheres, _1, _2, SdfT(radius));
462 if (mParent.mInterrupter) mParent.mInterrupter->end();
481 mMinCount = mMaxCount = 0;
482 if (mParent.mInterrupter) {
483 mParent.mInterrupter->start(
"Rasterizing particles to level set using trails");
485 mTask = boost::bind(&Raster::rasterTrails, _1, _2, SdfT(delta));
487 if (mParent.mInterrupter) mParent.mInterrupter->end();
491 void operator()(
const tbb::blocked_range<size_t>& r)
495 mParent.mMinCount = mMinCount;
496 mParent.mMaxCount = mMaxCount;
500 void join(Raster& other)
503 mMinCount += other.mMinCount;
504 mMaxCount += other.mMaxCount;
508 Raster& operator=(
const Raster& other) {
return *
this; }
511 bool ignoreParticle(SdfT R)
513 if (R < mParent.mRmin) {
517 if (R > mParent.mRmax) {
527 void rasterSpheres(
const tbb::blocked_range<size_t>& r)
529 AccessorT acc = mGrid->getAccessor();
531 const SdfT invDx = 1/mParent.mDx;
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;
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);
548 void rasterFixedSpheres(
const tbb::blocked_range<size_t>& r, SdfT R)
550 const SdfT dx = mParent.mDx, w = mParent.mHalfWidth;
551 AccessorT acc = mGrid->getAccessor();
552 const ValueT inside = -mGrid->background();
553 const SdfT
max = R + w;
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);
566 for ( Coord c = a; c.x() <= b.x(); ++c.x() ) {
569 tbb::task::self().cancel_group_execution();
573 for ( c.y() = a.y(); c.y() <= b.y(); ++c.y() ) {
575 for ( c.z() = a.z(); c.z() <= b.z(); ++c.z() ) {
577 if ( x2y2z2 >= max2 || (!acc.probeValue(c,v) && v<ValueT(0)) )
579 if ( x2y2z2 <= min2 ) {
580 acc.setValueOff(c, inside);
584 const ValueT d=Merge(dx*(
math::Sqrt(x2y2z2) - R), att);
585 if (d < v) acc.setValue(c, d);
595 void rasterTrails(
const tbb::blocked_range<size_t>& r, SdfT delta)
597 AccessorT acc = mGrid->getAccessor();
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;
611 const SdfT speed = V.length(), inv_speed=1.0/speed;
612 const Vec3R N = -V*inv_speed;
615 for (
size_t m=0; run && d <= speed ; ++m) {
616 run = this->makeSphere(P, R, att, acc);
619 R = R0-(R0-Rmin)*d*inv_speed;
626 if (mParent.mGrainSize>0) {
627 tbb::parallel_reduce(
628 tbb::blocked_range<size_t>(0,mParticles.size(),mParent.mGrainSize), *
this);
630 (*this)(tbb::blocked_range<size_t>(0, mParticles.size()));
649 bool makeSphere(
const Vec3R &P, SdfT R,
const AttT& att, AccessorT& acc)
651 const ValueT inside = -mGrid->background();
652 const SdfT dx = mParent.mDx, w = mParent.mHalfWidth;
653 const SdfT max = R + w;
660 for ( Coord c = a; c.x() <= b.x(); ++c.x() ) {
663 tbb::task::self().cancel_group_execution();
667 for ( c.y() = a.y(); c.y() <= b.y(); ++c.y() ) {
669 for ( c.z() = a.z(); c.z() <= b.z(); ++c.z() ) {
670 SdfT x2y2z2 = x2y2 +
math::Pow2( c.z() - P[2] );
671 if ( x2y2z2 >= max2 || (!acc.probeValue(c,v) && v<ValueT(0)) )
673 if ( x2y2z2 <= min2 ) {
674 acc.setValueOff(c, inside);
679 const ValueT d=Merge(dx*(
math::Sqrt(x2y2z2) - R), att);
680 if (d < v) acc.setValue(c, d);
686 typedef typename boost::function<void (Raster*, const tbb::blocked_range<size_t>&)> FuncType;
688 template <
typename DisableType>
689 typename boost::enable_if<DisableType>::type
690 getAtt(
size_t, AttT&)
const {;}
692 template <
typename DisableType>
693 typename boost::disable_if<DisableType>::type
694 getAtt(
size_t n, AttT& a)
const {mParticles.getAtt(n, a);}
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; }
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); }
704 ParticlesToLevelSetT& mParent;
705 const ParticleListT& mParticles;
707 const math::MapBase&
mMap;
708 size_t mMinCount, mMaxCount;
710 const bool mOwnsGrid;
720 template <
typename VisibleT,
typename BlindT>
750 template <
typename VisibleT,
typename BlindT>
751 inline std::ostream& operator<<(std::ostream& ostr, const BlindData<VisibleT, BlindT>& rhs)
753 ostr << rhs.visible();
757 template <
typename VisibleT,
typename BlindT>
770 #endif // OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
int Ceil(float x)
Return the ceiling of x.
Definition: Math.h:728
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
AttGridType::Ptr attributeGrid()
Return a shared pointer to the grid containing the (optional) attribute.
Definition: ParticlesToLevelSet.h:184
const MapT & mMap
Definition: GridOperators.h:260
void setGrainSize(int grainSize)
Set the grain-size used for multi-threading.
Definition: ParticlesToLevelSet.h:213
bool ignoredParticles() const
Return true if any particles were ignored due to their size.
Definition: ParticlesToLevelSet.h:198
Real getRmin() const
Return the smallest radius allowed in voxel units.
Definition: ParticlesToLevelSet.h:193
Functions to efficiently perform various compositing operations on grids.
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: Math.h:648
uint32_t Index32
Definition: Types.h:54
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
Type Pow2(Type x)
Return .
Definition: Math.h:460
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition: Math.h:507
double Real
Definition: Types.h:62
void setRmin(Real Rmin)
set the smallest radius allowed in voxel units
Definition: ParticlesToLevelSet.h:205
Definition: Exceptions.h:86
int getGrainSize() const
Rreturn the grain-size used for multi-threading.
Definition: ParticlesToLevelSet.h:210
boost::mpl::if_< DisableT, size_t, AttributeT >::type AttType
Definition: ParticlesToLevelSet.h:139
Real getHalfWidth() const
Return the half-width of the narrow band in voxel units.
Definition: ParticlesToLevelSet.h:190
void setRmax(Real Rmax)
set the largest radius allowed in voxel units
Definition: ParticlesToLevelSet.h:207
size_t getMaxCount() const
Return number of large particles that were ignore due to Rmax.
Definition: ParticlesToLevelSet.h:202
SdfGridT::ValueType SdfType
Definition: ParticlesToLevelSet.h:137
#define OPENVDB_VERSION_NAME
Definition: version.h:45
math::Vec3< Real > Vec3R
Definition: Types.h:74
~ParticlesToLevelSet()
Destructor.
Definition: ParticlesToLevelSet.h:168
SdfGridT SdfGridType
Definition: ParticlesToLevelSet.h:136
InterrupterT InterrupterType
Definition: ParticlesToLevelSet.h:134
Index32 Index
Definition: Types.h:56
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
Real getVoxelSize() const
Return the size of a voxel in world units.
Definition: ParticlesToLevelSet.h:187
Real getRmax() const
Return the largest radius allowed in voxel units.
Definition: ParticlesToLevelSet.h:195
int32_t Abs(int32_t i)
Return the absolute value of the given quantity.
Definition: Math.h:246
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:56
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
int Floor(float x)
Return the floor of x.
Definition: Math.h:720
boost::is_void< AttributeT >::type DisableT
Definition: ParticlesToLevelSet.h:133
SdfGridT::template ValueConverter< AttType >::Type AttGridType
Definition: ParticlesToLevelSet.h:140
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
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
Definition: ParticlesToLevelSet.h:129
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:52