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/Types.h>
48 #include <openvdb/math/Math.h>
49 #include <openvdb/math/FiniteDifference.h>
50 #include <openvdb/math/Operators.h>
51 #include <openvdb/math/Stencils.h>
52 #include <openvdb/math/Transform.h>
53 #include <openvdb/Grid.h>
54 #include <openvdb/util/NullInterrupter.h>
63 template<
typename Gr
idT,
typename InterruptT = util::NullInterrupter>
69 typedef typename TreeType::LeafNodeType
LeafType;
74 BOOST_STATIC_ASSERT(boost::is_floating_point<ValueType>::value);
119 void startInterrupter(
const char* msg);
120 void endInterrupter();
122 bool checkInterrupter();
130 if (mTask) mTask(const_cast<LevelSetTracker*>(
this), r);
143 typedef typename boost::function<void (Normalizer*, const RangeType&)>
FuncType;
146 void cook(
int swapBuffer=0);
153 template<
typename,
typename,
typename>
166 typedef typename boost::function<void (LevelSetTracker*, const RangeType&)> FuncType;
170 template<math::BiasedGradientScheme SpatialScheme>
182 const bool mIsMaster;
189 template<
typename Gr
idT,
typename InterruptT>
193 mInterrupter(interrupt),
194 mDx(grid.voxelSize()[0]),
196 mTemporalScheme(math::
TVD_RK1),
202 if ( !grid.hasUniformVoxels() ) {
204 "The transform must have uniform scale for the LevelSetTracker to function");
208 "LevelSetTracker only supports level sets!\n"
209 "However, only level sets are guaranteed to work!\n"
210 "Hint: Grid::setGridClass(openvdb::GRID_LEVEL_SET)");
214 template<
typename Gr
idT,
typename InterruptT>
217 mLeafs(other.mLeafs),
218 mInterrupter(other.mInterrupter),
220 mSpatialScheme(other.mSpatialScheme),
221 mTemporalScheme(other.mTemporalScheme),
222 mNormCount(other.mNormCount),
223 mGrainSize(other.mGrainSize),
229 template<
typename Gr
idT,
typename InterruptT>
233 this->startInterrupter(
"Pruning Level Set");
235 mTask = boost::bind(&LevelSetTracker::trim, _1, _2);
237 tbb::parallel_for(mLeafs->getRange(mGrainSize), *
this);
239 (*this)(mLeafs->getRange());
243 mGrid.tree().pruneLevelSet();
246 mLeafs->rebuildLeafArray();
247 this->endInterrupter();
250 template<
typename Gr
idT,
typename InterruptT>
264 template<
typename Gr
idT,
typename InterruptT>
268 if (mInterrupter) mInterrupter->start(msg);
271 template<
typename Gr
idT,
typename InterruptT>
275 if (mInterrupter) mInterrupter->end();
278 template<
typename Gr
idT,
typename InterruptT>
283 tbb::task::self().cancel_group_execution();
290 template<
typename Gr
idT,
typename InterruptT>
294 typedef typename LeafType::ValueOnIter VoxelIterT;
296 const ValueType gamma = mGrid.background();
297 for (
size_t n=range.begin(), e=range.end(); n != e; ++n) {
298 LeafType &leaf = mLeafs->leaf(n);
299 for (VoxelIterT iter = leaf.beginValueOn(); iter; ++iter) {
300 const ValueType val = *iter;
302 leaf.setValueOff(iter.pos(), -gamma);
303 else if (val > gamma)
304 leaf.setValueOff(iter.pos(), gamma);
309 template<
typename Gr
idT,
typename InterruptT>
313 switch (mSpatialScheme) {
315 this->normalize1<math::FIRST_BIAS >();
break;
317 this->normalize1<math::SECOND_BIAS >();
break;
319 this->normalize1<math::THIRD_BIAS >();
break;
321 this->normalize1<math::WENO5_BIAS >();
break;
323 this->normalize1<math::HJWENO5_BIAS>();
break;
329 template<
typename Gr
idT,
typename InterruptT>
330 template<math::BiasedGradientScheme SpatialScheme>
334 switch (mTemporalScheme) {
336 this->normalize2<SpatialScheme, math::TVD_RK1>();
break;
338 this->normalize2<SpatialScheme, math::TVD_RK2>();
break;
340 this->normalize2<SpatialScheme, math::TVD_RK3>();
break;
346 template<
typename Gr
idT,
typename InterruptT>
350 LevelSetTracker<GridT, InterruptT>::normalize2()
352 Normalizer<SpatialScheme, TemporalScheme> tmp(*
this);
356 template<
typename Gr
idT,
typename InterruptT>
364 mTracker.mLeafs->rebuildAuxBuffers(TemporalScheme ==
math::TVD_RK3 ? 2 : 1);
367 TemporalScheme ==
math::TVD_RK2 ? ValueType(0.9) : ValueType(1.0))
368 * ValueType(mTracker.voxelSize());
370 for (
int n=0, e=mTracker.getNormCount(); n < e; ++n) {
372 switch(TemporalScheme) {
377 mTask = boost::bind(&Normalizer::euler1, _1, _2, dt, 1);
385 mTask = boost::bind(&Normalizer::euler1, _1, _2, dt, 1);
391 mTask = boost::bind(&Normalizer::euler2,
392 _1, _2, dt, ValueType(0.5), 1, 1);
400 mTask = boost::bind(&Normalizer::euler1, _1, _2, dt, 1);
406 mTask = boost::bind(&Normalizer::euler2,
407 _1, _2, dt, ValueType(0.75), 1, 2);
413 mTask = boost::bind(&Normalizer::euler2,
414 _1, _2, dt, ValueType(1.0/3.0), 1, 2);
422 mTracker.mLeafs->removeAuxBuffers();
427 template<
typename Gr
idT,
typename InterruptT>
436 if (mTracker.getGrainSize()>0) {
437 tbb::parallel_for(mTracker.mLeafs->getRange(mTracker.getGrainSize()), *
this);
439 (*this)(mTracker.mLeafs->getRange());
442 mTracker.mLeafs->swapLeafBuffer(swapBuffer, mTracker.getGrainSize()==0);
444 mTracker.endInterrupter();
451 template<
typename Gr
idT,
typename InterruptT>
459 typedef typename Scheme::template ISStencil<GridType>::StencilType Stencil;
460 typedef typename LeafType::ValueOnCIter VoxelIterT;
461 mTracker.checkInterrupter();
462 const ValueType one(1.0), invDx = one/mTracker.voxelSize();
463 Stencil stencil(mTracker.grid());
464 for (
size_t n=range.begin(), e=range.end(); n != e; ++n) {
465 BufferType& result = mTracker.mLeafs->getBuffer(n, resultBuffer);
466 const LeafType& leaf = mTracker.mLeafs->leaf(n);
467 for (VoxelIterT iter = leaf.cbeginValueOn(); iter; ++iter) {
468 stencil.moveTo(iter);
471 const ValueType phi0 = stencil.getValue();
474 result.setValue(iter.pos(), phi0 - dt * S * diff);
479 template<
typename Gr
idT,
typename InterruptT>
487 typedef typename Scheme::template ISStencil<GridType>::StencilType Stencil;
488 typedef typename LeafType::ValueOnCIter VoxelIterT;
489 mTracker.checkInterrupter();
490 const ValueType one(1.0), beta = one - alpha, invDx = one/mTracker.voxelSize();
491 Stencil stencil(mTracker.grid());
492 for (
size_t n=range.begin(), e=range.end(); n != e; ++n) {
493 const BufferType& phi = mTracker.mLeafs->getBuffer(n, phiBuffer);
494 BufferType& result = mTracker.mLeafs->getBuffer(n, resultBuffer);
495 const LeafType& leaf = mTracker.mLeafs->leaf(n);
496 for (VoxelIterT iter = leaf.cbeginValueOn(); iter; ++iter) {
497 stencil.moveTo(iter);
500 const ValueType phi0 = stencil.getValue();
503 result.setValue(iter.pos(), alpha*phi[iter.pos()] + beta*(phi0 - dt * S * diff));
512 #endif // OPENVDB_TOOLS_LEVEL_SET_TRACKER_HAS_BEEN_INCLUDED