Go to the documentation of this file.
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;
299 this->removeMeta(GridBase::META_GRID_NAME);
307 this->getMetadata<StringMetadata>(GridBase::META_GRID_CLASS);
308 return s ? GridBase::stringToGridClass(s->value()) :
GRID_UNKNOWN;
314 this->insertMeta(GridBase::META_GRID_CLASS,
StringMetadata(GridBase::gridClassToString(cls)));
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) );
432 grid->setTransform( xform );
433 grid->insertMeta( *this->copyMeta() );
434 grid->insertMeta(
"MultiResGrid_Level",
Int64Metadata(level));
435 std::stringstream ss;
436 ss << this->getName() <<
"_level_" << level;
437 grid->setName( ss.str() );
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) );
458 grid->setTransform( xform );
459 grid->insertMeta( *(this->copyMeta()) );
460 grid->insertMeta(
"MultiResGrid_Level",
FloatMetadata(level) );
461 std::stringstream ss;
462 ss << this->getName() <<
"_level_" << level;
463 grid->setName( ss.str() );
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;
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
TypedMetadata< int64_t > Int64Metadata
Definition: Metadata.h:385
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
math::Vec3< Real > Vec3R
Definition: Types.h:49
TypedMetadata< std::string > StringMetadata
Definition: Metadata.h:386
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:766
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:25
void setValueOn(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:266
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:358
Type FractionalPart(Type x)
Return the fractional part of x.
Definition: Math.h:790
Definition: ValueAccessor.h:193
SharedPtr< Grid > Ptr
Definition: Grid.h:574
std::vector< GridBase::ConstPtr > GridCPtrVec
Definition: Grid.h:514
TypedMetadata< float > FloatMetadata
Definition: Metadata.h:383
std::shared_ptr< T > SharedPtr
Definition: Types.h:91
double Real
Definition: Types.h:37
Type Pow(Type x, int n)
Return xn.
Definition: Math.h:508
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:92
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:230
SharedPtr< GridCPtrVec > GridCPtrVecPtr
Definition: Grid.h:517
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:28
static Ptr create()
Return a new grid with background value zero.
Definition: Grid.h:1318
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.
Definition: Grid.h:1460
Definition: LeafManager.h:99
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:82
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:681
@ GRID_UNKNOWN
Definition: Types.h:453
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:154
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
Implementation of morphological dilation and erosion.
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
#define OPENVDB_VERSION_NAME
Definition: version.h:108
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:620
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:509
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...
Definition: Exceptions.h:65
GridClass
Definition: Types.h:452
@ GRID_LEVEL_SET
Definition: Types.h:454
SharedPtr< GridPtrVec > GridPtrVecPtr
Definition: Grid.h:512
Definition: Exceptions.h:13
SharedPtr< const Grid > ConstPtr
Definition: Grid.h:575
GridType::Ptr createGrid(const typename GridType::ValueType &background)
Create a new grid of type GridType with a given background value.
Definition: Grid.h:1728
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:82
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:905
const Int32 * data() const
Definition: Coord.h:140