35 #ifndef OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
36 #define OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED
38 #include <tbb/parallel_reduce.h>
39 #include <tbb/blocked_range.h>
40 #include <boost/bind.hpp>
41 #include <boost/function.hpp>
42 #include <openvdb/util/Util.h>
43 #include <openvdb/Types.h>
44 #include <openvdb/Grid.h>
45 #include <openvdb/math/Math.h>
46 #include <openvdb/math/Transform.h>
47 #include <openvdb/util/NullInterrupter.h>
109 template <
typename T>
113 static T
split(T dist) {
return dist; }
117 template<
typename GridT,
118 typename ParticleListT,
120 typename RealT =
typename GridT::ValueType>
141 mDx(grid.transform().voxelSize()[0]),
142 mHalfWidth(local::DualTrait<ValueT>::split(grid.background()) / mDx),
146 mInterrupter(interrupt),
151 if ( !mGrid->hasUniformVoxels() ) {
153 "The transform must have uniform scale for ParticlesToLevelSet to function!");
157 "ParticlesToLevelSet only supports level sets!"
158 "\nUse Grid::setGridClass(openvdb::GRID_LEVEL_SET)");
165 mGrid(new GridT(*other.mGrid, openvdb::
ShallowCopy())),
168 mHalfWidth(other.mHalfWidth),
171 mGrainSize(other.mGrainSize),
173 mInterrupter(other.mInterrupter),
214 void rasterizeSpheres(
const ParticleListT& pa)
217 if (mInterrupter) mInterrupter->start(
"Rasterizing particles to level set using spheres");
218 mTask = boost::bind(&ParticlesToLevelSet::rasterSpheres, _1, _2);
220 if (mInterrupter) mInterrupter->end();
238 void rasterizeTrails(
const ParticleListT& pa,
Real delta=1.0)
241 if (mInterrupter) mInterrupter->start(
"Rasterizing particles to level set using trails");
242 mTask = boost::bind(&ParticlesToLevelSet::rasterTrails, _1, _2, RealT(delta));
244 if (mInterrupter) mInterrupter->end();
252 void operator()(
const tbb::blocked_range<size_t>& r)
266 mMinCount += other.mMinCount;
267 mMaxCount += other.mMaxCount;
271 typedef typename GridT::ValueType ValueT;
272 typedef typename GridT::Accessor Accessor;
274 const tbb::blocked_range<size_t>&)> FuncType;
276 const ParticleListT* mPa;
278 const RealT mHalfWidth;
283 InterruptT* mInterrupter;
284 size_t mMinCount, mMaxCount;
290 tbb::parallel_reduce(tbb::blocked_range<size_t>(0,mPa->size(),mGrainSize), *
this);
292 (*this)(tbb::blocked_range<size_t>(0, mPa->size()));
296 inline bool ignoreParticle(RealT R)
323 inline bool rasterSphere(
const Vec3R &P, RealT R,
Index32 id, Accessor& accessor)
325 const ValueT inside = -mGrid->background();
326 const RealT dx = mDx;
327 const RealT
max = R + mHalfWidth;
334 for (
Coord c = a; c.
x() <= b.x(); ++c.x() ) {
337 tbb::task::self().cancel_group_execution();
341 for ( c.y() = a.y(); c.y() <= b.y(); ++c.y() ) {
343 for ( c.z() = a.z(); c.z() <= b.z(); ++c.z() ) {
344 RealT x2y2z2 = x2y2 +
math::Pow2( c.z() - P[2] );
345 if ( x2y2z2 >= max2 || (!accessor.probeValue(c,v) && v<ValueT(0)) )
347 if ( x2y2z2 <= min2 ) {
348 accessor.setValueOff(c, inside);
352 const ValueT d = local::DualTrait<ValueT>::merge(dx*(
math::Sqrt(x2y2z2) - R),
id);
353 if (d < v) accessor.setValue(c, d);
363 void rasterSpheres(
const tbb::blocked_range<size_t> &r)
365 Accessor accessor = mGrid->getAccessor();
366 const RealT inv_dx = RealT(1)/mDx;
368 for (
Index32 id = r.begin(), e=r.end(); run &&
id != e; ++id) {
369 const RealT R = inv_dx*mPa->radius(
id);
370 if (this->ignoreParticle(R))
continue;
371 const Vec3R P = mGrid->transform().worldToIndex(mPa->pos(
id));
372 run = this->rasterSphere(P, R,
id, accessor);
386 void rasterTrails(
const tbb::blocked_range<size_t> &r,
389 Accessor accessor = mGrid->getAccessor();
390 const RealT inv_dx = RealT(1)/mDx, Rmin = mRmin;
392 for (
Index32 id = r.begin(), e=r.end(); run &&
id != e; ++id) {
393 const RealT R0 = inv_dx*mPa->radius(
id);
394 if (this->ignoreParticle(R0))
continue;
395 const Vec3R P0 = mGrid->transform().worldToIndex(mPa->pos(
id)),
396 V = inv_dx*mPa->vel(
id);
397 const RealT speed = V.
length(), inv_speed=1.0/speed;
398 const Vec3R N = -V*inv_speed;
401 for (
size_t m=0; run && d < speed ; ++m) {
402 run = this->rasterSphere(P, R,
id, accessor);
405 R = R0-(R0-Rmin)*d*inv_speed;
416 template <
typename RealT>
426 RealT
dist()
const {
return mDist; }
441 template <
typename RealT>
442 inline std::ostream& operator<<(std::ostream& ostr, const Dual<RealT>& rhs)
448 template <
typename RealT>
454 template <
typename T>
469 template<
typename LevelSetGridT,
470 typename ParticleListT,
475 typedef typename LevelSetGridT::ValueType
RealT;
478 typedef typename RealTreeT::template ValueConverter<DualT>::Type
DualTreeT;
485 mDualGrid(
DualT(ls.background()))
487 mDualGrid.setGridClass(ls.getGridClass());
488 mDualGrid.setTransform(ls.transformPtr());
489 mRaster =
new RasterT(mDualGrid, interrupter);
529 mRaster->rasterizeSpheres(pa);
530 return this->extract();
549 mRaster->rasterizeTrails(pa, delta);
550 return this->extract();
558 ParticlesToLevelSetAndId& operator=(
const ParticlesToLevelSetAndId& rhs)
563 typename IndxGridT::Ptr extract()
567 const DualTreeT& dualTree = mDualGrid.tree();
569 typename IndxGridT::Ptr indxGrid =
typename IndxGridT::Ptr(
new IndxGridT(indxTree));
570 indxGrid->setTransform(mDualGrid.transformPtr());
571 typename RealTreeT::Ptr realTree(
new RealTreeT(dualTree,mRealGrid.background(),
TopologyCopy()));
572 mRealGrid.setTree(realTree);
577 typedef typename DualGridT::TreeType::LeafCIter LeafIterT;
578 typedef typename DualGridT::TreeType::LeafNodeType LeafT;
579 typedef typename LevelSetGridT::TreeType::LeafNodeType RealLeafT;
580 typedef typename IndxGridT::TreeType::LeafNodeType IndxLeafT;
581 RealTreeT& realTreeRef = *realTree;
582 IndxTreeT& indxTreeRef = *indxTree;
583 for (LeafIterT n = mDualGrid.tree().cbeginLeaf(); n; ++n) {
584 const LeafT& leaf = *n;
585 const Coord xyz = leaf.getOrigin();
587 RealLeafT& i = *realTreeRef.probeLeaf(xyz);
588 IndxLeafT& j = *indxTreeRef.probeLeaf(xyz);
589 for (
typename LeafT::ValueOnCIter m=leaf.cbeginValueOn(); m; ++m) {
591 const Index k = m.pos();
593 i.setValueOnly(k, v.dist());
594 j.setValueOnly(k, v.id());
597 mRealGrid.signedFloodFill();
601 typedef ParticlesToLevelSet<DualGridT, ParticleListT, InterruptT, RealT> RasterT;
602 LevelSetGridT& mRealGrid;
611 #endif // OPENVDB_TOOLS_PARTICLES_TO_LEVELSET_HAS_BEEN_INCLUDED