82 #ifndef OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
83 #define OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
85 #include <tbb/parallel_reduce.h>
86 #include <tbb/blocked_range.h>
87 #include <boost/bind.hpp>
88 #include <boost/function.hpp>
89 #include <openvdb/util/Util.h>
90 #include <openvdb/Types.h>
91 #include <openvdb/Grid.h>
92 #include <openvdb/math/Math.h>
93 #include <openvdb/math/Transform.h>
94 #include <openvdb/util/NullInterrupter.h>
107 template <
typename T>
111 static T
split(T dist) {
return dist; }
115 template<
typename GridT,
116 typename ParticleListT,
118 typename RealT =
typename GridT::ValueType>
139 mDx(grid.transform().voxelSize()[0]),
140 mHalfWidth(local::DualTrait<ValueT>::split(grid.background()) / mDx),
144 mInterrupter(interrupt),
149 if ( !mGrid->hasUniformVoxels() ) {
151 "The transform must have uniform scale for ParticlesToLevelSet to function!");
155 "ParticlesToLevelSet only supports level sets!"
156 "\nUse Grid::setGridClass(openvdb::GRID_LEVEL_SET)");
163 mGrid(new GridT(*other.mGrid, openvdb::
ShallowCopy())),
166 mHalfWidth(other.mHalfWidth),
169 mGrainSize(other.mGrainSize),
171 mInterrupter(other.mInterrupter),
212 void rasterizeSpheres(
const ParticleListT& pa)
215 if (mInterrupter) mInterrupter->start(
"Rasterizing particles to level set using spheres");
216 mTask = boost::bind(&ParticlesToLevelSet::rasterSpheres, _1, _2);
218 if (mInterrupter) mInterrupter->end();
236 void rasterizeTrails(
const ParticleListT& pa,
Real delta=1.0)
239 if (mInterrupter) mInterrupter->start(
"Rasterizing particles to level set using trails");
240 mTask = boost::bind(&ParticlesToLevelSet::rasterTrails, _1, _2, RealT(delta));
242 if (mInterrupter) mInterrupter->end();
250 void operator()(
const tbb::blocked_range<size_t>& r)
264 mMinCount += other.mMinCount;
265 mMaxCount += other.mMaxCount;
269 typedef typename GridT::ValueType ValueT;
270 typedef typename GridT::Accessor Accessor;
272 const tbb::blocked_range<size_t>&)> FuncType;
274 const ParticleListT* mPa;
276 const RealT mHalfWidth;
281 InterruptT* mInterrupter;
282 size_t mMinCount, mMaxCount;
288 tbb::parallel_reduce(tbb::blocked_range<size_t>(0,mPa->size(),mGrainSize), *
this);
290 (*this)(tbb::blocked_range<size_t>(0, mPa->size()));
294 inline bool ignoreParticle(RealT R)
321 inline bool rasterSphere(
const Vec3R &P, RealT R,
Index32 id, Accessor& accessor)
323 const ValueT inside = -mGrid->background();
324 const RealT dx = mDx;
325 const RealT
max = R + mHalfWidth;
332 for (
Coord c = a; c.
x() <= b.x(); ++c.x() ) {
335 tbb::task::self().cancel_group_execution();
339 for ( c.y() = a.y(); c.y() <= b.y(); ++c.y() ) {
341 for ( c.z() = a.z(); c.z() <= b.z(); ++c.z() ) {
342 RealT x2y2z2 = x2y2 +
math::Pow2( c.z() - P[2] );
343 if ( x2y2z2 >= max2 || (!accessor.probeValue(c,v) && v<ValueT(0)) )
345 if ( x2y2z2 <= min2 ) {
346 accessor.setValueOff(c, inside);
350 const ValueT d = local::DualTrait<ValueT>::merge(dx*(
math::Sqrt(x2y2z2) - R),
id);
351 if (d < v) accessor.setValue(c, d);
361 void rasterSpheres(
const tbb::blocked_range<size_t> &r)
363 Accessor accessor = mGrid->getAccessor();
364 const RealT inv_dx = RealT(1)/mDx;
366 for (
Index32 id = r.begin(), e=r.end(); run &&
id != e; ++id) {
367 const RealT R = inv_dx*mPa->radius(
id);
368 if (this->ignoreParticle(R))
continue;
369 const Vec3R P = mGrid->transform().worldToIndex(mPa->pos(
id));
370 run = this->rasterSphere(P, R,
id, accessor);
384 void rasterTrails(
const tbb::blocked_range<size_t> &r,
387 Accessor accessor = mGrid->getAccessor();
388 const RealT inv_dx = RealT(1)/mDx, Rmin = mRmin;
390 for (
Index32 id = r.begin(), e=r.end(); run &&
id != e; ++id) {
391 const RealT R0 = inv_dx*mPa->radius(
id);
392 if (this->ignoreParticle(R0))
continue;
393 const Vec3R P0 = mGrid->transform().worldToIndex(mPa->pos(
id)),
394 V = inv_dx*mPa->vel(
id);
395 const RealT speed = V.
length(), inv_speed=1.0/speed;
396 const Vec3R N = -V*inv_speed;
399 for (
size_t m=0; run && d < speed ; ++m) {
400 run = this->rasterSphere(P, R,
id, accessor);
403 R = R0-(R0-Rmin)*d*inv_speed;
414 template <
typename RealT>
424 RealT
dist()
const {
return mDist; }
439 template <
typename RealT>
440 inline std::ostream& operator<<(std::ostream& ostr, const Dual<RealT>& rhs)
446 template <
typename RealT>
452 template <
typename T>
467 template<
typename LevelSetGridT,
468 typename ParticleListT,
473 typedef typename LevelSetGridT::ValueType
RealT;
476 typedef typename RealTreeT::template ValueConverter<DualT>::Type
DualTreeT;
483 mDualGrid(
DualT(ls.background()))
485 mDualGrid.setGridClass(ls.getGridClass());
486 mDualGrid.setTransform(ls.transformPtr());
487 mRaster =
new RasterT(mDualGrid, interrupter);
527 mRaster->rasterizeSpheres(pa);
528 return this->extract();
547 mRaster->rasterizeTrails(pa, delta);
548 return this->extract();
556 ParticlesToLevelSetAndId& operator=(
const ParticlesToLevelSetAndId& rhs)
561 typename IndxGridT::Ptr extract()
565 const DualTreeT& dualTree = mDualGrid.tree();
567 typename IndxGridT::Ptr indxGrid =
typename IndxGridT::Ptr(
new IndxGridT(indxTree));
568 indxGrid->setTransform(mDualGrid.transformPtr());
569 typename RealTreeT::Ptr realTree(
new RealTreeT(dualTree,mRealGrid.background(),
TopologyCopy()));
570 mRealGrid.setTree(realTree);
575 typedef typename DualGridT::TreeType::LeafCIter LeafIterT;
576 typedef typename DualGridT::TreeType::LeafNodeType LeafT;
577 typedef typename LevelSetGridT::TreeType::LeafNodeType RealLeafT;
578 typedef typename IndxGridT::TreeType::LeafNodeType IndxLeafT;
579 RealTreeT& realTreeRef = *realTree;
580 IndxTreeT& indxTreeRef = *indxTree;
581 for (LeafIterT n = mDualGrid.tree().cbeginLeaf(); n; ++n) {
582 const LeafT& leaf = *n;
583 const Coord xyz = leaf.getOrigin();
585 RealLeafT& i = *realTreeRef.probeLeaf(xyz);
586 IndxLeafT& j = *indxTreeRef.probeLeaf(xyz);
587 for (
typename LeafT::ValueOnCIter m=leaf.cbeginValueOn(); m; ++m) {
589 const Index k = m.pos();
591 i.setValueOnly(k, v.dist());
592 j.setValueOnly(k, v.id());
595 mRealGrid.signedFloodFill();
599 typedef ParticlesToLevelSet<DualGridT, ParticleListT, InterruptT, RealT> RasterT;
600 LevelSetGridT& mRealGrid;
609 #endif // OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED