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;
170 ConstGridPtr grid(
size_t level)
const;
179 template<Index Order>
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>
231 template<Index Order>
241 template<Index Order>
251 template<Index Order>
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>
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>
443 grid(
size_t level)
const
448 template<
typename TreeType>
449 template<Index Order>
451 createGrid(
float level,
size_t grainSize)
const
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() );
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);
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) {
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
static std::string gridClassToString(GridClass)
Return the metadata string value for the given class of volumetric data.
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.
Definition: Grid.h:1471
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
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.
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:26
GridClass
Definition: openvdb/Types.h:313
SharedPtr< GridPtrVec > GridPtrVecPtr
Definition: Grid.h:512
void run(const char *ax, openvdb::GridBase &grid)
Run a full AX pipeline (parse, compile and execute) on a single OpenVDB Grid.
std::vector< GridBase::ConstPtr > GridCPtrVec
Definition: Grid.h:514
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:347
@ GRID_LEVEL_SET
Definition: openvdb/Types.h:315
void setValueOn(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:255
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...
math::Vec3< Real > Vec3R
Definition: openvdb/Types.h:50
TypedMetadata< std::string > StringMetadata
Definition: Metadata.h:363
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:92
Type Pow(Type x, int n)
Return xn.
Definition: Math.h:554
Definition: ValueAccessor.h:183
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:82
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:630
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:509
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:572
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:812
SharedPtr< const Grid > ConstPtr
Definition: Grid.h:575
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:219
Defined various multi-threaded utility functions for trees.
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:908
Type FractionalPart(Type x)
Return the fractional part of x.
Definition: Math.h:836
TypedMetadata< int64_t > Int64Metadata
Definition: Metadata.h:362
openvdb::GridBase::Ptr GridPtr
Definition: openvdb_houdini/openvdb_houdini/Utils.h:34
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:85
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:147
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...
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: openvdb/Types.h:542
TypedMetadata< float > FloatMetadata
Definition: Metadata.h:360
Implementation of morphological dilation and erosion.
double Real
Definition: openvdb/Types.h:38
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:95
SharedPtr< Grid > Ptr
Definition: Grid.h:574
static const char *const META_GRID_NAME
Definition: Grid.h:352
SharedPtr< GridCPtrVec > GridCPtrVecPtr
Definition: Grid.h:517
static const char *const META_GRID_CLASS
Definition: Grid.h:350
static Ptr create()
Return a new grid with background value zero.
Definition: Grid.h:1321
@ GRID_UNKNOWN
Definition: openvdb/Types.h:314
Definition: openvdb/Exceptions.h:65
std::shared_ptr< T > SharedPtr
Definition: openvdb/Types.h:92
Definition: openvdb/Exceptions.h:13
Definition: LeafManager.h:102
const Int32 * data() const
Definition: Coord.h:140
static GridClass stringToGridClass(const std::string &)
Return the class of volumetric data specified by the given string.