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>
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() );
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
void run(const char *ax, openvdb::GridBase &grid)
Run a full AX pipeline (parse, compile and execute) on a single OpenVDB Grid.
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
TypedMetadata< int64_t > Int64Metadata
Definition: Metadata.h:362
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:178
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.
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:345
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:822
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:917
Type FractionalPart(Type x)
Return the fractional part of x.
Definition: Math.h:846
std::vector< GridBase::ConstPtr > GridCPtrVec
Definition: Grid.h:519
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:84
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:74
TypedMetadata< std::string > StringMetadata
Definition: Metadata.h:363
TypedMetadata< float > FloatMetadata
Definition: Metadata.h:360
Definition: ValueAccessor.h:182
SharedPtr< const Grid > ConstPtr
Definition: Grid.h:580
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Defined various multi-threaded utility functions for trees.
Definition: openvdb/Exceptions.h:65
std::shared_ptr< T > SharedPtr
Definition: openvdb/Types.h:110
openvdb::GridBase::Ptr GridPtr
Definition: openvdb_houdini/openvdb_houdini/Utils.h:34
Definition: LeafManager.h:101
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:25
void setValueOn(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:255
Type Pow(Type x, int n)
Return xn.
Definition: Math.h:564
SharedPtr< GridCPtrVec > GridCPtrVecPtr
Definition: Grid.h:522
const Int32 * data() const
Definition: Coord.h:140
@ GRID_LEVEL_SET
Definition: openvdb/Types.h:333
SharedPtr< GridPtrVec > GridPtrVecPtr
Definition: Grid.h:517
double Real
Definition: openvdb/Types.h:56
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:514
GridType::Ptr createGrid(const typename GridType::ValueType &background)
Create a new grid of type GridType with a given background value.
Definition: Grid.h:1739
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: openvdb/Types.h:560
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.
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.
Definition: Grid.h:1473
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:637
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:219
math::Vec3< Real > Vec3R
Definition: openvdb/Types.h:68
Definition: openvdb/Exceptions.h:13
SharedPtr< Grid > Ptr
Definition: Grid.h:579
static Ptr create()
Return a new grid with background value zero.
Definition: Grid.h:1323
GridClass
Definition: openvdb/Types.h:331
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:28
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:92
@ GRID_UNKNOWN
Definition: openvdb/Types.h:332