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...
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
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
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:291
#define OPENVDB_INSTANTIATE_CLASS
Definition version.h.in:231