25 #ifndef OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED 26 #define OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED 44 #include <tbb/blocked_range.h> 45 #include <tbb/enumerable_thread_specific.h> 46 #include <tbb/parallel_for.h> 59 template<
typename TreeType>
121 TreeType& tree(
size_t level);
126 const TreeType& constTree(
size_t level)
const;
131 TreePtr treePtr(
size_t level);
136 ConstTreePtr constTreePtr(
size_t level)
const;
172 ConstGridPtr grid(
size_t level)
const;
181 template<Index Order>
212 static Vec3R xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level);
213 static Vec3R xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level);
214 static Vec3R xyz(
const Vec3R& in_xyz,
double in_level,
double out_level);
231 template<Index Order>
232 ValueType sampleValue(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
const;
233 template<Index Order>
234 ValueType sampleValue(
const Vec3R& in_ijk,
size_t in_level,
size_t out_level)
const;
243 template<Index Order>
244 ValueType sampleValue(
const Coord& ijk,
double level)
const;
253 template<Index Order>
254 ValueType sampleValue(
const Vec3R& xyz,
double level)
const;
264 ValueType prolongateVoxel(
const Coord& coords,
const size_t level)
const;
270 void prolongateActiveVoxels(
size_t destlevel,
size_t grainSize = 1);
278 ValueType restrictVoxel(
Coord ijk,
const size_t level,
bool useInjection =
false)
const;
286 void restrictActiveVoxels(
size_t destlevel,
size_t grainSize = 1);
289 void print(std::ostream& = std::cout,
int verboseLevel = 1)
const;
331 void topDownRestrict(
bool useInjection);
333 inline void initMeta();
346 template<Index Order>
350 template<
typename OpType>
struct CookOp;
353 std::vector<TreePtr> mTrees;
358 template<
typename TreeType>
359 MultiResGrid<TreeType>::
360 MultiResGrid(
size_t levels,
ValueType background,
double voxelSize)
362 , mTransform(math::Transform::createLinearTransform( voxelSize ))
365 for (
size_t i=0; i<levels; ++i) mTrees[i] =
TreePtr(
new TreeType(background));
368 template<
typename TreeType>
373 , mTransform( grid.transform().copy() )
376 mTrees[0].reset(
new TreeType(
grid.tree() ) );
377 mTrees[0]->voxelizeActiveTiles();
378 this->topDownRestrict(useInjection);
381 template<
typename TreeType>
386 , mTransform( grid->transform().copy() )
389 mTrees[0] =
grid->treePtr();
390 mTrees[0]->voxelizeActiveTiles();
392 this->topDownRestrict(useInjection);
395 template<
typename TreeType>
399 assert( level < mTrees.size() );
400 return *mTrees[level];
403 template<
typename TreeType>
407 assert( level < mTrees.size() );
408 return *mTrees[level];
411 template<
typename TreeType>
415 assert( level < mTrees.size() );
416 return mTrees[level];
419 template<
typename TreeType>
423 assert( level < mTrees.size() );
424 return mTrees[level];
427 template<
typename TreeType>
433 if (level>0) xform->preScale(
Real(1 << level) );
437 std::stringstream ss;
438 ss << this->getName() <<
"_level_" << level;
443 template<
typename TreeType>
450 template<
typename TreeType>
451 template<Index Order>
455 assert( level >= 0.0f && level <=
float(mTrees.size()-1) );
459 xform->preScale(
math::Pow(2.0f, level) );
463 std::stringstream ss;
464 ss << this->getName() <<
"_level_" << level;
467 if (
size_t(floorf(level)) == size_t(ceilf(level)) ) {
468 grid->
setTree( this->constTree(
size_t(floorf(level))).copy() );
470 FractionOp<Order> tmp(*
this, grid->
tree(), level, grainSize);
480 template<
typename TreeType>
485 for (
size_t level=0; level<mTrees.size(); ++level) grids->push_back(this->grid(level));
489 template<
typename TreeType>
494 for (
size_t level=0; level<mTrees.size(); ++level) grids->push_back(this->grid(level));
498 template<
typename TreeType>
500 xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
505 template<
typename TreeType>
507 xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level)
509 return in_xyz *
Real(1 << in_level) /
Real(1 << out_level);
512 template<
typename TreeType>
514 xyz(
const Vec3R& in_xyz,
double in_level,
double out_level)
516 return in_xyz *
math::Pow(2.0, in_level - out_level);
520 template<
typename TreeType>
521 template<Index Order>
525 assert( in_level >= 0 && in_level < mTrees.size() );
526 assert( out_level >= 0 && out_level < mTrees.size() );
531 template<
typename TreeType>
532 template<Index Order>
536 assert( in_level >= 0 && in_level < mTrees.size() );
537 assert( out_level >= 0 && out_level < mTrees.size() );
542 template<
typename TreeType>
543 template<Index Order>
547 assert( level >= 0.0 && level <=
double(mTrees.size()-1) );
548 const size_t level0 = size_t(floor(level)), level1 = size_t(ceil(level));
549 const ValueType v0 = this->
template sampleValue<Order>( ijk, 0, level0 );
550 if ( level0 == level1 )
return v0;
551 assert( level1 - level0 == 1 );
552 const ValueType v1 = this->
template sampleValue<Order>( ijk, 0, level1 );
559 template<
typename TreeType>
560 template<Index Order>
564 assert( level >= 0.0 && level <=
double(mTrees.size()-1) );
565 const size_t level0 = size_t(floor(level)), level1 = size_t(ceil(level));
566 const ValueType v0 = this->
template sampleValue<Order>( xyz, 0, level0 );
567 if ( level0 == level1 )
return v0;
568 assert( level1 - level0 == 1 );
569 const ValueType v1 = this->
template sampleValue<Order>( xyz, 0, level1 );
576 template<
typename TreeType>
580 assert( level+1 < mTrees.size() );
585 template<
typename TreeType>
589 assert( destlevel < mTrees.size()-1 );
590 TreeType &fineTree = *mTrees[ destlevel ];
591 const TreeType &coarseTree = *mTrees[ destlevel+1 ];
592 CookOp<ProlongateOp> tmp( coarseTree, fineTree, grainSize );
595 template<
typename TreeType>
599 assert( destlevel > 0 && destlevel < mTrees.size() );
600 const TreeType &fineTree = *mTrees[ destlevel-1 ];
601 if ( useInjection )
return fineTree.getValue(ijk<<1);
606 template<
typename TreeType>
610 assert( destlevel > 0 && destlevel < mTrees.size() );
611 const TreeType &fineTree = *mTrees[ destlevel-1 ];
612 TreeType &coarseTree = *mTrees[ destlevel ];
613 CookOp<RestrictOp> tmp( fineTree, coarseTree, grainSize );
616 template<
typename TreeType>
618 print(std::ostream& os,
int verboseLevel)
const 620 os <<
"MultiResGrid with " << mTrees.size() <<
" levels\n";
621 for (
size_t i=0; i<mTrees.size(); ++i) {
622 os <<
"Level " << i <<
": ";
623 mTrees[i]->print(os, verboseLevel);
627 os <<
"Additional metadata:" << std::endl;
629 os <<
" " << it->first;
631 const std::string
value = it->second->str();
638 os <<
"Transform:" << std::endl;
639 transform().print(os,
" ");
643 template<
typename TreeType>
647 const size_t levels = this->numLevels();
651 this->insertMeta(
"MultiResGrid_Levels",
Int64Metadata( levels ) );
654 template<
typename TreeType>
655 void MultiResGrid<TreeType>::
656 topDownRestrict(
bool useInjection)
659 for (
size_t n=1; n<mTrees.size(); ++n) {
660 const TreeType &fineTree = *mTrees[n-1];
661 mTrees[n] = TreePtr(
new TreeType( fineTree.background() ) );
662 TreeType &coarseTree = *mTrees[n];
664 for (ValueOnCIter it = fineTree.cbeginValueOn(); it; ++it) {
665 const Coord ijk = it.getCoord();
666 if ( (ijk[0] & 1) || (ijk[1] & 1) || (ijk[2] & 1) )
continue;
667 coarseTree.setValue( ijk >> 1, *it );
670 MaskOp tmp(fineTree, coarseTree, 128);
671 this->restrictActiveVoxels(n, 64);
680 template<
typename TreeType>
683 using MaskT =
typename TreeType::template ValueConverter<ValueMask>::Type;
684 using PoolType = tbb::enumerable_thread_specific<TreeType>;
687 using VoxelIterT =
typename ManagerT::LeafNodeType::ValueOnCIter;
689 MaskOp(
const TreeType& fineTree, TreeType& coarseTree,
size_t grainSize = 1)
690 : mPool(new
PoolType( coarseTree ) )
692 assert( coarseTree.empty() );
702 tbb::parallel_for(leafs.
leafRange( grainSize ), *
this);
705 using IterT =
typename PoolType::const_iterator;
706 for (IterT it=mPool->begin(); it!=mPool->end(); ++it) coarseTree.topologyUnion( *it );
711 Accessor coarseAcc( mPool->local() );
712 for (
typename RangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
713 for (
VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
714 Coord ijk = voxelIter.getCoord();
715 if ( (ijk[2] & 1) || (ijk[1] & 1) || (ijk[0] & 1) )
continue;
716 coarseAcc.setValueOn( ijk >> 1 );
723 template<
typename TreeType>
724 template<Index Order>
727 using MaskT =
typename TreeType::template ValueConverter<ValueMask>::Type;
728 using PoolType = tbb::enumerable_thread_specific<MaskT>;
729 using PoolIterT =
typename PoolType::iterator;
732 using Range1 =
typename Manager1::LeafRange;
733 using Range2 =
typename Manager2::LeafRange;
738 size_t grainSize = 1)
741 , mTree0( &*(parent.mTrees[
size_t(floorf(level))]) )
742 , mTree1( &*(parent.mTrees[
size_t(ceilf(level))]) )
744 assert( midTree.empty() );
745 assert( mTree0 != mTree1 );
748 MaskT examplar(
false );
749 mPool =
new PoolType( examplar );
753 tbb::parallel_for( manager.
leafRange(grainSize), *this );
757 tbb::parallel_for(tbb::blocked_range<PoolIterT>(mPool->begin(),mPool->end(),1), *
this);
760 for (PoolIterT it=mPool->begin(); it!=mPool->end(); ++it) midTree.topologyUnion( *it );
764 Manager2 manager( midTree );
765 tbb::parallel_for(manager.leafRange(grainSize), *
this);
768 void operator()(
const Range1& range)
const 770 using VoxelIter =
typename Manager1::LeafNodeType::ValueOnCIter;
781 for (
typename Range1::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
782 for (VoxelIter voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
783 Coord ijk = voxelIter.getCoord();
785 const auto value0 = ijk[0] *
scale;
786 const auto value1 = ijk[1] *
scale;
787 const auto value2 = ijk[2] *
scale;
793 acc.setValueOn( ijk );
797 void operator()(
const tbb::blocked_range<PoolIterT>& range)
const 799 for (PoolIterT it=range.begin(); it!=range.end(); ++it) {
803 void operator()(
const Range2 &r)
const 805 using VoxelIter =
typename TreeType::LeafNodeType::ValueOnIter;
819 const float scale0 =
math::Pow( 2.0f, b );
820 const float scale1 =
math::Pow( 2.0f,-a );
821 ConstAccessor acc0( *mTree0 ), acc1( *mTree1 );
822 for (
typename Range2::Iterator leafIter = r.begin(); leafIter; ++leafIter) {
823 for (VoxelIter voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
824 const Vec3R xyz =
Vec3R( voxelIter.getCoord().data() );
828 const auto value0 = a*v0;
829 const auto value1 = b*v1;
831 voxelIter.setValue( ValueType(value0 + value1) );
837 const TreeType *mTree0, *mTree1;
841 template<
typename TreeType>
842 template<
typename OperatorType>
843 struct MultiResGrid<TreeType>::CookOp
845 using ManagerT = tree::LeafManager<TreeType>;
846 using RangeT =
typename ManagerT::LeafRange;
848 CookOp(
const TreeType& srcTree, TreeType& dstTree,
size_t grainSize): acc(srcTree)
850 ManagerT leafs(dstTree);
851 tbb::parallel_for(leafs.leafRange(grainSize), *
this);
853 CookOp(
const CookOp &other): acc(other.acc.tree()) {}
855 void operator()(
const RangeT& range)
const 857 for (
auto leafIt = range.begin(); leafIt; ++leafIt) {
858 auto& phi = leafIt.buffer(0);
859 for (
auto voxelIt = leafIt->beginValueOn(); voxelIt; ++voxelIt) {
865 const ConstAccessor acc;
869 template<
typename TreeType>
892 for (
int i=-1; i<=1; i+=2) {
893 for (
int j=-1; j<=1; j+=2) {
902 template<
typename TreeType>
910 switch ( (ijk[0] & 1) | ((ijk[1] & 1) << 1) | ((ijk[2] & 1) << 2) ) {
940 for (
int i=-1; i<=1; i+=2) {
941 for (
int j=-1; j<=1; j+=2) {
955 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 957 #ifdef OPENVDB_INSTANTIATE_MULTIRESGRID 964 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION 971 #endif // OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
OPENVDB_AX_API void print(const ast::Node &node, const bool numberStatements=true, std::ostream &os=std::cout, const char *indent=" ")
Writes a descriptive printout of a Node hierarchy into a target stream.
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:819
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
GridClass
Definition: Types.h:414
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
GridClass getGridClass() const
Return the class of volumetric data (level set, fog volume, etc.) that is stored in this grid...
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:24
SharedPtr< GridCPtrVec > GridCPtrVecPtr
Definition: Grid.h:516
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:615
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.
Definition: Grid.h:1454
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:345
static const char *const META_GRID_NAME
Definition: Grid.h:353
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:508
openvdb::GridBase::Ptr GridPtr
Definition: Utils.h:35
Definition: Exceptions.h:65
TypedMetadata< float > FloatMetadata
Definition: Metadata.h:360
TypedMetadata< int64_t > Int64Metadata
Definition: Metadata.h:362
static Ptr create()
Return a new grid with background value zero.
Definition: Grid.h:1308
TypedMetadata< std::string > StringMetadata
Definition: Metadata.h:363
Defined various multi-threaded utility functions for trees.
const Int32 * data() const
Definition: Coord.h:139
OPENVDB_API uint32_t getGridClass(std::ios_base &)
Return the class (GRID_LEVEL_SET, GRID_UNKNOWN, etc.) of the grid currently being read from or writte...
OPENVDB_AX_API void run(const char *ax, openvdb::GridBase &grid, const AttributeBindings &bindings={})
Run a full AX pipeline (parse, compile and execute) on a single OpenVDB Grid.
void setName(const std::string &)
Specify a name for this grid.
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
GridType::Ptr createGrid(const typename GridType::ValueType &background)
Create a new grid of type GridType with a given background value.
Definition: Grid.h:1722
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:908
Implementation of morphological dilation and erosion.
Definition: Exceptions.h:13
void setTransform(math::Transform::Ptr)
Associate the given transform with this grid, in place of its existing transform. ...
Definition: Grid.h:1234
ValueT value
Definition: GridBuilder.h:1290
static std::string gridClassToString(GridClass)
Return the metadata string value for the given class of volumetric data.
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:91
math::Vec3< Real > Vec3R
Definition: Types.h:72
#define OPENVDB_INSTANTIATE_CLASS
Definition: version.h.in:153
Definition: LeafManager.h:101
SharedPtr< Grid > Ptr
Definition: Grid.h:573
std::shared_ptr< T > SharedPtr
Definition: Types.h:114
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:644
Definition: ValueAccessor.h:190
Type Pow(Type x, int n)
Return xn.
Definition: Math.h:561
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:84
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:28
Type FractionalPart(Type x)
Return the fractional part of x.
Definition: Math.h:843
static const char *const META_GRID_CLASS
Definition: Grid.h:351
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
static GridClass stringToGridClass(const std::string &)
Return the class of volumetric data specified by the given string.
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
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:235
SharedPtr< const Grid > ConstPtr
Definition: Grid.h:574
double Real
Definition: Types.h:60
std::vector< GridBase::ConstPtr > GridCPtrVec
Definition: Grid.h:513
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:212
SharedPtr< GridPtrVec > GridPtrVecPtr
Definition: Grid.h:511