25 #ifndef OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
26 #define OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
43 #include <tbb/blocked_range.h>
44 #include <tbb/enumerable_thread_specific.h>
45 #include <tbb/parallel_for.h>
58 template<
typename TreeType>
180 template<Index Order>
211 static Vec3R xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level);
212 static Vec3R xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level);
213 static Vec3R xyz(
const Vec3R& in_xyz,
double in_level,
double out_level);
230 template<Index Order>
232 template<Index Order>
242 template<Index Order>
252 template<Index Order>
288 void print(std::ostream& = std::cout,
int verboseLevel = 1)
const;
330 void topDownRestrict(
bool useInjection);
332 inline void initMeta();
345 template<Index Order>
349 template<
typename OpType>
struct CookOp;
352 std::vector<TreePtr> mTrees;
357 template<
typename TreeType>
361 , mTransform(math::
Transform::createLinearTransform( voxelSize ))
364 for (
size_t i=0; i<
levels; ++i) mTrees[i] =
TreePtr(
new TreeType(background));
367 template<
typename TreeType>
375 mTrees[0].reset(
new TreeType( grid.
tree() ) );
376 mTrees[0]->voxelizeActiveTiles();
377 this->topDownRestrict(useInjection);
380 template<
typename TreeType>
388 mTrees[0] = grid->treePtr();
389 mTrees[0]->voxelizeActiveTiles();
391 this->topDownRestrict(useInjection);
394 template<
typename TreeType>
398 assert( level < mTrees.size() );
399 return *mTrees[
level];
402 template<
typename TreeType>
406 assert( level < mTrees.size() );
407 return *mTrees[
level];
410 template<
typename TreeType>
414 assert( level < mTrees.size() );
415 return mTrees[
level];
418 template<
typename TreeType>
422 assert( level < mTrees.size() );
423 return mTrees[
level];
426 template<
typename TreeType>
432 if (level>0) xform->preScale(
Real(1 << level) );
436 std::stringstream ss;
437 ss << this->getName() <<
"_level_" <<
level;
442 template<
typename TreeType>
449 template<
typename TreeType>
450 template<Index Order>
454 assert( level >= 0.0
f && level <=
float(mTrees.size()-1) );
462 std::stringstream ss;
463 ss << this->getName() <<
"_level_" <<
level;
466 if (
size_t(floorf(level)) == size_t(ceilf(level)) ) {
467 grid->
setTree( this->constTree(
size_t(floorf(level))).
copy() );
469 FractionOp<Order> tmp(*
this, grid->
tree(),
level, grainSize);
479 template<
typename TreeType>
488 template<
typename TreeType>
497 template<
typename TreeType>
499 xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
501 return Vec3R( in_ijk.data() ) *
Real(1 << in_level) /
Real(1 << out_level);
504 template<
typename TreeType>
506 xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level)
508 return in_xyz *
Real(1 << in_level) /
Real(1 << out_level);
511 template<
typename TreeType>
513 xyz(
const Vec3R& in_xyz,
double in_level,
double out_level)
515 return in_xyz *
math::Pow(2.0, in_level - out_level);
519 template<
typename TreeType>
520 template<Index Order>
522 sampleValue(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
const
524 assert( in_level >= 0 && in_level < mTrees.size() );
525 assert( out_level >= 0 && out_level < mTrees.size() );
530 template<
typename TreeType>
531 template<Index Order>
535 assert( in_level >= 0 && in_level < mTrees.size() );
536 assert( out_level >= 0 && out_level < mTrees.size() );
541 template<
typename TreeType>
542 template<Index Order>
546 assert( level >= 0.0 && level <=
double(mTrees.size()-1) );
547 const size_t level0 = size_t(
floor(level)), level1 = size_t(
ceil(level));
548 const ValueType v0 = this->
template sampleValue<Order>( ijk, 0, level0 );
549 if ( level0 == level1 )
return v0;
550 assert( level1 - level0 == 1 );
551 const ValueType v1 = this->
template sampleValue<Order>( ijk, 0, level1 );
558 template<
typename TreeType>
559 template<Index Order>
563 assert( level >= 0.0 && level <=
double(mTrees.size()-1) );
564 const size_t level0 = size_t(
floor(level)), level1 = size_t(
ceil(level));
565 const ValueType v0 = this->
template sampleValue<Order>( xyz, 0, level0 );
566 if ( level0 == level1 )
return v0;
567 assert( level1 - level0 == 1 );
568 const ValueType v1 = this->
template sampleValue<Order>( xyz, 0, level1 );
575 template<
typename TreeType>
579 assert( level+1 < mTrees.size() );
581 return ProlongateOp::run(ijk, acc);
584 template<
typename TreeType>
588 assert( destlevel < mTrees.size()-1 );
589 TreeType &fineTree = *mTrees[ destlevel ];
590 const TreeType &coarseTree = *mTrees[ destlevel+1 ];
591 CookOp<ProlongateOp> tmp( coarseTree, fineTree, grainSize );
594 template<
typename TreeType>
598 assert( destlevel > 0 && destlevel < mTrees.size() );
599 const TreeType &fineTree = *mTrees[ destlevel-1 ];
600 if ( useInjection )
return fineTree.getValue(ijk<<1);
602 return RestrictOp::run( ijk, acc);
605 template<
typename TreeType>
609 assert( destlevel > 0 && destlevel < mTrees.size() );
610 const TreeType &fineTree = *mTrees[ destlevel-1 ];
611 TreeType &coarseTree = *mTrees[ destlevel ];
612 CookOp<RestrictOp> tmp( fineTree, coarseTree, grainSize );
615 template<
typename TreeType>
617 print(std::ostream& os,
int verboseLevel)
const
619 os <<
"MultiResGrid with " << mTrees.size() <<
" levels\n";
620 for (
size_t i=0; i<mTrees.size(); ++i) {
621 os <<
"Level " << i <<
": ";
622 mTrees[i]->print(os, verboseLevel);
626 os <<
"Additional metadata:" << std::endl;
628 os <<
" " << it->first;
631 if (!value.empty()) os <<
": " << value;
637 os <<
"Transform:" << std::endl;
642 template<
typename TreeType>
646 const size_t levels = this->numLevels();
648 OPENVDB_THROW(ValueError,
"MultiResGrid: at least two levels are required");
650 this->insertMeta(
"MultiResGrid_Levels",
Int64Metadata( levels ) );
653 template<
typename TreeType>
654 void MultiResGrid<TreeType>::
655 topDownRestrict(
bool useInjection)
658 for (
size_t n=1;
n<mTrees.size(); ++
n) {
659 const TreeType &fineTree = *mTrees[
n-1];
660 mTrees[
n] = TreePtr(
new TreeType( fineTree.background() ) );
661 TreeType &coarseTree = *mTrees[
n];
663 for (ValueOnCIter it = fineTree.cbeginValueOn(); it; ++it) {
664 const Coord ijk = it.getCoord();
665 if ( (ijk[0] & 1) || (ijk[1] & 1) || (ijk[2] & 1) )
continue;
666 coarseTree.setValue( ijk >> 1, *it );
669 MaskOp tmp(fineTree, coarseTree, 128);
670 this->restrictActiveVoxels(
n, 64);
679 template<
typename TreeType>
683 using PoolType = tbb::enumerable_thread_specific<TreeType>;
686 using VoxelIterT =
typename ManagerT::LeafNodeType::ValueOnCIter;
688 MaskOp(
const TreeType& fineTree, TreeType& coarseTree,
size_t grainSize = 1)
689 : mPool(new
PoolType( coarseTree ) )
691 assert( coarseTree.empty() );
704 using IterT =
typename PoolType::const_iterator;
705 for (IterT it=mPool->begin(); it!=mPool->end(); ++it) coarseTree.topologyUnion( *it );
710 Accessor coarseAcc( mPool->local() );
711 for (
typename RangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
712 for (
VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
713 Coord ijk = voxelIter.getCoord();
714 if ( (ijk[2] & 1) || (ijk[1] & 1) || (ijk[0] & 1) )
continue;
722 template<
typename TreeType>
723 template<Index Order>
727 using PoolType = tbb::enumerable_thread_specific<MaskT>;
728 using PoolIterT =
typename PoolType::iterator;
731 using Range1 =
typename Manager1::LeafRange;
732 using Range2 =
typename Manager2::LeafRange;
737 size_t grainSize = 1)
740 , mTree0( &*(parent.mTrees[
size_t(floorf(level))]) )
741 , mTree1( &*(parent.mTrees[
size_t(ceilf(level))]) )
743 assert( midTree.empty() );
744 assert( mTree0 != mTree1 );
747 MaskT examplar(
false );
748 mPool =
new PoolType( examplar );
756 tbb::parallel_for(tbb::blocked_range<PoolIterT>(mPool->begin(),mPool->end(),1), *
this);
759 for (PoolIterT it=mPool->begin(); it!=mPool->end(); ++it) midTree.topologyUnion( *it );
763 Manager2 manager( midTree );
767 void operator()(
const Range1&
range)
const
769 using VoxelIter =
typename Manager1::LeafNodeType::ValueOnCIter;
780 for (
typename Range1::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
781 for (VoxelIter voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
782 Coord ijk = voxelIter.getCoord();
784 const auto value0 = ijk[0] *
scale;
785 const auto value1 = ijk[1] *
scale;
786 const auto value2 = ijk[2] *
scale;
792 acc.setValueOn( ijk );
796 void operator()(
const tbb::blocked_range<PoolIterT>& range)
const
798 for (PoolIterT it=range.begin(); it!=range.end(); ++it) {
802 void operator()(
const Range2 &
r)
const
804 using VoxelIter =
typename TreeType::LeafNodeType::ValueOnIter;
820 ConstAccessor acc0( *mTree0 ), acc1( *mTree1 );
821 for (
typename Range2::Iterator leafIter = r.begin(); leafIter; ++leafIter) {
822 for (VoxelIter voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
823 const Vec3R xyz =
Vec3R( voxelIter.getCoord().data() );
827 const auto value0 =
a*
v0;
828 const auto value1 = b*
v1;
830 voxelIter.setValue( ValueType(value0 + value1) );
836 const TreeType *mTree0, *mTree1;
840 template<
typename TreeType>
841 template<
typename OperatorType>
842 struct MultiResGrid<TreeType>::CookOp
844 using ManagerT = tree::LeafManager<TreeType>;
845 using RangeT =
typename ManagerT::LeafRange;
847 CookOp(
const TreeType& srcTree, TreeType& dstTree,
size_t grainSize): acc(srcTree)
849 ManagerT leafs(dstTree);
852 CookOp(
const CookOp &other): acc(other.acc.tree()) {}
854 void operator()(
const RangeT& range)
const
856 for (
auto leafIt = range.begin(); leafIt; ++leafIt) {
857 auto& phi = leafIt.buffer(0);
858 for (
auto voxelIt = leafIt->beginValueOn(); voxelIt; ++voxelIt) {
859 phi.setValue(voxelIt.pos(), OperatorType::run(voxelIt.getCoord(), acc));
864 const ConstAccessor acc;
868 template<
typename TreeType>
880 v += 4*(acc.
getValue(ijk.offsetBy(-1, 0, 0)) + acc.
getValue(ijk.offsetBy( 1, 0, 0)) +
881 acc.
getValue(ijk.offsetBy( 0,-1, 0)) + acc.
getValue(ijk.offsetBy( 0, 1, 0)) +
882 acc.
getValue(ijk.offsetBy( 0, 0,-1)) + acc.
getValue(ijk.offsetBy( 0, 0, 1)));
884 v += 2*(acc.
getValue(ijk.offsetBy(-1,-1, 0)) + acc.
getValue(ijk.offsetBy(-1, 1, 0)) +
885 acc.
getValue(ijk.offsetBy( 1,-1, 0)) + acc.
getValue(ijk.offsetBy( 1, 1, 0)) +
886 acc.
getValue(ijk.offsetBy(-1, 0,-1)) + acc.
getValue(ijk.offsetBy(-1, 0, 1)) +
887 acc.
getValue(ijk.offsetBy( 1, 0,-1)) + acc.
getValue(ijk.offsetBy( 1, 0, 1)) +
888 acc.
getValue(ijk.offsetBy( 0,-1,-1)) + acc.
getValue(ijk.offsetBy( 0,-1, 1)) +
889 acc.
getValue(ijk.offsetBy( 0, 1,-1)) + acc.
getValue(ijk.offsetBy( 0, 1, 1)));
891 for (
int i=-1; i<=1; i+=2) {
892 for (
int j=-1; j<=1; j+=2) {
893 for (
int k=-1; k<=1; k+=2) v += acc.
getValue(ijk.offsetBy(i,j,k));
901 template<
typename TreeType>
909 switch ( (ijk[0] & 1) | ((ijk[1] & 1) << 1) | ((ijk[2] & 1) << 2) ) {
914 acc.
getValue(ijk.offsetBy( 1,0,0)>>1));
917 acc.
getValue(ijk.offsetBy(0, 1,0)>>1));
920 acc.
getValue(ijk.offsetBy(-1, 1,0)>>1) +
921 acc.
getValue(ijk.offsetBy( 1,-1,0)>>1) +
922 acc.
getValue(ijk.offsetBy( 1, 1,0)>>1));
925 acc.
getValue(ijk.offsetBy(0,0, 1)>>1));
928 acc.
getValue(ijk.offsetBy(-1,0, 1)>>1) +
929 acc.
getValue(ijk.offsetBy( 1,0,-1)>>1) +
930 acc.
getValue(ijk.offsetBy( 1,0, 1)>>1));
933 acc.
getValue(ijk.offsetBy(0,-1, 1)>>1) +
934 acc.
getValue(ijk.offsetBy(0, 1,-1)>>1) +
935 acc.
getValue(ijk.offsetBy(0, 1, 1)>>1));
939 for (
int i=-1; i<=1; i+=2) {
940 for (
int j=-1; j<=1; j+=2) {
941 for (
int k=-1; k<=1; k+=2) v += acc.
getValue(ijk.offsetBy(i,j,k)>>1);
954 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
956 #ifdef OPENVDB_INSTANTIATE_MULTIRESGRID
963 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
970 #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))
GLboolean GLboolean GLboolean b
GLenum GLenum GLenum GLenum GLenum scale
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)
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.
#define OPENVDB_USE_VERSION_NAMESPACE
**But if you need a or simply need to know when the task has note that the like this
GLuint const GLchar * name
static const char *const META_GRID_CLASS
std::vector< GridBase::Ptr > GridPtrVec
TypedMetadata< std::string > StringMetadata
std::shared_ptr< T > SharedPtr
GLuint GLenum GLenum transform
void setName(const std::string &)
Specify a name for this grid.
static GridClass stringToGridClass(const std::string &)
Return the class of volumetric data specified by the given string.
#define OPENVDB_INSTANTIATE_CLASS
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
static Ptr create()
Return a new grid with background value zero.
float Round(float x)
Return x rounded to the nearest integer.
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
GLboolean GLboolean GLboolean GLboolean a
GLsizei const GLchar *const * string
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...
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
TypedMetadata< int64_t > Int64Metadata
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...
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Implementation of morphological dilation and erosion.
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
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
#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.