25 #ifndef OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED 26 #define OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED 42 #include <tbb/blocked_range.h> 43 #include <tbb/enumerable_thread_specific.h> 44 #include <tbb/parallel_for.h> 57 template<
typename TreeType>
119 TreeType& tree(
size_t level);
124 const TreeType& constTree(
size_t level)
const;
129 TreePtr treePtr(
size_t level);
134 ConstTreePtr constTreePtr(
size_t level)
const;
165 GridPtr grid(
size_t level);
170 ConstGridPtr grid(
size_t level)
const;
179 template<Index Order>
180 GridPtr
createGrid(
float level,
size_t grainSize = 1)
const;
208 static Vec3R xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level);
211 static Vec3R xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level);
212 static Vec3R xyz(
const Vec3R& in_xyz,
double in_level,
double out_level);
220 template<Index Order>
230 ValueType sampleValue(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
const;
231 template<Index Order>
232 ValueType sampleValue(
const Vec3R& in_ijk,
size_t in_level,
size_t out_level)
const;
241 template<Index Order>
242 ValueType sampleValue(
const Coord& ijk,
double level)
const;
251 template<Index Order>
252 ValueType sampleValue(
const Vec3R& xyz,
double level)
const;
262 ValueType prolongateVoxel(
const Coord& coords,
const size_t level)
const;
268 void prolongateActiveVoxels(
size_t destlevel,
size_t grainSize = 1);
276 ValueType restrictVoxel(
Coord ijk,
const size_t level,
bool useInjection =
false)
const;
284 void restrictActiveVoxels(
size_t destlevel,
size_t grainSize = 1);
287 void print(std::ostream& = std::cout,
int verboseLevel = 1)
const;
329 void topDownRestrict(
bool useInjection);
331 inline void initMeta();
344 template<Index Order>
348 template<
typename OpType>
struct CookOp;
351 std::vector<TreePtr> mTrees;
356 template<
typename TreeType>
357 MultiResGrid<TreeType>::
358 MultiResGrid(
size_t levels,
ValueType background,
double voxelSize)
360 , mTransform(math::Transform::createLinearTransform( voxelSize ))
363 for (
size_t i=0; i<levels; ++i) mTrees[i] =
TreePtr(
new TreeType(background));
366 template<
typename TreeType>
371 , mTransform( grid.transform().copy() )
374 mTrees[0].reset(
new TreeType(
grid.tree() ) );
375 mTrees[0]->voxelizeActiveTiles();
376 this->topDownRestrict(useInjection);
379 template<
typename TreeType>
384 , mTransform( grid->transform().copy() )
387 mTrees[0] =
grid->treePtr();
388 mTrees[0]->voxelizeActiveTiles();
390 this->topDownRestrict(useInjection);
393 template<
typename TreeType>
397 assert( level < mTrees.size() );
398 return *mTrees[level];
401 template<
typename TreeType>
405 assert( level < mTrees.size() );
406 return *mTrees[level];
409 template<
typename TreeType>
413 assert( level < mTrees.size() );
414 return mTrees[level];
417 template<
typename TreeType>
421 assert( level < mTrees.size() );
422 return mTrees[level];
425 template<
typename TreeType>
431 if (level>0) xform->preScale(
Real(1 << level) );
435 std::stringstream ss;
436 ss << this->getName() <<
"_level_" << level;
441 template<
typename TreeType>
448 template<
typename TreeType>
449 template<Index Order>
453 assert( level >= 0.0f && level <=
float(mTrees.size()-1) );
457 xform->preScale(
math::Pow(2.0f, level) );
461 std::stringstream ss;
462 ss << this->getName() <<
"_level_" << level;
465 if (
size_t(floorf(level)) == size_t(ceilf(level)) ) {
466 grid->
setTree( this->constTree(
size_t(floorf(level))).copy() );
468 FractionOp<Order> tmp(*
this, grid->
tree(), level, grainSize);
478 template<
typename TreeType>
483 for (
size_t level=0; level<mTrees.size(); ++level) grids->push_back(this->grid(level));
487 template<
typename TreeType>
492 for (
size_t level=0; level<mTrees.size(); ++level) grids->push_back(this->grid(level));
496 template<
typename TreeType>
498 xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
503 template<
typename TreeType>
505 xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level)
507 return in_xyz *
Real(1 << in_level) /
Real(1 << out_level);
510 template<
typename TreeType>
512 xyz(
const Vec3R& in_xyz,
double in_level,
double out_level)
514 return in_xyz *
math::Pow(2.0, in_level - out_level);
518 template<
typename TreeType>
519 template<Index Order>
523 assert( in_level >= 0 && in_level < mTrees.size() );
524 assert( out_level >= 0 && out_level < mTrees.size() );
529 template<
typename TreeType>
530 template<Index Order>
534 assert( in_level >= 0 && in_level < mTrees.size() );
535 assert( out_level >= 0 && out_level < mTrees.size() );
540 template<
typename TreeType>
541 template<Index Order>
545 assert( level >= 0.0 && level <=
double(mTrees.size()-1) );
546 const size_t level0 = size_t(floor(level)), level1 = size_t(ceil(level));
547 const ValueType v0 = this->
template sampleValue<Order>( ijk, 0, level0 );
548 if ( level0 == level1 )
return v0;
549 assert( level1 - level0 == 1 );
550 const ValueType v1 = this->
template sampleValue<Order>( ijk, 0, level1 );
557 template<
typename TreeType>
558 template<Index Order>
562 assert( level >= 0.0 && level <=
double(mTrees.size()-1) );
563 const size_t level0 = size_t(floor(level)), level1 = size_t(ceil(level));
564 const ValueType v0 = this->
template sampleValue<Order>( xyz, 0, level0 );
565 if ( level0 == level1 )
return v0;
566 assert( level1 - level0 == 1 );
567 const ValueType v1 = this->
template sampleValue<Order>( xyz, 0, level1 );
574 template<
typename TreeType>
578 assert( level+1 < mTrees.size() );
580 return ProlongateOp::run(ijk, acc);
583 template<
typename TreeType>
587 assert( destlevel < mTrees.size()-1 );
588 TreeType &fineTree = *mTrees[ destlevel ];
589 const TreeType &coarseTree = *mTrees[ destlevel+1 ];
590 CookOp<ProlongateOp> tmp( coarseTree, fineTree, grainSize );
593 template<
typename TreeType>
597 assert( destlevel > 0 && destlevel < mTrees.size() );
598 const TreeType &fineTree = *mTrees[ destlevel-1 ];
599 if ( useInjection )
return fineTree.getValue(ijk<<1);
601 return RestrictOp::run( ijk, acc);
604 template<
typename TreeType>
608 assert( destlevel > 0 && destlevel < mTrees.size() );
609 const TreeType &fineTree = *mTrees[ destlevel-1 ];
610 TreeType &coarseTree = *mTrees[ destlevel ];
611 CookOp<RestrictOp> tmp( fineTree, coarseTree, grainSize );
614 template<
typename TreeType>
616 print(std::ostream& os,
int verboseLevel)
const 618 os <<
"MultiResGrid with " << mTrees.size() <<
" levels\n";
619 for (
size_t i=0; i<mTrees.size(); ++i) {
620 os <<
"Level " << i <<
": ";
621 mTrees[i]->print(os, verboseLevel);
625 os <<
"Additional metadata:" << std::endl;
627 os <<
" " << it->first;
629 const std::string value = it->second->str();
630 if (!value.empty()) os <<
": " << value;
636 os <<
"Transform:" << std::endl;
637 transform().print(os,
" ");
641 template<
typename TreeType>
645 const size_t levels = this->numLevels();
649 this->insertMeta(
"MultiResGrid_Levels",
Int64Metadata( levels ) );
652 template<
typename TreeType>
653 void MultiResGrid<TreeType>::
654 topDownRestrict(
bool useInjection)
657 for (
size_t n=1; n<mTrees.size(); ++n) {
658 const TreeType &fineTree = *mTrees[n-1];
659 mTrees[n] = TreePtr(
new TreeType( fineTree.background() ) );
660 TreeType &coarseTree = *mTrees[n];
662 for (ValueOnCIter it = fineTree.cbeginValueOn(); it; ++it) {
663 const Coord ijk = it.getCoord();
664 if ( (ijk[0] & 1) || (ijk[1] & 1) || (ijk[2] & 1) )
continue;
665 coarseTree.setValue( ijk >> 1, *it );
668 MaskOp tmp(fineTree, coarseTree, 128);
669 this->restrictActiveVoxels(n, 64);
678 template<
typename TreeType>
681 using MaskT =
typename TreeType::template ValueConverter<ValueMask>::Type;
682 using PoolType = tbb::enumerable_thread_specific<TreeType>;
685 using VoxelIterT =
typename ManagerT::LeafNodeType::ValueOnCIter;
687 MaskOp(
const TreeType& fineTree, TreeType& coarseTree,
size_t grainSize = 1)
688 : mPool(new
PoolType( coarseTree ) )
690 assert( coarseTree.empty() );
700 tbb::parallel_for(leafs.
leafRange( grainSize ), *
this);
703 using IterT =
typename PoolType::const_iterator;
704 for (IterT it=mPool->begin(); it!=mPool->end(); ++it) coarseTree.topologyUnion( *it );
709 Accessor coarseAcc( mPool->local() );
710 for (
typename RangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
711 for (
VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
712 Coord ijk = voxelIter.getCoord();
713 if ( (ijk[2] & 1) || (ijk[1] & 1) || (ijk[0] & 1) )
continue;
714 coarseAcc.setValueOn( ijk >> 1 );
721 template<
typename TreeType>
722 template<Index Order>
725 using MaskT =
typename TreeType::template ValueConverter<ValueMask>::Type;
726 using PoolType = tbb::enumerable_thread_specific<MaskT>;
727 using PoolIterT =
typename PoolType::iterator;
730 using Range1 =
typename Manager1::LeafRange;
731 using Range2 =
typename Manager2::LeafRange;
736 size_t grainSize = 1)
739 , mTree0( &*(parent.mTrees[
size_t(floorf(level))]) )
740 , mTree1( &*(parent.mTrees[
size_t(ceilf(level))]) )
742 assert( midTree.empty() );
743 assert( mTree0 != mTree1 );
746 MaskT examplar(
false );
747 mPool =
new PoolType( examplar );
751 tbb::parallel_for( manager.
leafRange(grainSize), *this );
755 tbb::parallel_for(tbb::blocked_range<PoolIterT>(mPool->begin(),mPool->end(),1), *
this);
758 for (PoolIterT it=mPool->begin(); it!=mPool->end(); ++it) midTree.topologyUnion( *it );
762 Manager2 manager( midTree );
763 tbb::parallel_for(manager.leafRange(grainSize), *
this);
766 void operator()(
const Range1& range)
const 768 using VoxelIter =
typename Manager1::LeafNodeType::ValueOnCIter;
779 for (
typename Range1::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
780 for (VoxelIter voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
781 Coord ijk = voxelIter.getCoord();
783 const auto value0 = ijk[0] *
scale;
784 const auto value1 = ijk[1] *
scale;
785 const auto value2 = ijk[2] *
scale;
791 acc.setValueOn( ijk );
795 void operator()(
const tbb::blocked_range<PoolIterT>& range)
const 797 for (PoolIterT it=range.begin(); it!=range.end(); ++it) {
801 void operator()(
const Range2 &r)
const 803 using VoxelIter =
typename TreeType::LeafNodeType::ValueOnIter;
817 const float scale0 =
math::Pow( 2.0f, b );
818 const float scale1 =
math::Pow( 2.0f,-a );
819 ConstAccessor acc0( *mTree0 ), acc1( *mTree1 );
820 for (
typename Range2::Iterator leafIter = r.begin(); leafIter; ++leafIter) {
821 for (VoxelIter voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
822 const Vec3R xyz =
Vec3R( voxelIter.getCoord().data() );
826 const auto value0 = a*v0;
827 const auto value1 = b*v1;
829 voxelIter.setValue( ValueType(value0 + value1) );
835 const TreeType *mTree0, *mTree1;
839 template<
typename TreeType>
840 template<
typename OperatorType>
841 struct MultiResGrid<TreeType>::CookOp
843 using ManagerT = tree::LeafManager<TreeType>;
844 using RangeT =
typename ManagerT::LeafRange;
846 CookOp(
const TreeType& srcTree, TreeType& dstTree,
size_t grainSize): acc(srcTree)
848 ManagerT leafs(dstTree);
849 tbb::parallel_for(leafs.leafRange(grainSize), *
this);
851 CookOp(
const CookOp &other): acc(other.acc.tree()) {}
853 void operator()(
const RangeT& range)
const 855 for (
auto leafIt = range.begin(); leafIt; ++leafIt) {
856 auto& phi = leafIt.buffer(0);
857 for (
auto voxelIt = leafIt->beginValueOn(); voxelIt; ++voxelIt) {
858 phi.setValue(voxelIt.pos(), OperatorType::run(voxelIt.getCoord(), acc));
863 const ConstAccessor acc;
867 template<
typename TreeType>
890 for (
int i=-1; i<=1; i+=2) {
891 for (
int j=-1; j<=1; j+=2) {
900 template<
typename TreeType>
908 switch ( (ijk[0] & 1) | ((ijk[1] & 1) << 1) | ((ijk[2] & 1) << 2) ) {
938 for (
int i=-1; i<=1; i+=2) {
939 for (
int j=-1; j<=1; j+=2) {
951 #endif // OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
Definition: ValueAccessor.h:193
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
static const char *const META_GRID_NAME
Definition: Grid.h:352
SharedPtr< Grid > Ptr
Definition: Grid.h:574
Type FractionalPart(Type x)
Return the fractional part of x.
Definition: Math.h:790
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:82
std::shared_ptr< T > SharedPtr
Definition: Types.h:91
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:766
static std::string gridClassToString(GridClass)
Return the metadata string value for the given class of volumetric data.
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:25
static const char *const META_GRID_CLASS
Definition: Grid.h:350
double Real
Definition: Types.h:37
static Ptr create()
Return a new grid with background value zero.
Definition: Grid.h:1318
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:92
Defined various multi-threaded utility functions for trees.
Definition: Exceptions.h:65
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:102
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:358
SharedPtr< GridPtrVec > GridPtrVecPtr
Definition: Grid.h:512
Definition: LeafManager.h:99
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:905
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.
Definition: Grid.h:1460
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
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...
SharedPtr< const Grid > ConstPtr
Definition: Grid.h:575
Implementation of morphological dilation and erosion.
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:230
TypedMetadata< std::string > StringMetadata
Definition: Metadata.h:386
Definition: Exceptions.h:13
GridClass getGridClass() const
Return the class of volumetric data (level set, fog volume, etc.) that is stored in this grid...
math::Vec3< Real > Vec3R
Definition: Types.h:49
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:82
const Int32 * data() const
Definition: Coord.h:140
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:681
GridType::Ptr createGrid(const typename GridType::ValueType &background)
Create a new grid of type GridType with a given background value.
Definition: Grid.h:1728
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:509
Type Pow(Type x, int n)
Return xn.
Definition: Math.h:508
std::vector< GridBase::ConstPtr > GridCPtrVec
Definition: Grid.h:514
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:28
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
void setName(const std::string &)
Specify a name for this grid.
TypedMetadata< int64_t > Int64Metadata
Definition: Metadata.h:385
GridClass
Definition: Types.h:452
static GridClass stringToGridClass(const std::string &)
Return the class of volumetric data specified by the given string.
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:154
SharedPtr< GridCPtrVec > GridCPtrVecPtr
Definition: Grid.h:517
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:620
TypedMetadata< float > FloatMetadata
Definition: Metadata.h:383
void setTransform(math::Transform::Ptr)
Associate the given transform with this grid, in place of its existing transform. ...
Definition: Grid.h:1242