25 #ifndef OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
26 #define OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
44 #include <tbb/blocked_range.h>
45 #include <tbb/enumerable_thread_specific.h>
46 #include <tbb/parallel_for.h>
59 template<
typename TreeType>
181 template<Index Order>
212 static Vec3R xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level);
213 static Vec3R xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level);
214 static Vec3R xyz(
const Vec3R& in_xyz,
double in_level,
double out_level);
231 template<Index Order>
233 template<Index Order>
243 template<Index Order>
253 template<Index Order>
289 void print(std::ostream& = std::cout,
int verboseLevel = 1)
const;
331 void topDownRestrict(
bool useInjection);
333 inline void initMeta();
346 template<Index Order>
350 template<
typename OpType>
struct CookOp;
353 std::vector<TreePtr> mTrees;
358 template<
typename TreeType>
362 , mTransform(math::
Transform::createLinearTransform( voxelSize ))
365 for (
size_t i=0; i<
levels; ++i) mTrees[i] =
TreePtr(
new TreeType(background));
368 template<
typename TreeType>
376 mTrees[0].reset(
new TreeType( grid.
tree() ) );
377 mTrees[0]->voxelizeActiveTiles();
378 this->topDownRestrict(useInjection);
381 template<
typename TreeType>
389 mTrees[0] = grid->treePtr();
390 mTrees[0]->voxelizeActiveTiles();
392 this->topDownRestrict(useInjection);
395 template<
typename TreeType>
399 assert( level < mTrees.size() );
400 return *mTrees[
level];
403 template<
typename TreeType>
407 assert( level < mTrees.size() );
408 return *mTrees[
level];
411 template<
typename TreeType>
415 assert( level < mTrees.size() );
416 return mTrees[
level];
419 template<
typename TreeType>
423 assert( level < mTrees.size() );
424 return mTrees[
level];
427 template<
typename TreeType>
433 if (level>0) xform->preScale(
Real(1 << level) );
437 std::stringstream ss;
443 template<
typename TreeType>
450 template<
typename TreeType>
451 template<Index Order>
455 assert( level >= 0.0
f && level <=
float(mTrees.size()-1) );
463 std::stringstream ss;
467 if (
size_t(floorf(level)) == size_t(ceilf(level)) ) {
468 grid->
setTree( this->constTree(
size_t(floorf(level))).
copy() );
470 FractionOp<Order> tmp(*
this, grid->
tree(),
level, grainSize);
480 template<
typename TreeType>
489 template<
typename TreeType>
498 template<
typename TreeType>
500 xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
502 return Vec3R( in_ijk.data() ) *
Real(1 << in_level) /
Real(1 << out_level);
505 template<
typename TreeType>
507 xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level)
509 return in_xyz *
Real(1 << in_level) /
Real(1 << out_level);
512 template<
typename TreeType>
514 xyz(
const Vec3R& in_xyz,
double in_level,
double out_level)
516 return in_xyz *
math::Pow(2.0, in_level - out_level);
520 template<
typename TreeType>
521 template<Index Order>
523 sampleValue(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
const
525 assert( in_level < mTrees.size() );
526 assert( out_level < mTrees.size() );
531 template<
typename TreeType>
532 template<Index Order>
536 assert( in_level < mTrees.size() );
537 assert( out_level < mTrees.size() );
542 template<
typename TreeType>
543 template<Index Order>
547 assert( level >= 0.0 && level <=
double(mTrees.size()-1) );
548 const size_t level0 = size_t(
floor(level)), level1 = size_t(
ceil(level));
549 const ValueType v0 = this->
template sampleValue<Order>( ijk, 0, level0 );
550 if ( level0 == level1 )
return v0;
551 assert( level1 - level0 == 1 );
552 const ValueType v1 = this->
template sampleValue<Order>( ijk, 0, level1 );
559 template<
typename TreeType>
560 template<Index Order>
564 assert( level >= 0.0 && level <=
double(mTrees.size()-1) );
565 const size_t level0 = size_t(
floor(level)), level1 = size_t(
ceil(level));
566 const ValueType v0 = this->
template sampleValue<Order>( xyz, 0, level0 );
567 if ( level0 == level1 )
return v0;
568 assert( level1 - level0 == 1 );
569 const ValueType v1 = this->
template sampleValue<Order>( xyz, 0, level1 );
576 template<
typename TreeType>
580 assert( level+1 < mTrees.size() );
582 return ProlongateOp::run(ijk, acc);
585 template<
typename TreeType>
589 assert( destlevel < mTrees.size()-1 );
590 TreeType &fineTree = *mTrees[ destlevel ];
591 const TreeType &coarseTree = *mTrees[ destlevel+1 ];
592 CookOp<ProlongateOp> tmp( coarseTree, fineTree, grainSize );
595 template<
typename TreeType>
599 assert( destlevel > 0 && destlevel < mTrees.size() );
600 const TreeType &fineTree = *mTrees[ destlevel-1 ];
601 if ( useInjection )
return fineTree.getValue(ijk<<1);
603 return RestrictOp::run( ijk, acc);
606 template<
typename TreeType>
610 assert( destlevel > 0 && destlevel < mTrees.size() );
611 const TreeType &fineTree = *mTrees[ destlevel-1 ];
612 TreeType &coarseTree = *mTrees[ destlevel ];
613 CookOp<RestrictOp> tmp( fineTree, coarseTree, grainSize );
616 template<
typename TreeType>
618 print(std::ostream& os,
int verboseLevel)
const
620 os <<
"MultiResGrid with " << mTrees.size() <<
" levels\n";
621 for (
size_t i=0; i<mTrees.size(); ++i) {
622 os <<
"Level " << i <<
": ";
623 mTrees[i]->print(os, verboseLevel);
627 os <<
"Additional metadata:" << std::endl;
629 os <<
" " << it->first;
632 if (!value.empty()) os <<
": " << value;
638 os <<
"Transform:" << std::endl;
643 template<
typename TreeType>
647 const size_t levels = this->numLevels();
649 OPENVDB_THROW(ValueError,
"MultiResGrid: at least two levels are required");
651 this->insertMeta(
"MultiResGrid_Levels",
Int64Metadata( levels ) );
654 template<
typename TreeType>
655 void MultiResGrid<TreeType>::
656 topDownRestrict(
bool useInjection)
659 for (
size_t n=1;
n<mTrees.size(); ++
n) {
660 const TreeType &fineTree = *mTrees[
n-1];
661 mTrees[
n] = TreePtr(
new TreeType( fineTree.background() ) );
662 TreeType &coarseTree = *mTrees[
n];
664 for (ValueOnCIter it = fineTree.cbeginValueOn(); it; ++it) {
665 const Coord ijk = it.getCoord();
666 if ( (ijk[0] & 1) || (ijk[1] & 1) || (ijk[2] & 1) )
continue;
667 coarseTree.setValue( ijk >> 1, *it );
670 MaskOp tmp(fineTree, coarseTree, 128);
671 this->restrictActiveVoxels(
n, 64);
680 template<
typename TreeType>
684 using PoolType = tbb::enumerable_thread_specific<TreeType>;
687 using VoxelIterT =
typename ManagerT::LeafNodeType::ValueOnCIter;
689 MaskOp(
const TreeType& fineTree, TreeType& coarseTree,
size_t grainSize = 1)
690 : mPool(new
PoolType( coarseTree ) )
692 assert( coarseTree.empty() );
705 using IterT =
typename PoolType::const_iterator;
706 for (IterT it=mPool->begin(); it!=mPool->end(); ++it) coarseTree.topologyUnion( *it );
711 Accessor coarseAcc( mPool->local() );
712 for (
typename RangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
713 for (
VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
714 Coord ijk = voxelIter.getCoord();
715 if ( (ijk[2] & 1) || (ijk[1] & 1) || (ijk[0] & 1) )
continue;
723 template<
typename TreeType>
724 template<Index Order>
728 using PoolType = tbb::enumerable_thread_specific<MaskT>;
729 using PoolIterT =
typename PoolType::iterator;
732 using Range1 =
typename Manager1::LeafRange;
733 using Range2 =
typename Manager2::LeafRange;
738 size_t grainSize = 1)
741 , mTree0( &*(parent.mTrees[
size_t(floorf(level))]) )
742 , mTree1( &*(parent.mTrees[
size_t(ceilf(level))]) )
744 assert( midTree.empty() );
745 assert( mTree0 != mTree1 );
748 MaskT examplar(
false );
749 mPool =
new PoolType( examplar );
757 tbb::parallel_for(tbb::blocked_range<PoolIterT>(mPool->begin(),mPool->end(),1), *
this);
760 for (PoolIterT it=mPool->begin(); it!=mPool->end(); ++it) midTree.topologyUnion( *it );
764 Manager2 manager( midTree );
768 void operator()(
const Range1&
range)
const
770 using VoxelIter =
typename Manager1::LeafNodeType::ValueOnCIter;
781 for (
typename Range1::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
782 for (VoxelIter voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
783 Coord ijk = voxelIter.getCoord();
785 const auto value0 = ijk[0] *
scale;
786 const auto value1 = ijk[1] *
scale;
787 const auto value2 = ijk[2] *
scale;
793 acc.setValueOn( ijk );
797 void operator()(
const tbb::blocked_range<PoolIterT>& range)
const
799 for (PoolIterT it=range.begin(); it!=range.end(); ++it) {
803 void operator()(
const Range2 &
r)
const
805 using VoxelIter =
typename TreeType::LeafNodeType::ValueOnIter;
821 ConstAccessor acc0( *mTree0 ), acc1( *mTree1 );
822 for (
typename Range2::Iterator leafIter = r.begin(); leafIter; ++leafIter) {
823 for (VoxelIter voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
824 const Vec3R xyz =
Vec3R( voxelIter.getCoord().data() );
828 const auto value0 =
a*
v0;
829 const auto value1 = b*
v1;
831 voxelIter.setValue(
ValueType(value0 + value1) );
837 const TreeType *mTree0, *mTree1;
841 template<
typename TreeType>
842 template<
typename OperatorType>
843 struct MultiResGrid<TreeType>::CookOp
845 using ManagerT = tree::LeafManager<TreeType>;
846 using RangeT =
typename ManagerT::LeafRange;
848 CookOp(
const TreeType& srcTree, TreeType& dstTree,
size_t grainSize): acc(srcTree)
850 ManagerT leafs(dstTree);
853 CookOp(
const CookOp &other): acc(other.acc.tree()) {}
855 void operator()(
const RangeT& range)
const
857 for (
auto leafIt = range.begin(); leafIt; ++leafIt) {
858 auto& phi = leafIt.buffer(0);
859 for (
auto voxelIt = leafIt->beginValueOn(); voxelIt; ++voxelIt) {
860 phi.setValue(voxelIt.pos(), OperatorType::run(voxelIt.getCoord(), acc));
865 const ConstAccessor acc;
869 template<
typename TreeType>
881 v += 4*(acc.
getValue(ijk.offsetBy(-1, 0, 0)) + acc.
getValue(ijk.offsetBy( 1, 0, 0)) +
882 acc.
getValue(ijk.offsetBy( 0,-1, 0)) + acc.
getValue(ijk.offsetBy( 0, 1, 0)) +
883 acc.
getValue(ijk.offsetBy( 0, 0,-1)) + acc.
getValue(ijk.offsetBy( 0, 0, 1)));
885 v += 2*(acc.
getValue(ijk.offsetBy(-1,-1, 0)) + acc.
getValue(ijk.offsetBy(-1, 1, 0)) +
886 acc.
getValue(ijk.offsetBy( 1,-1, 0)) + acc.
getValue(ijk.offsetBy( 1, 1, 0)) +
887 acc.
getValue(ijk.offsetBy(-1, 0,-1)) + acc.
getValue(ijk.offsetBy(-1, 0, 1)) +
888 acc.
getValue(ijk.offsetBy( 1, 0,-1)) + acc.
getValue(ijk.offsetBy( 1, 0, 1)) +
889 acc.
getValue(ijk.offsetBy( 0,-1,-1)) + acc.
getValue(ijk.offsetBy( 0,-1, 1)) +
890 acc.
getValue(ijk.offsetBy( 0, 1,-1)) + acc.
getValue(ijk.offsetBy( 0, 1, 1)));
892 for (
int i=-1; i<=1; i+=2) {
893 for (
int j=-1;
j<=1;
j+=2) {
894 for (
int k=-1; k<=1; k+=2) v += acc.
getValue(ijk.offsetBy(i,
j,k));
902 template<
typename TreeType>
910 switch ( (ijk[0] & 1) | ((ijk[1] & 1) << 1) | ((ijk[2] & 1) << 2) ) {
915 acc.
getValue(ijk.offsetBy( 1,0,0)>>1));
918 acc.
getValue(ijk.offsetBy(0, 1,0)>>1));
921 acc.
getValue(ijk.offsetBy(-1, 1,0)>>1) +
922 acc.
getValue(ijk.offsetBy( 1,-1,0)>>1) +
923 acc.
getValue(ijk.offsetBy( 1, 1,0)>>1));
926 acc.
getValue(ijk.offsetBy(0,0, 1)>>1));
929 acc.
getValue(ijk.offsetBy(-1,0, 1)>>1) +
930 acc.
getValue(ijk.offsetBy( 1,0,-1)>>1) +
931 acc.
getValue(ijk.offsetBy( 1,0, 1)>>1));
934 acc.
getValue(ijk.offsetBy(0,-1, 1)>>1) +
935 acc.
getValue(ijk.offsetBy(0, 1,-1)>>1) +
936 acc.
getValue(ijk.offsetBy(0, 1, 1)>>1));
940 for (
int i=-1; i<=1; i+=2) {
941 for (
int j=-1;
j<=1;
j+=2) {
942 for (
int k=-1; k<=1; k+=2) v += acc.
getValue(ijk.offsetBy(i,
j,k)>>1);
955 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
957 #ifdef OPENVDB_INSTANTIATE_MULTIRESGRID
964 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
971 #endif // OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
void parallel_for(int64_t start, int64_t end, std::function< void(int64_t index)> &&task, parallel_options opt=parallel_options(0, Split_Y, 1))
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
Type Pow(Type x, int n)
Return xn.
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
SharedPtr< const Grid > ConstPtr
IMATH_HOSTDEVICE constexpr int floor(T x) IMATH_NOEXCEPT
static const char *const META_GRID_NAME
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
GLsizei const GLchar *const * string
Type FractionalPart(Type x)
Return the fractional part of x.
SharedPtr< GridCPtrVec > GridCPtrVecPtr
static std::string gridClassToString(GridClass)
Return the metadata string value for the given class of volumetric data.
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
GLboolean GLboolean GLboolean GLboolean a
#define OPENVDB_USE_VERSION_NAMESPACE
**But if you need a or simply need to know when the task has note that the like this
The Value Accessor Implementation and API methods. The majoirty of the API matches the API of a compa...
static const char *const META_GRID_CLASS
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
std::vector< GridBase::Ptr > GridPtrVec
TypedMetadata< std::string > StringMetadata
std::shared_ptr< T > SharedPtr
void setName(const std::string &)
Specify a name for this grid.
GA_API const UT_StringHolder scale
static GridClass stringToGridClass(const std::string &)
Return the class of volumetric data specified by the given string.
#define OPENVDB_INSTANTIATE_CLASS
static Ptr create()
Return a new grid with background value zero.
void setValueOn(const Coord &xyz, const ValueType &value)
Set a particular value at the given coordinate and mark the coordinate as active. ...
float Round(float x)
Return x rounded to the nearest integer.
PXL_API const char * getName(const ColorSpace *space)
Return the name of the color space.
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Defined various multi-threaded utility functions for trees.
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
GridClass getGridClass() const
Return the class of volumetric data (level set, fog volume, etc.) that is stored in this grid...
GLuint const GLchar * name
TypedMetadata< int64_t > Int64Metadata
GLboolean GLboolean GLboolean b
GA_API const UT_StringHolder transform
Container class that associates a tree with a transform and metadata.
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
SharedPtr< GridPtrVec > GridPtrVecPtr
IMATH_HOSTDEVICE constexpr int ceil(T x) IMATH_NOEXCEPT
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...
Implementation of morphological dilation and erosion.
TypedMetadata< float > FloatMetadata
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
void setTransform(math::Transform::Ptr)
Associate the given transform with this grid, in place of its existing transform. ...
std::vector< GridBase::ConstPtr > GridCPtrVec
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
#define OPENVDB_THROW(exception, message)
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.