25#ifndef OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
26#define OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
45#include <tbb/blocked_range.h>
46#include <tbb/enumerable_thread_specific.h>
47#include <tbb/parallel_for.h>
60template<
typename TreeType>
182 template<Index Order>
232 template<Index Order>
234 template<Index Order>
244 template<Index Order>
254 template<Index Order>
290 void print(std::ostream& = std::cout,
int verboseLevel = 1)
const;
332 void topDownRestrict(
bool useInjection);
334 inline void initMeta();
347 template<Index Order>
351 template<
typename OpType>
struct CookOp;
354 std::vector<TreePtr> mTrees;
359template<
typename TreeType>
363 , mTransform(
math::Transform::createLinearTransform( voxelSize ))
366 for (
size_t i=0; i<levels; ++i) mTrees[i] =
TreePtr(
new TreeType(background));
369template<
typename TreeType>
377 mTrees[0].reset(
new TreeType(
grid.tree() ) );
378 mTrees[0]->voxelizeActiveTiles();
379 this->topDownRestrict(useInjection);
382template<
typename TreeType>
390 mTrees[0] =
grid->treePtr();
391 mTrees[0]->voxelizeActiveTiles();
393 this->topDownRestrict(useInjection);
396template<
typename TreeType>
401 return *mTrees[level];
404template<
typename TreeType>
409 return *mTrees[level];
412template<
typename TreeType>
417 return mTrees[level];
420template<
typename TreeType>
425 return mTrees[level];
428template<
typename TreeType>
434 if (level>0) xform->preScale(
Real(1 << level) );
435 grid->setTransform( xform );
438 std::stringstream ss;
439 ss << this->
getName() <<
"_level_" << level;
440 grid->setName( ss.str() );
444template<
typename TreeType>
446grid(
size_t level)
const
451template<
typename TreeType>
454createGrid(
float level,
size_t grainSize)
const
456 OPENVDB_ASSERT( level >= 0.0f && level <=
float(mTrees.size()-1) );
460 xform->preScale(
math::Pow(2.0f, level) );
461 grid->setTransform( xform );
464 std::stringstream ss;
465 ss << this->
getName() <<
"_level_" << level;
466 grid->setName( ss.str() );
468 if (
size_t(floorf(level)) ==
size_t(ceilf(level)) ) {
469 grid->setTree( this->
constTree(
size_t(floorf(level))).copy() );
471 FractionOp<Order> tmp(*
this,
grid->tree(), level, grainSize);
481template<
typename TreeType>
486 for (
size_t level=0; level<mTrees.size(); ++level)
grids->push_back(this->grid(level));
490template<
typename TreeType>
495 for (
size_t level=0; level<mTrees.size(); ++level)
grids->push_back(this->grid(level));
499template<
typename TreeType>
501xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
506template<
typename TreeType>
508xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level)
510 return in_xyz *
Real(1 << in_level) /
Real(1 << out_level);
513template<
typename TreeType>
515xyz(
const Vec3R& in_xyz,
double in_level,
double out_level)
517 return in_xyz *
math::Pow(2.0, in_level - out_level);
521template<
typename TreeType>
528 const ConstAccessor acc(*mTrees[out_level]);
532template<
typename TreeType>
539 const ConstAccessor acc(*mTrees[out_level]);
543template<
typename TreeType>
548 OPENVDB_ASSERT( level >= 0.0 && level <=
double(mTrees.size()-1) );
549 const size_t level0 = size_t(floor(level)), level1 = size_t(ceil(level));
551 if ( level0 == level1 )
return v0;
560template<
typename TreeType>
565 OPENVDB_ASSERT( level >= 0.0 && level <=
double(mTrees.size()-1) );
566 const size_t level0 = size_t(floor(level)), level1 = size_t(ceil(level));
568 if ( level0 == level1 )
return v0;
577template<
typename TreeType>
582 const ConstAccessor acc(*mTrees[level + 1]);
586template<
typename TreeType>
591 TreeType &fineTree = *mTrees[ destlevel ];
592 const TreeType &coarseTree = *mTrees[ destlevel+1 ];
593 CookOp<ProlongateOp> tmp( coarseTree, fineTree, grainSize );
596template<
typename TreeType>
601 const TreeType &fineTree = *mTrees[ destlevel-1 ];
602 if ( useInjection )
return fineTree.getValue(ijk<<1);
603 const ConstAccessor acc( fineTree );
607template<
typename TreeType>
612 const TreeType &fineTree = *mTrees[ destlevel-1 ];
613 TreeType &coarseTree = *mTrees[ destlevel ];
614 CookOp<RestrictOp> tmp( fineTree, coarseTree, grainSize );
617template<
typename TreeType>
619print(std::ostream& os,
int verboseLevel)
const
621 os <<
"MultiResGrid with " << mTrees.size() <<
" levels\n";
622 for (
size_t i=0; i<mTrees.size(); ++i) {
623 os <<
"Level " << i <<
": ";
624 mTrees[i]->print(os, verboseLevel);
628 os <<
"Additional metadata:" << std::endl;
630 os <<
" " << it->first;
632 const std::string value = it->second->str();
633 if (!value.empty()) os <<
": " << value;
639 os <<
"Transform:" << std::endl;
644template<
typename TreeType>
648 const size_t levels = this->numLevels();
652 this->insertMeta(
"MultiResGrid_Levels",
Int64Metadata( levels ) );
655template<
typename TreeType>
656void MultiResGrid<TreeType>::
657topDownRestrict(
bool useInjection)
660 for (
size_t n=1; n<mTrees.size(); ++n) {
661 const TreeType &fineTree = *mTrees[n-1];
662 mTrees[n] = TreePtr(
new TreeType( fineTree.background() ) );
663 TreeType &coarseTree = *mTrees[n];
665 for (ValueOnCIter it = fineTree.cbeginValueOn(); it; ++it) {
666 const Coord ijk = it.getCoord();
667 if ( (ijk[0] & 1) || (ijk[1] & 1) || (ijk[2] & 1) )
continue;
668 coarseTree.setValue( ijk >> 1, *it );
671 MaskOp tmp(fineTree, coarseTree, 128);
672 this->restrictActiveVoxels(n, 64);
681template<
typename TreeType>
684 using MaskT =
typename TreeType::template ValueConverter<ValueMask>::Type;
685 using PoolType = tbb::enumerable_thread_specific<TreeType>;
687 using RangeT =
typename ManagerT::LeafRange;
688 using VoxelIterT =
typename ManagerT::LeafNodeType::ValueOnCIter;
690 MaskOp(
const TreeType& fineTree, TreeType& coarseTree,
size_t grainSize = 1)
703 tbb::parallel_for(leafs.
leafRange( grainSize ), *
this);
706 using IterT =
typename PoolType::const_iterator;
707 for (IterT it=
mPool->begin(); it!=
mPool->end(); ++it) coarseTree.topologyUnion( *it );
712 Accessor coarseAcc(
mPool->local() );
713 for (
typename RangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
714 for (
VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
715 Coord ijk = voxelIter.getCoord();
716 if ( (ijk[2] & 1) || (ijk[1] & 1) || (ijk[0] & 1) )
continue;
724template<
typename TreeType>
726struct MultiResGrid<TreeType>::FractionOp
728 using MaskT =
typename TreeType::template ValueConverter<ValueMask>::Type;
729 using PoolType = tbb::enumerable_thread_specific<MaskT>;
730 using PoolIterT =
typename PoolType::iterator;
733 using Range1 =
typename Manager1::LeafRange;
734 using Range2 =
typename Manager2::LeafRange;
739 size_t grainSize = 1)
742 , mTree0( &*(parent.mTrees[
size_t(floorf(level))]) )
743 , mTree1( &*(parent.mTrees[
size_t(ceilf(level))]) )
749 MaskT examplar(
false );
750 mPool =
new PoolType( examplar );
754 tbb::parallel_for( manager.
leafRange(grainSize), *
this );
758 tbb::parallel_for(tbb::blocked_range<PoolIterT>(mPool->begin(),mPool->end(),1), *
this);
761 for (PoolIterT it=mPool->begin(); it!=mPool->end(); ++it) midTree.topologyUnion( *it );
765 Manager2 manager( midTree );
766 tbb::parallel_for(manager.leafRange(grainSize), *
this);
769 void operator()(
const Range1& range)
const
771 using VoxelIter =
typename Manager1::LeafNodeType::ValueOnCIter;
782 for (
typename Range1::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
783 for (VoxelIter voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
784 Coord ijk = voxelIter.getCoord();
786 const auto value0 = ijk[0] * scale;
787 const auto value1 = ijk[1] * scale;
788 const auto value2 = ijk[2] * scale;
794 acc.setValueOn( ijk );
798 void operator()(
const tbb::blocked_range<PoolIterT>& range)
const
800 for (PoolIterT it=range.begin(); it!=range.end(); ++it) {
804 void operator()(
const Range2 &r)
const
806 using VoxelIter =
typename TreeType::LeafNodeType::ValueOnIter;
820 const float scale0 =
math::Pow( 2.0f, b );
821 const float scale1 =
math::Pow( 2.0f,-a );
822 ConstAccessor acc0( *mTree0 ), acc1( *mTree1 );
823 for (
typename Range2::Iterator leafIter = r.begin(); leafIter; ++leafIter) {
824 for (VoxelIter voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
825 const Vec3R xyz =
Vec3R( voxelIter.getCoord().data() );
829 const auto value0 = a*v0;
830 const auto value1 = b*v1;
832 voxelIter.setValue( ValueType(value0 + value1) );
838 const TreeType *mTree0, *mTree1;
842template<
typename TreeType>
843template<
typename OperatorType>
844struct MultiResGrid<TreeType>::CookOp
846 using ManagerT = tree::LeafManager<TreeType>;
847 using RangeT =
typename ManagerT::LeafRange;
849 CookOp(
const TreeType& srcTree, TreeType& dstTree,
size_t grainSize): acc(srcTree)
851 ManagerT leafs(dstTree);
852 tbb::parallel_for(leafs.leafRange(grainSize), *
this);
854 CookOp(
const CookOp &other): acc(other.acc.tree()) {}
856 void operator()(
const RangeT& range)
const
858 for (
auto leafIt = range.begin(); leafIt; ++leafIt) {
859 auto& phi = leafIt.buffer(0);
860 for (
auto voxelIt = leafIt->beginValueOn(); voxelIt; ++voxelIt) {
861 phi.setValue(voxelIt.pos(), OperatorType::run(voxelIt.getCoord(), acc));
866 const ConstAccessor acc;
870template<
typename TreeType>
893 for (
int i=-1; i<=1; i+=2) {
894 for (
int j=-1; j<=1; j+=2) {
903template<
typename TreeType>
911 switch ( (ijk[0] & 1) | ((ijk[1] & 1) << 1) | ((ijk[2] & 1) << 2) ) {
941 for (
int i=-1; i<=1; i+=2) {
942 for (
int j=-1; j<=1; j+=2) {
956#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
958#ifdef OPENVDB_INSTANTIATE_MULTIRESGRID
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Implementation of morphological dilation and erosion.
Defined various multi-threaded utility functions for trees.
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
static const char *const META_GRID_NAME
Definition Grid.h:353
static const char *const META_GRID_CLASS
Definition Grid.h:351
static GridClass stringToGridClass(const std::string &)
Return the class of volumetric data specified by the given string.
static std::string gridClassToString(GridClass)
Return the metadata string value for the given class of volumetric data.
Container class that associates a tree with a transform and metadata.
Definition Grid.h:571
SharedPtr< const Grid > ConstPtr
Definition Grid.h:574
SharedPtr< Grid > Ptr
Definition Grid.h:573
static Ptr create()
Return a new grid with background value zero.
Definition Grid.h:1343
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition Types.h:683
Definition Exceptions.h:65
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition Coord.h:92
const Int32 * data() const
Definition Coord.h:140
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition LeafManager.h:86
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition LeafManager.h:346
void setValueOn(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:569
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition ValueAccessor.h:455
Type Pow(Type x, int n)
Return xn.
Definition Math.h:561
float Round(float x)
Return x rounded to the nearest integer.
Definition Math.h:819
Type FractionalPart(Type x)
Return the fractional part of x.
Definition Math.h:843
ValueAccessorImpl< TreeType, IsSafe, MutexType, openvdb::make_index_sequence< CacheLevels > > ValueAccessor
Default alias for a ValueAccessor. This is simply a helper alias for the generic definition but takes...
Definition ValueAccessor.h:86
std::vector< GridBase::Ptr > GridPtrVec
Definition Grid.h:508
TypedMetadata< float > FloatMetadata
Definition Metadata.h:361
double Real
Definition Types.h:60
GridClass
Definition Types.h:453
@ GRID_LEVEL_SET
Definition Types.h:455
@ GRID_UNKNOWN
Definition Types.h:454
SharedPtr< GridCPtrVec > GridCPtrVecPtr
Definition Grid.h:516
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:70
SharedPtr< GridPtrVec > GridPtrVecPtr
Definition Grid.h:511
TypedMetadata< std::string > StringMetadata
Definition Metadata.h:364
math::Vec3< Real > Vec3R
Definition Types.h:72
std::shared_ptr< T > SharedPtr
Definition Types.h:114
TypedMetadata< int64_t > Int64Metadata
Definition Metadata.h:363
std::vector< GridBase::ConstPtr > GridCPtrVec
Definition Grid.h:513
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218
#define OPENVDB_INSTANTIATE_CLASS
Definition version.h.in:158