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>
59template<
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;
167 GridPtr grid(
size_t level);
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>
233 template<Index Order>
243 template<Index Order>
253 template<Index Order>
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;
301 this->removeMeta(GridBase::META_GRID_NAME);
309 this->getMetadata<StringMetadata>(GridBase::META_GRID_CLASS);
310 return s ? GridBase::stringToGridClass(s->value()) :
GRID_UNKNOWN;
316 this->insertMeta(GridBase::META_GRID_CLASS,
StringMetadata(GridBase::gridClassToString(cls)));
331 void topDownRestrict(
bool useInjection);
333 inline void initMeta();
346 template<Index Order>
350 template<
typename OpType>
struct CookOp;
353 std::vector<TreePtr> mTrees;
358template<
typename TreeType>
362 , mTransform(math::Transform::createLinearTransform( voxelSize ))
365 for (
size_t i=0; i<levels; ++i) mTrees[i] =
TreePtr(
new TreeType(background));
368template<
typename TreeType>
373 , mTransform( grid.transform().copy() )
376 mTrees[0].reset(
new TreeType(
grid.tree() ) );
377 mTrees[0]->voxelizeActiveTiles();
378 this->topDownRestrict(useInjection);
381template<
typename TreeType>
386 , mTransform( grid->transform().copy() )
389 mTrees[0] =
grid->treePtr();
390 mTrees[0]->voxelizeActiveTiles();
392 this->topDownRestrict(useInjection);
395template<
typename TreeType>
399 assert( level < mTrees.size() );
400 return *mTrees[level];
403template<
typename TreeType>
407 assert( level < mTrees.size() );
408 return *mTrees[level];
411template<
typename TreeType>
415 assert( level < mTrees.size() );
416 return mTrees[level];
419template<
typename TreeType>
423 assert( level < mTrees.size() );
424 return mTrees[level];
427template<
typename TreeType>
433 if (level>0) xform->preScale(
Real(1 << level) );
437 std::stringstream ss;
438 ss << this->getName() <<
"_level_" << level;
443template<
typename TreeType>
445grid(
size_t level)
const
450template<
typename TreeType>
453createGrid(
float level,
size_t grainSize)
const
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);
480template<
typename TreeType>
485 for (
size_t level=0; level<mTrees.size(); ++level) grids->push_back(this->grid(level));
489template<
typename TreeType>
494 for (
size_t level=0; level<mTrees.size(); ++level) grids->push_back(this->grid(level));
498template<
typename TreeType>
500xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
505template<
typename TreeType>
507xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level)
509 return in_xyz *
Real(1 << in_level) /
Real(1 << out_level);
512template<
typename TreeType>
514xyz(
const Vec3R& in_xyz,
double in_level,
double out_level)
516 return in_xyz *
math::Pow(2.0, in_level - out_level);
520template<
typename TreeType>
525 assert( in_level >= 0 && in_level < mTrees.size() );
526 assert( out_level >= 0 && out_level < mTrees.size() );
531template<
typename TreeType>
536 assert( in_level >= 0 && in_level < mTrees.size() );
537 assert( out_level >= 0 && out_level < mTrees.size() );
542template<
typename TreeType>
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 );
559template<
typename TreeType>
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 );
576template<
typename TreeType>
580 assert( level+1 < mTrees.size() );
582 return ProlongateOp::run(ijk, acc);
585template<
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 );
595template<
typename TreeType>
599 assert( destlevel > 0 && destlevel < mTrees.size() );
600 const TreeType &fineTree = *mTrees[ destlevel-1 ];
601 if ( useInjection )
return fineTree.getValue(ijk<<1);
603 return RestrictOp::run( ijk, acc);
606template<
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 );
616template<
typename TreeType>
618print(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,
" ");
643template<
typename TreeType>
647 const size_t levels = this->numLevels();
651 this->insertMeta(
"MultiResGrid_Levels",
Int64Metadata( levels ) );
654template<
typename TreeType>
655void MultiResGrid<TreeType>::
656topDownRestrict(
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);
680template<
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;
723template<
typename TreeType>
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;
841template<
typename TreeType>
842template<
typename OperatorType>
843struct 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) {
860 phi.setValue(voxelIt.pos(), OperatorType::run(voxelIt.getCoord(), acc));
865 const ConstAccessor acc;
869template<
typename TreeType>
892 for (
int i=-1; i<=1; i+=2) {
893 for (
int j=-1; j<=1; j+=2) {
902template<
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
ValueT value
Definition: GridBuilder.h:1290
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...
void setName(const std::string &)
Specify a name for this grid.
void setTransform(math::Transform::Ptr)
Associate the given transform with this grid, in place of its existing transform.
Definition: Grid.h:1234
GridClass getGridClass() const
Return the class of volumetric data (level set, fog volume, etc.) that is stored in this grid.
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:571
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:908
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.
Definition: Grid.h:1454
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:1308
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:644
Definition: Exceptions.h:65
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:25
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:91
const Int32 * data() const
Definition: Coord.h:139
Definition: LeafManager.h:102
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:85
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:345
Definition: ValueAccessor.h:191
void setValueOn(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:271
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:235
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
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:508
TypedMetadata< float > FloatMetadata
Definition: Metadata.h:360
double Real
Definition: Types.h:60
GridClass
Definition: Types.h:414
@ GRID_LEVEL_SET
Definition: Types.h:416
@ GRID_UNKNOWN
Definition: Types.h:415
SharedPtr< GridCPtrVec > GridCPtrVecPtr
Definition: Grid.h:516
SharedPtr< GridPtrVec > GridPtrVecPtr
Definition: Grid.h:511
math::Vec3< Real > Vec3R
Definition: Types.h:72
std::shared_ptr< T > SharedPtr
Definition: Types.h:114
TypedMetadata< int64_t > Int64Metadata
Definition: Metadata.h:362
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:212
#define OPENVDB_INSTANTIATE_CLASS
Definition: version.h.in:153