21#ifndef OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
22#define OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
41#include <tbb/blocked_range.h>
42#include <tbb/enumerable_thread_specific.h>
43#include <tbb/parallel_for.h>
56template<
typename TreeType>
118 TreeType&
tree(
size_t level);
123 const TreeType& constTree(
size_t level)
const;
128 TreePtr treePtr(
size_t level);
133 ConstTreePtr constTreePtr(
size_t level)
const;
164 GridPtr grid(
size_t level);
169 ConstGridPtr grid(
size_t level)
const;
178 template<Index Order>
209 static Vec3R xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level);
210 static Vec3R xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level);
211 static Vec3R xyz(
const Vec3R& in_xyz,
double in_level,
double out_level);
228 template<Index Order>
230 template<Index Order>
240 template<Index Order>
250 template<Index Order>
286 void print(std::ostream& = std::cout,
int verboseLevel = 1)
const;
328 void topDownRestrict(
bool useInjection);
330 inline void initMeta();
343 template<Index Order>
347 template<
typename OpType>
struct CookOp;
350 std::vector<TreePtr> mTrees;
355template<
typename TreeType>
359 , mTransform(
math::Transform::createLinearTransform( voxelSize ))
362 for (
size_t i=0; i<levels; ++i) mTrees[i] =
TreePtr(
new TreeType(background));
365template<
typename TreeType>
373 mTrees[0].reset(
new TreeType(
grid.tree() ) );
374 mTrees[0]->voxelizeActiveTiles();
375 this->topDownRestrict(useInjection);
378template<
typename TreeType>
386 mTrees[0] =
grid->treePtr();
387 mTrees[0]->voxelizeActiveTiles();
389 this->topDownRestrict(useInjection);
392template<
typename TreeType>
397 return *mTrees[level];
400template<
typename TreeType>
405 return *mTrees[level];
408template<
typename TreeType>
413 return mTrees[level];
416template<
typename TreeType>
421 return mTrees[level];
424template<
typename TreeType>
430 if (level>0) xform->preScale(
Real(1 << level) );
431 grid->setTransform( xform );
434 std::stringstream ss;
435 ss << this->
getName() <<
"_level_" << level;
436 grid->setName( ss.str() );
440template<
typename TreeType>
442grid(
size_t level)
const
447template<
typename TreeType>
450createGrid(
float level,
size_t grainSize)
const
452 OPENVDB_ASSERT( level >= 0.0f && level <=
float(mTrees.size()-1) );
456 xform->preScale(
math::Pow(2.0f, level) );
457 grid->setTransform( xform );
460 std::stringstream ss;
461 ss << this->
getName() <<
"_level_" << level;
462 grid->setName( ss.str() );
464 if (
size_t(floorf(level)) ==
size_t(ceilf(level)) ) {
465 grid->setTree( this->
constTree(
size_t(floorf(level))).copy() );
467 FractionOp<Order> tmp(*
this,
grid->tree(), level, grainSize);
477template<
typename TreeType>
482 for (
size_t level=0; level<mTrees.size(); ++level)
grids->push_back(this->grid(level));
486template<
typename TreeType>
491 for (
size_t level=0; level<mTrees.size(); ++level)
grids->push_back(this->grid(level));
495template<
typename TreeType>
497xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
502template<
typename TreeType>
504xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level)
506 return in_xyz *
Real(1 << in_level) /
Real(1 << out_level);
509template<
typename TreeType>
511xyz(
const Vec3R& in_xyz,
double in_level,
double out_level)
513 return in_xyz *
math::Pow(2.0, in_level - out_level);
517template<
typename TreeType>
524 const ConstAccessor acc(*mTrees[out_level]);
528template<
typename TreeType>
535 const ConstAccessor acc(*mTrees[out_level]);
539template<
typename TreeType>
544 OPENVDB_ASSERT( level >= 0.0 && level <=
double(mTrees.size()-1) );
545 const size_t level0 = size_t(floor(level)), level1 = size_t(ceil(level));
547 if ( level0 == level1 )
return v0;
556template<
typename TreeType>
561 OPENVDB_ASSERT( level >= 0.0 && level <=
double(mTrees.size()-1) );
562 const size_t level0 = size_t(floor(level)), level1 = size_t(ceil(level));
564 if ( level0 == level1 )
return v0;
573template<
typename TreeType>
578 const ConstAccessor acc(*mTrees[level + 1]);
582template<
typename TreeType>
587 TreeType &fineTree = *mTrees[ destlevel ];
588 const TreeType &coarseTree = *mTrees[ destlevel+1 ];
589 CookOp<ProlongateOp> tmp( coarseTree, fineTree, grainSize );
592template<
typename TreeType>
597 const TreeType &fineTree = *mTrees[ destlevel-1 ];
598 if ( useInjection )
return fineTree.getValue(ijk<<1);
599 const ConstAccessor acc( fineTree );
603template<
typename TreeType>
608 const TreeType &fineTree = *mTrees[ destlevel-1 ];
609 TreeType &coarseTree = *mTrees[ destlevel ];
610 CookOp<RestrictOp> tmp( fineTree, coarseTree, grainSize );
613template<
typename TreeType>
615print(std::ostream& os,
int verboseLevel)
const
617 os <<
"MultiResGrid with " << mTrees.size() <<
" levels\n";
618 for (
size_t i=0; i<mTrees.size(); ++i) {
619 os <<
"Level " << i <<
": ";
620 mTrees[i]->print(os, verboseLevel);
624 os <<
"Additional metadata:" << std::endl;
626 os <<
" " << it->first;
628 const std::string value = it->second->str();
629 if (!value.empty()) os <<
": " << value;
635 os <<
"Transform:" << std::endl;
640template<
typename TreeType>
644 const size_t levels = this->numLevels();
648 this->insertMeta(
"MultiResGrid_Levels",
Int64Metadata( levels ) );
651template<
typename TreeType>
652void MultiResGrid<TreeType>::
653topDownRestrict(
bool useInjection)
656 for (
size_t n=1; n<mTrees.size(); ++n) {
657 const TreeType &fineTree = *mTrees[n-1];
658 mTrees[n] = TreePtr(
new TreeType( fineTree.background() ) );
659 TreeType &coarseTree = *mTrees[n];
661 for (ValueOnCIter it = fineTree.cbeginValueOn(); it; ++it) {
662 const Coord ijk = it.getCoord();
663 if ( (ijk[0] & 1) || (ijk[1] & 1) || (ijk[2] & 1) )
continue;
664 coarseTree.setValue( ijk >> 1, *it );
667 MaskOp tmp(fineTree, coarseTree, 128);
668 this->restrictActiveVoxels(n, 64);
677template<
typename TreeType>
680 using MaskT =
typename TreeType::template ValueConverter<ValueMask>::Type;
681 using PoolType = tbb::enumerable_thread_specific<TreeType>;
683 using RangeT =
typename ManagerT::LeafRange;
684 using VoxelIterT =
typename ManagerT::LeafNodeType::ValueOnCIter;
686 MaskOp(
const TreeType& fineTree, TreeType& coarseTree,
size_t grainSize = 1)
699 tbb::parallel_for(leafs.
leafRange( grainSize ), *
this);
702 using IterT =
typename PoolType::const_iterator;
703 for (IterT it=
mPool->begin(); it!=
mPool->end(); ++it) coarseTree.topologyUnion( *it );
708 Accessor coarseAcc(
mPool->local() );
709 for (
typename RangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
710 for (
VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
711 Coord ijk = voxelIter.getCoord();
712 if ( (ijk[2] & 1) || (ijk[1] & 1) || (ijk[0] & 1) )
continue;
720template<
typename TreeType>
722struct MultiResGrid<TreeType>::FractionOp
724 using MaskT =
typename TreeType::template ValueConverter<ValueMask>::Type;
725 using PoolType = tbb::enumerable_thread_specific<MaskT>;
726 using PoolIterT =
typename PoolType::iterator;
729 using Range1 =
typename Manager1::LeafRange;
730 using Range2 =
typename Manager2::LeafRange;
735 size_t grainSize = 1)
738 , mTree0( &*(parent.mTrees[
size_t(floorf(level))]) )
739 , mTree1( &*(parent.mTrees[
size_t(ceilf(level))]) )
745 MaskT examplar(
false );
746 mPool =
new PoolType( examplar );
750 tbb::parallel_for( manager.
leafRange(grainSize), *
this );
754 tbb::parallel_for(tbb::blocked_range<PoolIterT>(mPool->begin(),mPool->end(),1), *
this);
757 for (PoolIterT it=mPool->begin(); it!=mPool->end(); ++it) midTree.topologyUnion( *it );
761 Manager2 manager( midTree );
762 tbb::parallel_for(manager.leafRange(grainSize), *
this);
765 void operator()(
const Range1& range)
const
767 using VoxelIter =
typename Manager1::LeafNodeType::ValueOnCIter;
778 for (
typename Range1::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
779 for (VoxelIter voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
780 Coord ijk = voxelIter.getCoord();
782 const auto value0 = ijk[0] * scale;
783 const auto value1 = ijk[1] * scale;
784 const auto value2 = ijk[2] * scale;
790 acc.setValueOn( ijk );
794 void operator()(
const tbb::blocked_range<PoolIterT>& range)
const
796 for (PoolIterT it=range.begin(); it!=range.end(); ++it) {
800 void operator()(
const Range2 &r)
const
802 using VoxelIter =
typename TreeType::LeafNodeType::ValueOnIter;
816 const float scale0 =
math::Pow( 2.0f, b );
817 const float scale1 =
math::Pow( 2.0f,-a );
818 ConstAccessor acc0( *mTree0 ), acc1( *mTree1 );
819 for (
typename Range2::Iterator leafIter = r.begin(); leafIter; ++leafIter) {
820 for (VoxelIter voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
821 const Vec3R xyz =
Vec3R( voxelIter.getCoord().data() );
825 const auto value0 = a*v0;
826 const auto value1 = b*v1;
828 voxelIter.setValue( ValueType(value0 + value1) );
834 const TreeType *mTree0, *mTree1;
838template<
typename TreeType>
839template<
typename OperatorType>
840struct MultiResGrid<TreeType>::CookOp
842 using ManagerT = tree::LeafManager<TreeType>;
843 using RangeT =
typename ManagerT::LeafRange;
845 CookOp(
const TreeType& srcTree, TreeType& dstTree,
size_t grainSize): acc(srcTree)
847 ManagerT leafs(dstTree);
848 tbb::parallel_for(leafs.leafRange(grainSize), *
this);
850 CookOp(
const CookOp &other): acc(other.acc.tree()) {}
852 void operator()(
const RangeT& range)
const
854 for (
auto leafIt = range.begin(); leafIt; ++leafIt) {
855 auto& phi = leafIt.buffer(0);
856 for (
auto voxelIt = leafIt->beginValueOn(); voxelIt; ++voxelIt) {
857 phi.setValue(voxelIt.pos(), OperatorType::run(voxelIt.getCoord(), acc));
862 const ConstAccessor acc;
866template<
typename TreeType>
889 for (
int i=-1; i<=1; i+=2) {
890 for (
int j=-1; j<=1; j+=2) {
899template<
typename TreeType>
907 switch ( (ijk[0] & 1) | ((ijk[1] & 1) << 1) | ((ijk[2] & 1) << 2) ) {
937 for (
int i=-1; i<=1; i+=2) {
938 for (
int j=-1; j<=1; j+=2) {
952#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
954#ifdef OPENVDB_INSTANTIATE_MULTIRESGRID
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
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.
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...
static const char *const META_GRID_NAME
Definition Grid.h:353
static const char *const META_GRID_CLASS
Definition Grid.h:351
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:571
SharedPtr< const Grid > ConstPtr
Definition Grid.h:574
SharedPtr< Grid > Ptr
Definition Grid.h:573
static Ptr create()
Return a new grid with background value zero.
Definition Grid.h:1341
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition Types.h:754
Definition Exceptions.h:65
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition Coord.h:92
const Int32 * data() const
Definition Coord.h:140
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition LeafManager.h:86
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition LeafManager.h:346
void setValueOn(const Coord &xyz, const ValueType &value)
Definition ValueAccessor.h:569
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition ValueAccessor.h:455
Type Pow(Type x, int n)
Return xn.
Definition Math.h:583
float Round(float x)
Return x rounded to the nearest integer.
Definition Math.h:887
Type FractionalPart(Type x)
Return the fractional part of x.
Definition Math.h:911
Definition PointDataGrid.h:170
ValueAccessorImpl< TreeType, IsSafe, MutexType, openvdb::make_index_sequence< CacheLevels > > ValueAccessor
Default alias for a ValueAccessor. This is simply a helper alias for the generic definition but takes...
Definition ValueAccessor.h:86
std::vector< GridBase::Ptr > GridPtrVec
Definition Grid.h:508
TypedMetadata< float > FloatMetadata
Definition Metadata.h:361
double Real
Definition Types.h:40
GridClass
Definition Types.h:524
@ GRID_LEVEL_SET
Definition Types.h:526
@ GRID_UNKNOWN
Definition Types.h:525
SharedPtr< GridCPtrVec > GridCPtrVecPtr
Definition Grid.h:516
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:71
SharedPtr< GridPtrVec > GridPtrVecPtr
Definition Grid.h:511
TypedMetadata< std::string > StringMetadata
Definition Metadata.h:365
math::Vec3< Real > Vec3R
Definition Types.h:53
std::shared_ptr< T > SharedPtr
Definition Types.h:95
TypedMetadata< int64_t > Int64Metadata
Definition Metadata.h:364
std::vector< GridBase::ConstPtr > GridCPtrVec
Definition Grid.h:513
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:284
#define OPENVDB_INSTANTIATE_CLASS
Definition version.h.in:224