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>
210 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);
229 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) );
435 std::stringstream ss;
436 ss << this->getName() <<
"_level_" << level;
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) );
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() );
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) {
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Implementation of morphological dilation and erosion.
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
Defined various multi-threaded utility functions for trees.
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
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.
void setTransform(math::Transform::Ptr)
Associate the given transform with this grid, in place of its existing transform.
Definition: Grid.h:1247
GridClass getGridClass() const
Return the class of volumetric data (level set, fog volume, etc.) that is stored in this grid.
static const char *const META_GRID_NAME
Definition: Grid.h:357
static const char *const META_GRID_CLASS
Definition: Grid.h:355
static GridClass stringToGridClass(const std::string &)
Return the class of volumetric data specified by the given string.
static std::string gridClassToString(GridClass)
Return the metadata string value for the given class of volumetric data.
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:577
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.
Definition: Grid.h:1473
SharedPtr< const Grid > ConstPtr
Definition: Grid.h:580
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:917
SharedPtr< Grid > Ptr
Definition: Grid.h:579
static Ptr create()
Return a new grid with background value zero.
Definition: Grid.h:1323
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:564
Definition: Exceptions.h:65
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:25
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:91
const Int32 * data() const
Definition: Coord.h:139
Definition: LeafManager.h:102
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:85
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:345
Definition: ValueAccessor.h:183
void setValueOn(const Coord &xyz, const ValueType &value)
Definition: ValueAccessor.h:255
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:219
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.
void run(const char *ax, openvdb::GridBase &grid)
Run a full AX pipeline (parse, compile and execute) on a single OpenVDB Grid.
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...
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:637
Type FractionalPart(Type x)
Return the fractional part of x.
Definition: Math.h:846
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:822
Type Pow(Type x, int n)
Return xn.
Definition: Math.h:564
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:514
TypedMetadata< float > FloatMetadata
Definition: Metadata.h:360
double Real
Definition: Types.h:60
GridClass
Definition: Types.h:335
@ GRID_LEVEL_SET
Definition: Types.h:337
@ GRID_UNKNOWN
Definition: Types.h:336
SharedPtr< GridCPtrVec > GridCPtrVecPtr
Definition: Grid.h:522
SharedPtr< GridPtrVec > GridPtrVecPtr
Definition: Grid.h:517
TypedMetadata< std::string > StringMetadata
Definition: Metadata.h:363
math::Vec3< Real > Vec3R
Definition: Types.h:72
std::shared_ptr< T > SharedPtr
Definition: Types.h:114
TypedMetadata< int64_t > Int64Metadata
Definition: Metadata.h:362
std::vector< GridBase::ConstPtr > GridCPtrVec
Definition: Grid.h:519
openvdb::GridBase::Ptr GridPtr
Definition: Utils.h:34
Definition: Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
#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:180