52 #ifndef OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED 53 #define OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED 69 #include <tbb/blocked_range.h> 70 #include <tbb/enumerable_thread_specific.h> 71 #include <tbb/parallel_for.h> 84 template<
typename TreeType>
146 TreeType& tree(
size_t level);
151 const TreeType& constTree(
size_t level)
const;
156 TreePtr treePtr(
size_t level);
161 ConstTreePtr constTreePtr(
size_t level)
const;
192 GridPtr grid(
size_t level);
197 ConstGridPtr grid(
size_t level)
const;
206 template<Index Order>
207 GridPtr
createGrid(
float level,
size_t grainSize = 1)
const;
235 static Vec3R xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level);
238 static Vec3R xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level);
239 static Vec3R xyz(
const Vec3R& in_xyz,
double in_level,
double out_level);
247 template<Index Order>
257 ValueType sampleValue(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
const;
258 template<Index Order>
259 ValueType sampleValue(
const Vec3R& in_ijk,
size_t in_level,
size_t out_level)
const;
268 template<Index Order>
269 ValueType sampleValue(
const Coord& ijk,
double level)
const;
278 template<Index Order>
279 ValueType sampleValue(
const Vec3R& xyz,
double level)
const;
289 ValueType prolongateVoxel(
const Coord& coords,
const size_t level)
const;
295 void prolongateActiveVoxels(
size_t destlevel,
size_t grainSize = 1);
303 ValueType restrictVoxel(
Coord ijk,
const size_t level,
bool useInjection =
false)
const;
311 void restrictActiveVoxels(
size_t destlevel,
size_t grainSize = 1);
314 void print(std::ostream& = std::cout,
int verboseLevel = 1)
const;
356 void topDownRestrict(
bool useInjection);
358 inline void initMeta();
371 template<Index Order>
375 template<
typename OpType>
struct CookOp;
378 std::vector<TreePtr> mTrees;
383 template<
typename TreeType>
384 MultiResGrid<TreeType>::
385 MultiResGrid(
size_t levels,
ValueType background,
double voxelSize)
387 , mTransform(math::Transform::createLinearTransform( voxelSize ))
390 for (
size_t i=0; i<levels; ++i) mTrees[i] =
TreePtr(
new TreeType(background));
393 template<
typename TreeType>
398 , mTransform( grid.transform().copy() )
401 mTrees[0].reset(
new TreeType(
grid.tree() ) );
402 mTrees[0]->voxelizeActiveTiles();
403 this->topDownRestrict(useInjection);
406 template<
typename TreeType>
411 , mTransform( grid->transform().copy() )
414 mTrees[0] =
grid->treePtr();
415 mTrees[0]->voxelizeActiveTiles();
417 this->topDownRestrict(useInjection);
420 template<
typename TreeType>
424 assert( level < mTrees.size() );
425 return *mTrees[level];
428 template<
typename TreeType>
432 assert( level < mTrees.size() );
433 return *mTrees[level];
436 template<
typename TreeType>
440 assert( level < mTrees.size() );
441 return mTrees[level];
444 template<
typename TreeType>
448 assert( level < mTrees.size() );
449 return mTrees[level];
452 template<
typename TreeType>
458 if (level>0) xform->preScale(
Real(1 << level) );
462 std::stringstream ss;
463 ss << this->getName() <<
"_level_" << level;
468 template<
typename TreeType>
472 return const_cast<MultiResGrid*>(
this)->grid(level);
475 template<
typename TreeType>
476 template<Index Order>
480 assert( level >= 0.0f && level <=
float(mTrees.size()-1) );
484 xform->preScale(
math::Pow(2.0f, level) );
488 std::stringstream ss;
489 ss << this->getName() <<
"_level_" << level;
492 if (
size_t(floorf(level)) == size_t(ceilf(level)) ) {
493 grid->
setTree( this->constTree(
size_t(floorf(level))).copy() );
495 FractionOp<Order> tmp(*
this, grid->
tree(), level, grainSize);
505 template<
typename TreeType>
510 for (
size_t level=0; level<mTrees.size(); ++level) grids->push_back(this->grid(level));
514 template<
typename TreeType>
519 for (
size_t level=0; level<mTrees.size(); ++level) grids->push_back(this->grid(level));
523 template<
typename TreeType>
525 xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
530 template<
typename TreeType>
532 xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level)
534 return in_xyz *
Real(1 << in_level) /
Real(1 << out_level);
537 template<
typename TreeType>
539 xyz(
const Vec3R& in_xyz,
double in_level,
double out_level)
541 return in_xyz *
math::Pow(2.0, in_level - out_level);
545 template<
typename TreeType>
546 template<Index Order>
550 assert( in_level >= 0 && in_level < mTrees.size() );
551 assert( out_level >= 0 && out_level < mTrees.size() );
556 template<
typename TreeType>
557 template<Index Order>
561 assert( in_level >= 0 && in_level < mTrees.size() );
562 assert( out_level >= 0 && out_level < mTrees.size() );
567 template<
typename TreeType>
568 template<Index Order>
572 assert( level >= 0.0 && level <=
double(mTrees.size()-1) );
573 const size_t level0 = size_t(floor(level)), level1 = size_t(ceil(level));
574 const ValueType v0 = this->
template sampleValue<Order>( ijk, 0, level0 );
575 if ( level0 == level1 )
return v0;
576 assert( level1 - level0 == 1 );
577 const ValueType v1 = this->
template sampleValue<Order>( ijk, 0, level1 );
584 template<
typename TreeType>
585 template<Index Order>
589 assert( level >= 0.0 && level <=
double(mTrees.size()-1) );
590 const size_t level0 = size_t(floor(level)), level1 = size_t(ceil(level));
591 const ValueType v0 = this->
template sampleValue<Order>( xyz, 0, level0 );
592 if ( level0 == level1 )
return v0;
593 assert( level1 - level0 == 1 );
594 const ValueType v1 = this->
template sampleValue<Order>( xyz, 0, level1 );
601 template<
typename TreeType>
605 assert( level+1 < mTrees.size() );
607 return ProlongateOp::run(ijk, acc);
610 template<
typename TreeType>
614 assert( destlevel < mTrees.size()-1 );
615 TreeType &fineTree = *mTrees[ destlevel ];
616 const TreeType &coarseTree = *mTrees[ destlevel+1 ];
617 CookOp<ProlongateOp> tmp( coarseTree, fineTree, grainSize );
620 template<
typename TreeType>
624 assert( destlevel > 0 && destlevel < mTrees.size() );
625 const TreeType &fineTree = *mTrees[ destlevel-1 ];
626 if ( useInjection )
return fineTree.getValue(ijk<<1);
628 return RestrictOp::run( ijk, acc);
631 template<
typename TreeType>
635 assert( destlevel > 0 && destlevel < mTrees.size() );
636 const TreeType &fineTree = *mTrees[ destlevel-1 ];
637 TreeType &coarseTree = *mTrees[ destlevel ];
638 CookOp<RestrictOp> tmp( fineTree, coarseTree, grainSize );
641 template<
typename TreeType>
643 print(std::ostream& os,
int verboseLevel)
const 645 os <<
"MultiResGrid with " << mTrees.size() <<
" levels\n";
646 for (
size_t i=0; i<mTrees.size(); ++i) {
647 os <<
"Level " << i <<
": ";
648 mTrees[i]->print(os, verboseLevel);
652 os <<
"Additional metadata:" << std::endl;
654 os <<
" " << it->first;
656 const std::string value = it->second->str();
657 if (!value.empty()) os <<
": " << value;
663 os <<
"Transform:" << std::endl;
664 transform().print(os,
" ");
668 template<
typename TreeType>
672 const size_t levels = this->numLevels();
676 this->insertMeta(
"MultiResGrid_Levels",
Int64Metadata( levels ) );
679 template<
typename TreeType>
680 void MultiResGrid<TreeType>::
681 topDownRestrict(
bool useInjection)
684 for (
size_t n=1; n<mTrees.size(); ++n) {
685 const TreeType &fineTree = *mTrees[n-1];
686 mTrees[n] = TreePtr(
new TreeType( fineTree.background() ) );
687 TreeType &coarseTree = *mTrees[n];
689 for (ValueOnCIter it = fineTree.cbeginValueOn(); it; ++it) {
690 const Coord ijk = it.getCoord();
691 if ( (ijk[0] & 1) || (ijk[1] & 1) || (ijk[2] & 1) )
continue;
692 coarseTree.setValue( ijk >> 1, *it );
695 MaskOp tmp(fineTree, coarseTree, 128);
696 this->restrictActiveVoxels(n, 64);
705 template<
typename TreeType>
708 using MaskT =
typename TreeType::template ValueConverter<ValueMask>::Type;
709 using PoolType = tbb::enumerable_thread_specific<TreeType>;
712 using VoxelIterT =
typename ManagerT::LeafNodeType::ValueOnCIter;
714 MaskOp(
const TreeType& fineTree, TreeType& coarseTree,
size_t grainSize = 1)
715 : mPool(new
PoolType( coarseTree ) )
717 assert( coarseTree.empty() );
727 tbb::parallel_for(leafs.
leafRange( grainSize ), *
this);
730 using IterT =
typename PoolType::const_iterator;
731 for (IterT it=mPool->begin(); it!=mPool->end(); ++it) coarseTree.topologyUnion( *it );
736 Accessor coarseAcc( mPool->local() );
737 for (
typename RangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
738 for (
VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
739 Coord ijk = voxelIter.getCoord();
740 if ( (ijk[2] & 1) || (ijk[1] & 1) || (ijk[0] & 1) )
continue;
741 coarseAcc.setValueOn( ijk >> 1 );
748 template<
typename TreeType>
749 template<Index Order>
752 using MaskT =
typename TreeType::template ValueConverter<ValueMask>::Type;
753 using PoolType = tbb::enumerable_thread_specific<MaskT>;
754 using PoolIterT =
typename PoolType::iterator;
757 using Range1 =
typename Manager1::LeafRange;
758 using Range2 =
typename Manager2::LeafRange;
763 size_t grainSize = 1)
766 , mTree0( &*(parent.mTrees[
size_t(floorf(level))]) )
767 , mTree1( &*(parent.mTrees[
size_t(ceilf(level))]) )
769 assert( midTree.empty() );
770 assert( mTree0 != mTree1 );
773 MaskT examplar(
false );
774 mPool =
new PoolType( examplar );
778 tbb::parallel_for( manager.
leafRange(grainSize), *this );
782 tbb::parallel_for(tbb::blocked_range<PoolIterT>(mPool->begin(),mPool->end(),1), *
this);
785 for (PoolIterT it=mPool->begin(); it!=mPool->end(); ++it) midTree.topologyUnion( *it );
789 Manager2 manager( midTree );
790 tbb::parallel_for(manager.leafRange(grainSize), *
this);
793 void operator()(
const Range1& range)
const 795 using VoxelIter =
typename Manager1::LeafNodeType::ValueOnCIter;
806 for (
typename Range1::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
807 for (VoxelIter voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
808 Coord ijk = voxelIter.getCoord();
810 const auto value0 = ijk[0] *
scale;
811 const auto value1 = ijk[1] *
scale;
812 const auto value2 = ijk[2] *
scale;
818 acc.setValueOn( ijk );
822 void operator()(
const tbb::blocked_range<PoolIterT>& range)
const 824 for (PoolIterT it=range.begin(); it!=range.end(); ++it) {
828 void operator()(
const Range2 &r)
const 830 using VoxelIter =
typename TreeType::LeafNodeType::ValueOnIter;
844 const float scale0 =
math::Pow( 2.0f, b );
845 const float scale1 =
math::Pow( 2.0f,-a );
846 ConstAccessor acc0( *mTree0 ), acc1( *mTree1 );
847 for (
typename Range2::Iterator leafIter = r.begin(); leafIter; ++leafIter) {
848 for (VoxelIter voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
849 const Vec3R xyz =
Vec3R( voxelIter.getCoord().data() );
853 const auto value0 = a*v0;
854 const auto value1 = b*v1;
856 voxelIter.setValue( ValueType(value0 + value1) );
862 const TreeType *mTree0, *mTree1;
866 template<
typename TreeType>
867 template<
typename OperatorType>
868 struct MultiResGrid<TreeType>::CookOp
870 using ManagerT = tree::LeafManager<TreeType>;
871 using RangeT =
typename ManagerT::LeafRange;
873 CookOp(
const TreeType& srcTree, TreeType& dstTree,
size_t grainSize): acc(srcTree)
875 ManagerT leafs(dstTree);
876 tbb::parallel_for(leafs.leafRange(grainSize), *
this);
878 CookOp(
const CookOp &other): acc(other.acc.tree()) {}
880 void operator()(
const RangeT& range)
const 882 for (
auto leafIt = range.begin(); leafIt; ++leafIt) {
883 auto& phi = leafIt.buffer(0);
884 for (
auto voxelIt = leafIt->beginValueOn(); voxelIt; ++voxelIt) {
885 phi.setValue(voxelIt.pos(), OperatorType::run(voxelIt.getCoord(), acc));
890 const ConstAccessor acc;
894 template<
typename TreeType>
917 for (
int i=-1; i<=1; i+=2) {
918 for (
int j=-1; j<=1; j+=2) {
927 template<
typename TreeType>
935 switch ( (ijk[0] & 1) | ((ijk[1] & 1) << 1) | ((ijk[2] & 1) << 2) ) {
965 for (
int i=-1; i<=1; i+=2) {
966 for (
int j=-1; j<=1; j+=2) {
978 #endif // OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED static Ptr create()
Return a new grid with background value zero.
Definition: Grid.h:1279
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
TypedMetadata< float > FloatMetadata
Definition: Metadata.h:410
Type Pow(Type x, int n)
Return xn.
Definition: Math.h:515
static const char *const META_GRID_NAME
Definition: Grid.h:369
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
SharedPtr< GridCPtrVec > GridCPtrVecPtr
Definition: Grid.h:535
Definition: ValueAccessor.h:220
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:55
std::shared_ptr< T > SharedPtr
Definition: Types.h:139
SharedPtr< GridPtrVec > GridPtrVecPtr
Definition: Grid.h:530
static std::string gridClassToString(GridClass)
Return the metadata string value for the given class of volumetric data.
GridClass getGridClass() const
Return the class of volumetric data (level set, fog volume, etc.) that is stored in this grid.
Defined various multi-threaded utility functions for trees.
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:527
static const char *const META_GRID_CLASS
Definition: Grid.h:367
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:385
math::Vec3< Real > Vec3R
Definition: Types.h:79
const Int32 * data() const
Definition: Coord.h:167
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:125
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:1677
double Real
Definition: Types.h:67
Implementation of morphological dilation and erosion.
Definition: Exceptions.h:40
std::vector< GridBase::ConstPtr > GridCPtrVec
Definition: Grid.h:532
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:647
Definition: LeafManager.h:126
TypedMetadata< std::string > StringMetadata
Definition: Metadata.h:413
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:52
void setName(const std::string &)
Specify a name for this grid.
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:750
GridClass
Definition: Types.h:502
static GridClass stringToGridClass(const std::string &)
Return the class of volumetric data specified by the given string.
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
Type FractionalPart(Type x)
Return the fractional part of x.
Definition: Math.h:797
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:890
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.
Definition: Grid.h:1402
void setTransform(math::Transform::Ptr)
Associate the given transform with this grid, in place of its existing transform.
Definition: Grid.h:1205
Definition: Exceptions.h:92
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:177
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
SharedPtr< Grid > Ptr
Definition: Grid.h:592
SharedPtr< const Grid > ConstPtr
Definition: Grid.h:593
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:773
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:119
TypedMetadata< int64_t > Int64Metadata
Definition: Metadata.h:412
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...
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:257