OpenVDB: VolumeAdvect.h Source File

OpenVDB 5.0.0

VolumeAdvect.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2017 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 //
32 //
39
40 #ifndef OPENVDB_TOOLS_VOLUME_ADVECT_HAS_BEEN_INCLUDED
41 #define OPENVDB_TOOLS_VOLUME_ADVECT_HAS_BEEN_INCLUDED
42
43 #include <tbb/parallel_for.h>
44 #include <openvdb/Types.h>
45 #include <openvdb/math/Math.h>
46 #include <openvdb/util/NullInterrupter.h>
47 #include "Interpolation.h"// for Sampler
48 #include "VelocityFields.h" // for VelocityIntegrator
49 #include "Morphology.h"//for dilateActiveValues and dilateVoxels
50 #include "Prune.h"// for prune
51 #include "Statistics.h" // for extrema
52 #include <functional>
53
54
55 namespace openvdb {
56 OPENVDB_USE_VERSION_NAMESPACE
57 namespace OPENVDB_VERSION_NAME {
58 namespace tools {
59
60 namespace Scheme {
62 enum SemiLagrangian { SEMI, MID, RK3, RK4, MAC, BFECC };
65 enum Limiter { NO_LIMITER, CLAMP, REVERT };
66 }
67
95
96 template<typename VelocityGridT = Vec3fGrid,
97 bool StaggeredVelocity = false,
98 typename InterrupterType = util::NullInterrupter>
99 class VolumeAdvection
100 {
101 public:
102
110 VolumeAdvection(const VelocityGridT& velGrid, InterrupterType* interrupter = nullptr)
111 : mVelGrid(velGrid)
112 , mInterrupter(interrupter)
113 , mIntegrator( Scheme::SEMI )
114 , mLimiter( Scheme::CLAMP )
115 , mGrainSize( 128 )
116 , mSubSteps( 1 )
117 {
118 math::Extrema e = extrema(velGrid.cbeginValueAll(), /*threading*/true);
119 e.add(velGrid.background().length());
120 mMaxVelocity = e.max();
121 }
122
123 virtual ~VolumeAdvection()
124 {
125 }
126
132 int spatialOrder() const { return (mIntegrator == Scheme::MAC ||
133 mIntegrator == Scheme::BFECC) ? 2 : 1; }
134
140 int temporalOrder() const {
141 switch (mIntegrator) {
142 case Scheme::SEMI: return 1;
143 case Scheme::MID: return 2;
144 case Scheme::RK3: return 3;
145 case Scheme::RK4: return 4;
146 case Scheme::BFECC:return 2;
147 case Scheme::MAC: return 2;
148 }
149 return 0;//should never reach this point
150 }
151
153 void setIntegrator(Scheme::SemiLagrangian integrator) { mIntegrator = integrator; }
154
156 Scheme::SemiLagrangian getIntegrator() const { return mIntegrator; }
157
159 void setLimiter(Scheme::Limiter limiter) { mLimiter = limiter; }
160
162 Scheme::Limiter getLimiter() const { return mLimiter; }
163
166 bool isLimiterOn() const { return this->spatialOrder()>1 &&
167 mLimiter != Scheme::NO_LIMITER; }
168
171 size_t getGrainSize() const { return mGrainSize; }
172
177 void setGrainSize(size_t grainsize) { mGrainSize = grainsize; }
178
181 int getSubSteps() const { return mSubSteps; }
182
188 void setSubSteps(int substeps) { mSubSteps = math::Max(1, substeps); }
189
192 double getMaxVelocity() const { return mMaxVelocity; }
193
204 template<typename VolumeGridT>
205 int getMaxDistance(const VolumeGridT& inGrid, double dt) const
206 {
207 if (!inGrid.hasUniformVoxels()) {
208 OPENVDB_THROW(RuntimeError, "Volume grid does not have uniform voxels!");
209 }
210 const double d = mMaxVelocity*math::Abs(dt)/inGrid.voxelSize()[0];
211 return static_cast<int>( math::RoundUp(d) );
212 }
213
232 template<typename VolumeGridT,
233 typename VolumeSamplerT>//only C++11 allows for a default argument
234 typename VolumeGridT::Ptr advect(const VolumeGridT& inGrid, double timeStep)
235 {
236 typename VolumeGridT::Ptr outGrid = inGrid.deepCopy();
237 const double dt = timeStep/mSubSteps;
238 const int n = this->getMaxDistance(inGrid, dt);
239 dilateActiveValues( outGrid->tree(), n, NN_FACE, EXPAND_TILES);
240 this->template cook<VolumeGridT, VolumeSamplerT>(*outGrid, inGrid, dt);
241 for (int step = 1; step < mSubSteps; ++step) {
242 typename VolumeGridT::Ptr tmpGrid = outGrid->deepCopy();
243 dilateActiveValues( tmpGrid->tree(), n, NN_FACE, EXPAND_TILES);
244 this->template cook<VolumeGridT, VolumeSamplerT>(*tmpGrid, *outGrid, dt);
245 outGrid.swap( tmpGrid );
246 }
247
248 return outGrid;
249 }
250
278 template<typename VolumeGridT,
279 typename MaskGridT,
280 typename VolumeSamplerT>//only C++11 allows for a default argument
281 typename VolumeGridT::Ptr advect(const VolumeGridT& inGrid, const MaskGridT& mask, double timeStep)
282 {
283 if (inGrid.transform() != mask.transform()) {
284 OPENVDB_THROW(RuntimeError, "Volume grid and mask grid are misaligned! Consider "
285 "resampling either of the two grids into the index space of the other.");
286 }
287 typename VolumeGridT::Ptr outGrid = inGrid.deepCopy();
288 const double dt = timeStep/mSubSteps;
289 const int n = this->getMaxDistance(inGrid, dt);
290 dilateActiveValues( outGrid->tree(), n, NN_FACE, EXPAND_TILES);
291 outGrid->topologyIntersection( mask );
292 pruneInactive( outGrid->tree(), mGrainSize>0, mGrainSize );
293 this->template cook<VolumeGridT, VolumeSamplerT>(*outGrid, inGrid, dt);
294 outGrid->topologyUnion( inGrid );
295
296 for (int step = 1; step < mSubSteps; ++step) {
297 typename VolumeGridT::Ptr tmpGrid = outGrid->deepCopy();
298 dilateActiveValues( tmpGrid->tree(), n, NN_FACE, EXPAND_TILES);
299 tmpGrid->topologyIntersection( mask );
300 pruneInactive( tmpGrid->tree(), mGrainSize>0, mGrainSize );
301 this->template cook<VolumeGridT, VolumeSamplerT>(*tmpGrid, *outGrid, dt);
302 tmpGrid->topologyUnion( inGrid );
303 outGrid.swap( tmpGrid );
304 }
305 return outGrid;
306 }
307
308 private:
309 // disallow copy construction and copy by assignment!
310 VolumeAdvection(const VolumeAdvection&);// not implemented
311 VolumeAdvection& operator=(const VolumeAdvection&);// not implemented
312
313 void start(const char* str) const
314 {
315 if (mInterrupter) mInterrupter->start(str);
316 }
317 void stop() const
318 {
319 if (mInterrupter) mInterrupter->end();
320 }
321 bool interrupt() const
322 {
323 if (mInterrupter && util::wasInterrupted(mInterrupter)) {
324 tbb::task::self().cancel_group_execution();
325 return true;
326 }
327 return false;
328 }
329
330 template<typename VolumeGridT, typename VolumeSamplerT>
331 void cook(VolumeGridT& outGrid, const VolumeGridT& inGrid, double dt)
332 {
333 switch (mIntegrator) {
334 case Scheme::SEMI: {
335 Advect<VolumeGridT, 1, VolumeSamplerT> adv(inGrid, *this);
336 adv.cook(outGrid, dt);
337 break;
338 }
339 case Scheme::MID: {
340 Advect<VolumeGridT, 2, VolumeSamplerT> adv(inGrid, *this);
341 adv.cook(outGrid, dt);
342 break;
343 }
344 case Scheme::RK3: {
345 Advect<VolumeGridT, 3, VolumeSamplerT> adv(inGrid, *this);
346 adv.cook(outGrid, dt);
347 break;
348 }
349 case Scheme::RK4: {
350 Advect<VolumeGridT, 4, VolumeSamplerT> adv(inGrid, *this);
351 adv.cook(outGrid, dt);
352 break;
353 }
354 case Scheme::BFECC: {
355 Advect<VolumeGridT, 1, VolumeSamplerT> adv(inGrid, *this);
356 adv.cook(outGrid, dt);
357 break;
358 }
359 case Scheme::MAC: {
360 Advect<VolumeGridT, 1, VolumeSamplerT> adv(inGrid, *this);
361 adv.cook(outGrid, dt);
362 break;
363 }
364 default:
365 OPENVDB_THROW(ValueError, "Spatial difference scheme not supported!");
366 }
367 pruneInactive(outGrid.tree(), mGrainSize>0, mGrainSize);
368 }
369
370 // Private class that implements the multi-threaded advection
371 template<typename VolumeGridT, size_t OrderRK, typename SamplerT> struct Advect;
372
373 // Private member data of VolumeAdvection
374 const VelocityGridT& mVelGrid;
375 double mMaxVelocity;
376 InterrupterType* mInterrupter;
377 Scheme::SemiLagrangian mIntegrator;
378 Scheme::Limiter mLimiter;
379 size_t mGrainSize;
380 int mSubSteps;
381 };//end of VolumeAdvection class
382
383 // Private class that implements the multi-threaded advection
384 template<typename VelocityGridT, bool StaggeredVelocity, typename InterrupterType>
385 template<typename VolumeGridT, size_t OrderRK, typename SamplerT>
386 struct VolumeAdvection<VelocityGridT, StaggeredVelocity, InterrupterType>::Advect
387 {
388 using TreeT = typename VolumeGridT::TreeType;
389 using AccT = typename VolumeGridT::ConstAccessor;
390 using ValueT = typename TreeT::ValueType;
391 using LeafManagerT = typename tree::LeafManager<TreeT>;
392 using LeafNodeT = typename LeafManagerT::LeafNodeType;
393 using LeafRangeT = typename LeafManagerT::LeafRange;
394 using VelocityIntegratorT = VelocityIntegrator<VelocityGridT, StaggeredVelocity>;
395 using RealT = typename VelocityIntegratorT::ElementType;
396 using VoxelIterT = typename TreeT::LeafNodeType::ValueOnIter;
397
398 Advect(const VolumeGridT& inGrid, const VolumeAdvection& parent)
399 : mTask(0)
400 , mInGrid(&inGrid)
401 , mVelocityInt(parent.mVelGrid)
402 , mParent(&parent)
403 {
404 }
405 inline void cook(const LeafRangeT& range)
406 {
407 if (mParent->mGrainSize > 0) {
408 tbb::parallel_for(range, *this);
409 } else {
410 (*this)(range);
411 }
412 }
413 void operator()(const LeafRangeT& range) const
414 {
415 assert(mTask);
416 mTask(const_cast<Advect*>(this), range);
417 }
418 void cook(VolumeGridT& outGrid, double time_step)
419 {
420 namespace ph = std::placeholders;
421
422 mParent->start("Advecting volume");
423 LeafManagerT manager(outGrid.tree(), mParent->spatialOrder()==2 ? 1 : 0);
424 const LeafRangeT range = manager.leafRange(mParent->mGrainSize);
425 const RealT dt = static_cast<RealT>(-time_step);//method of characteristics backtracks
426 if (mParent->mIntegrator == Scheme::MAC) {
427 mTask = std::bind(&Advect::rk, ph::_1, ph::_2, dt, 0, mInGrid);//out[0]=forward
428 this->cook(range);
429 mTask = std::bind(&Advect::rk, ph::_1, ph::_2,-dt, 1, &outGrid);//out[1]=backward
430 this->cook(range);
431 mTask = std::bind(&Advect::mac, ph::_1, ph::_2);//out[0] = out[0] + (in[0] - out[1])/2
432 this->cook(range);
433 } else if (mParent->mIntegrator == Scheme::BFECC) {
434 mTask = std::bind(&Advect::rk, ph::_1, ph::_2, dt, 0, mInGrid);//out[0]=forward
435 this->cook(range);
436 mTask = std::bind(&Advect::rk, ph::_1, ph::_2,-dt, 1, &outGrid);//out[1]=backward
437 this->cook(range);
438 mTask = std::bind(&Advect::bfecc, ph::_1, ph::_2);//out[0] = (3*in[0] - out[1])/2
439 this->cook(range);
440 mTask = std::bind(&Advect::rk, ph::_1, ph::_2, dt, 1, &outGrid);//out[1]=forward
441 this->cook(range);
442 manager.swapLeafBuffer(1);// out[0] = out[1]
443 } else {// SEMI, MID, RK3 and RK4
444 mTask = std::bind(&Advect::rk, ph::_1, ph::_2, dt, 0, mInGrid);//forward
445 this->cook(range);
446 }
447
448 if (mParent->spatialOrder()==2) manager.removeAuxBuffers();
449
450 mTask = std::bind(&Advect::limiter, ph::_1, ph::_2, dt);// out[0] = limiter( out[0] )
451 this->cook(range);
452
453 mParent->stop();
454 }
455 // Last step of the MacCormack scheme: out[0] = out[0] + (in[0] - out[1])/2
456 void mac(const LeafRangeT& range) const
457 {
458 if (mParent->interrupt()) return;
459 assert( mParent->mIntegrator == Scheme::MAC );
460 AccT acc = mInGrid->getAccessor();
461 for (typename LeafRangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
462 ValueT* out0 = leafIter.buffer( 0 ).data();// forward
463 const ValueT* out1 = leafIter.buffer( 1 ).data();// backward
464 const LeafNodeT* leaf = acc.probeConstLeaf( leafIter->origin() );
465 if (leaf != nullptr) {
466 const ValueT* in0 = leaf->buffer().data();
467 for (VoxelIterT voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
468 const Index i = voxelIter.pos();
469 out0[i] += RealT(0.5) * ( in0[i] - out1[i] );
470 }
471 } else {
472 for (VoxelIterT voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
473 const Index i = voxelIter.pos();
474 out0[i] += RealT(0.5) * ( acc.getValue(voxelIter.getCoord()) - out1[i] );
475 }//loop over active voxels
476 }
477 }//loop over leaf nodes
478 }
479 // Intermediate step in the BFECC scheme: out[0] = (3*in[0] - out[1])/2
480 void bfecc(const LeafRangeT& range) const
481 {
482 if (mParent->interrupt()) return;
483 assert( mParent->mIntegrator == Scheme::BFECC );
484 AccT acc = mInGrid->getAccessor();
485 for (typename LeafRangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
486 ValueT* out0 = leafIter.buffer( 0 ).data();// forward
487 const ValueT* out1 = leafIter.buffer( 1 ).data();// backward
488 const LeafNodeT* leaf = acc.probeConstLeaf(leafIter->origin());
489 if (leaf != nullptr) {
490 const ValueT* in0 = leaf->buffer().data();
491 for (VoxelIterT voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
492 const Index i = voxelIter.pos();
493 out0[i] = RealT(0.5)*( RealT(3)*in0[i] - out1[i] );
494 }//loop over active voxels
495 } else {
496 for (VoxelIterT voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
497 const Index i = voxelIter.pos();
498 out0[i] = RealT(0.5)*( RealT(3)*acc.getValue(voxelIter.getCoord()) - out1[i] );
499 }//loop over active voxels
500 }
501 }//loop over leaf nodes
502 }
503 // Semi-Lagrangian integration with Runge-Kutta of various orders (1->4)
504 void rk(const LeafRangeT& range, RealT dt, size_t n, const VolumeGridT* grid) const
505 {
506 if (mParent->interrupt()) return;
507 const math::Transform& xform = mInGrid->transform();
508 AccT acc = grid->getAccessor();
509 for (typename LeafRangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
510 ValueT* phi = leafIter.buffer( n ).data();
511 for (VoxelIterT voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
512 ValueT& value = phi[voxelIter.pos()];
513 Vec3d wPos = xform.indexToWorld(voxelIter.getCoord());
514 mVelocityInt.template rungeKutta<OrderRK, Vec3d>(dt, wPos);
515 value = SamplerT::sample(acc, xform.worldToIndex(wPos));
516 }//loop over active voxels
517 }//loop over leaf nodes
518 }
519 void limiter(const LeafRangeT& range, RealT dt) const
520 {
521 if (mParent->interrupt()) return;
522 const bool doLimiter = mParent->isLimiterOn();
523 const bool doClamp = mParent->mLimiter == Scheme::CLAMP;
524 ValueT data[2][2][2], vMin, vMax;
525 const math::Transform& xform = mInGrid->transform();
526 AccT acc = mInGrid->getAccessor();
527 const ValueT backg = mInGrid->background();
528 for (typename LeafRangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
529 ValueT* phi = leafIter.buffer( 0 ).data();
530 for (VoxelIterT voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
531 ValueT& value = phi[voxelIter.pos()];
532
533 if ( doLimiter ) {
534 assert(OrderRK == 1);
535 Vec3d wPos = xform.indexToWorld(voxelIter.getCoord());
536 mVelocityInt.template rungeKutta<1, Vec3d>(dt, wPos);// Explicit Euler
537 Vec3d iPos = xform.worldToIndex(wPos);
538 Coord ijk = Coord::floor( iPos );
539 BoxSampler::getValues(data, acc, ijk);
540 BoxSampler::extrema(data, vMin, vMax);
541 if ( doClamp ) {
542 value = math::Clamp( value, vMin, vMax);
543 } else if (value < vMin || value > vMax ) {
544 iPos -= Vec3R(ijk[0], ijk[1], ijk[2]);//unit coordinates
545 value = BoxSampler::trilinearInterpolation( data, iPos );
546 }
547 }
548
549 if (math::isApproxEqual(value, backg, math::Delta<ValueT>::value())) {
550 value = backg;
551 leafIter->setValueOff( voxelIter.pos() );
552 }
553 }//loop over active voxels
554 }//loop over leaf nodes
555 }
556 // Public member data of the private Advect class
557
558 typename std::function<void (Advect*, const LeafRangeT&)> mTask;
559 const VolumeGridT* mInGrid;
560 const VelocityIntegratorT mVelocityInt;// lightweight!
561 const VolumeAdvection* mParent;
562 };// end of private member class Advect
563
564 } // namespace tools
565 } // namespace OPENVDB_VERSION_NAME
566 } // namespace openvdb
567
568 #endif // OPENVDB_TOOLS_VOLUME_ADVECT_HAS_BEEN_INCLUDED
569
570 // Copyright (c) 2012-2017 DreamWorks Animation LLC
571 // All rights reserved. This software is distributed under the
572 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
openvdb::v5_0::tools::pruneInactive
void pruneInactive(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with background tiles any nodes whose values are a...
Definition: Prune.h:381
openvdb::v5_0::util::NullInterrupter
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:52
openvdb::v5_0::tools::Scheme::MID
Definition: VolumeAdvect.h:62
openvdb::v5_0::math::Extrema::max
double max() const
Return the maximum value.
Definition: Stats.h:154
openvdb::v5_0::tools::extrema
math::Extrema extrema(const IterT &iter, bool threaded=true)
Iterate over a scalar grid and compute extrema (min/max) of the values of the voxels that are visited...
Definition: Statistics.h:379
Types.h
openvdb::v5_0::tools::Scheme::BFECC
Definition: VolumeAdvect.h:62
openvdb::v5_0::math::Max
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition: Math.h:545
NullInterrupter.h
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
openvdb::v5_0::tools::Scheme::Limiter
Limiter
Flux-limiters employed to stabalize the second-order advection schemes MacCormack and BFECC...
Definition: VolumeAdvect.h:65
VelocityFields.h
Defines two simple wrapper classes for advection velocity fields as well as VelocitySampler and Veloc...
openvdb::v5_0::tools::VolumeAdvection::getMaxDistance
int getMaxDistance(const VolumeGridT &inGrid, double dt) const
Definition: VolumeAdvect.h:205
openvdb::v5_0::math::Extrema
This class computes the minimum and maximum values of a population of floating-point values...
Definition: Stats.h:118
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:108
openvdb::v5_0::tools::VolumeAdvection::getGrainSize
size_t getGrainSize() const
Definition: VolumeAdvect.h:171
openvdb::v5_0::tools::Scheme::SEMI
Definition: VolumeAdvect.h:62
openvdb::v5_0::math::Coord::floor
static Coord floor(const Vec3< T > &xyz)
Return the largest integer coordinates that are not greater than xyz (node centered conversion)...
Definition: Coord.h:83
Statistics.h
Functions to efficiently compute histograms, extremas (min/max) and statistics (mean, variance, etc.) of grid values.
openvdb::v5_0::tools::VolumeAdvection::setIntegrator
void setIntegrator(Scheme::SemiLagrangian integrator)
Set the integrator (see details in the table above)
Definition: VolumeAdvect.h:153
openvdb::v5_0::math::RoundUp
float RoundUp(float x)
Return x rounded up to the nearest integer.
Definition: Math.h:737
openvdb::v5_0::math::Vec3d
Vec3< double > Vec3d
Definition: Vec3.h:679
openvdb::v5_0::tools::dilateActiveValues
void dilateActiveValues(TreeType &tree, int iterations=1, NearestNeighbors nn=NN_FACE, TilePolicy mode=PRESERVE_TILES)
Topologically dilate all active values (i.e. both voxels and tiles) in a tree using one of three near...
Definition: Morphology.h:1078
openvdb::v5_0::math::isApproxEqual
bool isApproxEqual(const Type &a, const Type &b)
Return true if a is equal to b to within the default floating-point comparison tolerance.
Definition: Math.h:354
openvdb::v5_0::Vec3R
math::Vec3< Real > Vec3R
Definition: Types.h:78
openvdb::v5_0::tools::Scheme::MAC
Definition: VolumeAdvect.h:62
openvdb::v5_0::math::Abs
Coord Abs(const Coord &xyz)
Definition: Coord.h:513
openvdb::v5_0::tools::VolumeAdvection::isLimiterOn
bool isLimiterOn() const
Return true if a limiter will be applied based on the current settings.
Definition: VolumeAdvect.h:166
openvdb::v5_0::tools::VolumeAdvection::getSubSteps
int getSubSteps() const
Definition: VolumeAdvect.h:181
openvdb::v5_0::tools::VolumeAdvection::~VolumeAdvection
virtual ~VolumeAdvection()
Definition: VolumeAdvect.h:123
openvdb::v5_0::tools::VolumeAdvection::getLimiter
Scheme::Limiter getLimiter() const
Retrun the limiter (see details above)
Definition: VolumeAdvect.h:162
Prune.h
Defined various multi-threaded utility functions for trees.
openvdb::v5_0::tools::Scheme::CLAMP
Definition: VolumeAdvect.h:65
openvdb::v5_0::tools::VolumeAdvection::setGrainSize
void setGrainSize(size_t grainsize)
Set the grain-size used for multi-threading.
Definition: VolumeAdvect.h:177
openvdb::v5_0::RuntimeError
Definition: Exceptions.h:89
openvdb::v5_0::math::Clamp
Type Clamp(Type x, Type min, Type max)
Return x clamped to [min, max].
Definition: Math.h:230
openvdb::v5_0::tools::Scheme::NO_LIMITER
Definition: VolumeAdvect.h:65
openvdb::v5_0::Index
Index32 Index
Definition: Types.h:60
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
openvdb::v5_0::tools::VolumeAdvection::setSubSteps
void setSubSteps(int substeps)
Set the number of sub-steps per integration.
Definition: VolumeAdvect.h:188
openvdb::v5_0::tools::VolumeAdvection
Performs advections of an arbitrary type of volume in a static velocity field. The advections are per...
Definition: VolumeAdvect.h:99
openvdb::v5_0::tools::VolumeAdvection::setLimiter
void setLimiter(Scheme::Limiter limiter)
Set the limiter (see details above)
Definition: VolumeAdvect.h:159
openvdb::v5_0::tools::Scheme::RK3
Definition: VolumeAdvect.h:62
Morphology.h
Implementation of morphological dilation and erosion.
openvdb::v5_0::tools::VolumeAdvection::getMaxVelocity
double getMaxVelocity() const
Return the maximum magnitude of the velocity in the advection velocity field defined during construct...
Definition: VolumeAdvect.h:192
openvdb::v5_0::tools::VolumeAdvection::spatialOrder
int spatialOrder() const
Return the spatial order of accuracy of the advection scheme.
Definition: VolumeAdvect.h:132
openvdb
Definition: Exceptions.h:39
openvdb::v5_0::math::Extrema::add
void add(double val)
Add a single sample.
Definition: Stats.h:132
openvdb::v5_0::tools::NN_FACE
Definition: Morphology.h:85
openvdb::v5_0::tools::VolumeAdvection::VolumeAdvection
VolumeAdvection(const VelocityGridT &velGrid, InterrupterType *interrupter=nullptr)
Constructor.
Definition: VolumeAdvect.h:110
openvdb::v5_0::tools::Scheme::RK4
Definition: VolumeAdvect.h:62
openvdb::v5_0::util::wasInterrupted
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
Interpolation.h
openvdb::v5_0::tools::VolumeAdvection::advect
VolumeGridT::Ptr advect(const VolumeGridT &inGrid, const MaskGridT &mask, double timeStep)
Definition: VolumeAdvect.h:281
openvdb::v5_0::tools::VolumeAdvection::advect
VolumeGridT::Ptr advect(const VolumeGridT &inGrid, double timeStep)
Definition: VolumeAdvect.h:234
openvdb::v5_0::Vec3fGrid
Vec3SGrid Vec3fGrid
Definition: openvdb.h:83
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
openvdb::v5_0::tools::Scheme::REVERT
Definition: VolumeAdvect.h:65
openvdb::v5_0::tools::EXPAND_TILES
Definition: Morphology.h:100
openvdb::v5_0::tools::VolumeAdvection::getIntegrator
Scheme::SemiLagrangian getIntegrator() const
Return the integrator (see details in the table above)
Definition: VolumeAdvect.h:156
openvdb::v5_0::tools::VolumeAdvection::temporalOrder
int temporalOrder() const
Return the temporal order of accuracy of the advection scheme.
Definition: VolumeAdvect.h:140
openvdb::v5_0::tools::Scheme::SemiLagrangian
SemiLagrangian
Numerical advections schemes.
Definition: VolumeAdvect.h:62