39 #ifndef OPENVDB_TOOLS_LEVEL_SET_TRACKER_HAS_BEEN_INCLUDED
40 #define OPENVDB_TOOLS_LEVEL_SET_TRACKER_HAS_BEEN_INCLUDED
42 #include <tbb/parallel_reduce.h>
43 #include <tbb/parallel_for.h>
44 #include <boost/bind.hpp>
45 #include <boost/function.hpp>
46 #include <boost/type_traits/is_floating_point.hpp>
47 #include <openvdb/openvdb.h>
48 #include <openvdb/Types.h>
49 #include <openvdb/math/Math.h>
50 #include <openvdb/math/FiniteDifference.h>
51 #include <openvdb/math/Operators.h>
52 #include <openvdb/math/Stencils.h>
53 #include <openvdb/math/Transform.h>
54 #include <openvdb/Grid.h>
55 #include <openvdb/util/NullInterrupter.h>
64 template<
typename Gr
idT,
typename InterruptT = util::NullInterrupter>
70 typedef typename TreeType::LeafNodeType
LeafType;
75 BOOST_STATIC_ASSERT(boost::is_floating_point<ValueType>::value);
120 void startInterrupter(
const char* msg);
121 void endInterrupter();
123 bool checkInterrupter();
131 if (mTask) mTask(const_cast<LevelSetTracker*>(
this), r);
144 typedef typename boost::function<void (Normalizer*, const RangeType&)>
FuncType;
147 void cook(
int swapBuffer=0);
154 template<
typename,
typename,
typename>
167 typedef typename boost::function<void (LevelSetTracker*, const RangeType&)> FuncType;
171 template<math::BiasedGradientScheme SpatialScheme>
183 const bool mIsMaster;
190 template<
typename Gr
idT,
typename InterruptT>
194 mInterrupter(interrupt),
195 mDx(grid.voxelSize()[0]),
197 mTemporalScheme(math::
TVD_RK1),
203 if ( !grid.hasUniformVoxels() ) {
205 "The transform must have uniform scale for the LevelSetTracker to function");
209 "LevelSetTracker only supports level sets!\n"
210 "However, only level sets are guaranteed to work!\n"
211 "Hint: Grid::setGridClass(openvdb::GRID_LEVEL_SET)");
215 template<
typename Gr
idT,
typename InterruptT>
219 mInterrupter(other.mInterrupter),
221 mSpatialScheme(other.mSpatialScheme),
222 mTemporalScheme(other.mTemporalScheme),
223 mNormCount(other.mNormCount),
224 mGrainSize(other.mGrainSize),
230 template<
typename Gr
idT,
typename InterruptT>
234 this->startInterrupter(
"Pruning Level Set");
236 mTask = boost::bind(&LevelSetTracker::trim, _1, _2);
238 tbb::parallel_for(
mLeafs->getRange(mGrainSize), *
this);
240 (*this)(
mLeafs->getRange());
244 mGrid.tree().pruneLevelSet();
248 this->endInterrupter();
251 template<
typename Gr
idT,
typename InterruptT>
267 template<
typename Gr
idT,
typename InterruptT>
271 if (mInterrupter) mInterrupter->start(msg);
274 template<
typename Gr
idT,
typename InterruptT>
278 if (mInterrupter) mInterrupter->end();
281 template<
typename Gr
idT,
typename InterruptT>
286 tbb::task::self().cancel_group_execution();
293 template<
typename Gr
idT,
typename InterruptT>
297 typedef typename LeafType::ValueOnIter VoxelIterT;
299 const ValueType gamma = mGrid.background();
300 for (
size_t n=range.begin(), e=range.end(); n != e; ++n) {
301 LeafType &leaf =
mLeafs->leaf(n);
302 for (VoxelIterT iter = leaf.beginValueOn(); iter; ++iter) {
303 const ValueType val = *iter;
305 leaf.setValueOff(iter.pos(), -gamma);
306 else if (val > gamma)
307 leaf.setValueOff(iter.pos(), gamma);
312 template<
typename Gr
idT,
typename InterruptT>
316 switch (mSpatialScheme) {
318 this->normalize1<math::FIRST_BIAS >();
break;
320 this->normalize1<math::SECOND_BIAS >();
break;
322 this->normalize1<math::THIRD_BIAS >();
break;
324 this->normalize1<math::WENO5_BIAS >();
break;
326 this->normalize1<math::HJWENO5_BIAS>();
break;
332 template<
typename Gr
idT,
typename InterruptT>
333 template<math::BiasedGradientScheme SpatialScheme>
337 switch (mTemporalScheme) {
339 this->normalize2<SpatialScheme, math::TVD_RK1>();
break;
341 this->normalize2<SpatialScheme, math::TVD_RK2>();
break;
343 this->normalize2<SpatialScheme, math::TVD_RK3>();
break;
349 template<
typename Gr
idT,
typename InterruptT>
353 LevelSetTracker<GridT, InterruptT>::normalize2()
355 Normalizer<SpatialScheme, TemporalScheme> tmp(*
this);
359 template<
typename Gr
idT,
typename InterruptT>
367 mTracker.mLeafs->rebuildAuxBuffers(TemporalScheme ==
math::TVD_RK3 ? 2 : 1);
370 TemporalScheme ==
math::TVD_RK2 ? ValueType(0.9) : ValueType(1.0))
371 * ValueType(mTracker.voxelSize());
373 for (
int n=0, e=mTracker.getNormCount(); n < e; ++n) {
375 switch(TemporalScheme) {
380 mTask = boost::bind(&Normalizer::euler1, _1, _2, dt, 1);
388 mTask = boost::bind(&Normalizer::euler1, _1, _2, dt, 1);
394 mTask = boost::bind(&Normalizer::euler2,
395 _1, _2, dt, ValueType(0.5), 1, 1);
403 mTask = boost::bind(&Normalizer::euler1, _1, _2, dt, 1);
409 mTask = boost::bind(&Normalizer::euler2,
410 _1, _2, dt, ValueType(0.75), 1, 2);
416 mTask = boost::bind(&Normalizer::euler2,
417 _1, _2, dt, ValueType(1.0/3.0), 1, 2);
425 mTracker.mLeafs->removeAuxBuffers();
430 template<
typename Gr
idT,
typename InterruptT>
439 if (mTracker.getGrainSize()>0) {
440 tbb::parallel_for(mTracker.mLeafs->getRange(mTracker.getGrainSize()), *
this);
442 (*this)(mTracker.mLeafs->getRange());
445 mTracker.mLeafs->swapLeafBuffer(swapBuffer, mTracker.getGrainSize()==0);
447 mTracker.endInterrupter();
454 template<
typename Gr
idT,
typename InterruptT>
462 typedef typename Scheme::template ISStencil<GridType>::StencilType Stencil;
463 typedef typename LeafType::ValueOnCIter VoxelIterT;
464 mTracker.checkInterrupter();
465 const ValueType one(1.0), invDx = one/mTracker.voxelSize();
466 Stencil stencil(mTracker.grid());
467 for (
size_t n=range.begin(), e=range.end(); n != e; ++n) {
468 BufferType& result = mTracker.mLeafs->getBuffer(n, resultBuffer);
469 const LeafType& leaf = mTracker.mLeafs->leaf(n);
470 for (VoxelIterT iter = leaf.cbeginValueOn(); iter; ++iter) {
471 stencil.moveTo(iter);
474 const ValueType phi0 = stencil.getValue();
477 result.setValue(iter.pos(), phi0 - dt * S * diff);
482 template<
typename Gr
idT,
typename InterruptT>
490 typedef typename Scheme::template ISStencil<GridType>::StencilType Stencil;
491 typedef typename LeafType::ValueOnCIter VoxelIterT;
492 mTracker.checkInterrupter();
493 const ValueType one(1.0), beta = one - alpha, invDx = one/mTracker.voxelSize();
494 Stencil stencil(mTracker.grid());
495 for (
size_t n=range.begin(), e=range.end(); n != e; ++n) {
496 const BufferType& phi = mTracker.mLeafs->getBuffer(n, phiBuffer);
497 BufferType& result = mTracker.mLeafs->getBuffer(n, resultBuffer);
498 const LeafType& leaf = mTracker.mLeafs->leaf(n);
499 for (VoxelIterT iter = leaf.cbeginValueOn(); iter; ++iter) {
500 stencil.moveTo(iter);
503 const ValueType phi0 = stencil.getValue();
506 result.setValue(iter.pos(), alpha*phi[iter.pos()] + beta*(phi0 - dt * S * diff));
516 #endif // OPENVDB_TOOLS_LEVEL_SET_TRACKER_HAS_BEEN_INCLUDED