25 #ifndef OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
26 #define OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
45 #include <tbb/blocked_range.h>
46 #include <tbb/enumerable_thread_specific.h>
47 #include <tbb/parallel_for.h>
60 template<
typename TreeType>
182 template<Index Order>
213 static Vec3R xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level);
214 static Vec3R xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level);
215 static Vec3R xyz(
const Vec3R& in_xyz,
double in_level,
double out_level);
232 template<Index Order>
234 template<Index Order>
244 template<Index Order>
254 template<Index Order>
290 void print(std::ostream& = std::cout,
int verboseLevel = 1)
const;
332 void topDownRestrict(
bool useInjection);
334 inline void initMeta();
347 template<Index Order>
351 template<
typename OpType>
struct CookOp;
354 std::vector<TreePtr> mTrees;
359 template<
typename TreeType>
363 , mTransform(math::
Transform::createLinearTransform( voxelSize ))
366 for (
size_t i=0; i<
levels; ++i) mTrees[i] =
TreePtr(
new TreeType(background));
369 template<
typename TreeType>
377 mTrees[0].reset(
new TreeType( grid.
tree() ) );
378 mTrees[0]->voxelizeActiveTiles();
379 this->topDownRestrict(useInjection);
382 template<
typename TreeType>
390 mTrees[0] = grid->treePtr();
391 mTrees[0]->voxelizeActiveTiles();
393 this->topDownRestrict(useInjection);
396 template<
typename TreeType>
401 return *mTrees[
level];
404 template<
typename TreeType>
409 return *mTrees[
level];
412 template<
typename TreeType>
417 return mTrees[
level];
420 template<
typename TreeType>
425 return mTrees[
level];
428 template<
typename TreeType>
434 if (level>0) xform->preScale(
Real(1 << level) );
438 std::stringstream ss;
444 template<
typename TreeType>
451 template<
typename TreeType>
452 template<Index Order>
464 std::stringstream ss;
468 if (
size_t(floorf(level)) == size_t(ceilf(level)) ) {
469 grid->
setTree( this->constTree(
size_t(floorf(level))).
copy() );
471 FractionOp<Order> tmp(*
this, grid->
tree(),
level, grainSize);
481 template<
typename TreeType>
490 template<
typename TreeType>
499 template<
typename TreeType>
501 xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
503 return Vec3R( in_ijk.data() ) *
Real(1 << in_level) /
Real(1 << out_level);
506 template<
typename TreeType>
508 xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level)
510 return in_xyz *
Real(1 << in_level) /
Real(1 << out_level);
513 template<
typename TreeType>
515 xyz(
const Vec3R& in_xyz,
double in_level,
double out_level)
517 return in_xyz *
math::Pow(2.0, in_level - out_level);
521 template<
typename TreeType>
522 template<Index Order>
524 sampleValue(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
const
532 template<
typename TreeType>
533 template<Index Order>
543 template<
typename TreeType>
544 template<Index Order>
548 OPENVDB_ASSERT( level >= 0.0 && level <=
double(mTrees.size()-1) );
549 const size_t level0 = size_t(
floor(level)), level1 = size_t(
ceil(level));
550 const ValueType v0 = this->
template sampleValue<Order>( ijk, 0, level0 );
551 if ( level0 == level1 )
return v0;
553 const ValueType v1 = this->
template sampleValue<Order>( ijk, 0, level1 );
560 template<
typename TreeType>
561 template<Index Order>
565 OPENVDB_ASSERT( level >= 0.0 && level <=
double(mTrees.size()-1) );
566 const size_t level0 = size_t(
floor(level)), level1 = size_t(
ceil(level));
567 const ValueType v0 = this->
template sampleValue<Order>( xyz, 0, level0 );
568 if ( level0 == level1 )
return v0;
570 const ValueType v1 = this->
template sampleValue<Order>( xyz, 0, level1 );
577 template<
typename TreeType>
583 return ProlongateOp::run(ijk, acc);
586 template<
typename TreeType>
591 TreeType &fineTree = *mTrees[ destlevel ];
592 const TreeType &coarseTree = *mTrees[ destlevel+1 ];
593 CookOp<ProlongateOp> tmp( coarseTree, fineTree, grainSize );
596 template<
typename TreeType>
601 const TreeType &fineTree = *mTrees[ destlevel-1 ];
602 if ( useInjection )
return fineTree.getValue(ijk<<1);
604 return RestrictOp::run( ijk, acc);
607 template<
typename TreeType>
612 const TreeType &fineTree = *mTrees[ destlevel-1 ];
613 TreeType &coarseTree = *mTrees[ destlevel ];
614 CookOp<RestrictOp> tmp( fineTree, coarseTree, grainSize );
617 template<
typename TreeType>
619 print(std::ostream& os,
int verboseLevel)
const
621 os <<
"MultiResGrid with " << mTrees.size() <<
" levels\n";
622 for (
size_t i=0; i<mTrees.size(); ++i) {
623 os <<
"Level " << i <<
": ";
624 mTrees[i]->print(os, verboseLevel);
628 os <<
"Additional metadata:" << std::endl;
630 os <<
" " << it->first;
632 const std::string
value = it->second->str();
633 if (!value.empty()) os <<
": " << value;
639 os <<
"Transform:" << std::endl;
644 template<
typename TreeType>
648 const size_t levels = this->numLevels();
650 OPENVDB_THROW(ValueError,
"MultiResGrid: at least two levels are required");
652 this->insertMeta(
"MultiResGrid_Levels",
Int64Metadata( levels ) );
655 template<
typename TreeType>
656 void MultiResGrid<TreeType>::
657 topDownRestrict(
bool useInjection)
660 for (
size_t n=1;
n<mTrees.size(); ++
n) {
661 const TreeType &fineTree = *mTrees[
n-1];
662 mTrees[
n] = TreePtr(
new TreeType( fineTree.background() ) );
663 TreeType &coarseTree = *mTrees[
n];
665 for (ValueOnCIter it = fineTree.cbeginValueOn(); it; ++it) {
666 const Coord ijk = it.getCoord();
667 if ( (ijk[0] & 1) || (ijk[1] & 1) || (ijk[2] & 1) )
continue;
668 coarseTree.setValue( ijk >> 1, *it );
671 MaskOp tmp(fineTree, coarseTree, 128);
672 this->restrictActiveVoxels(
n, 64);
681 template<
typename TreeType>
685 using PoolType = tbb::enumerable_thread_specific<TreeType>;
688 using VoxelIterT =
typename ManagerT::LeafNodeType::ValueOnCIter;
690 MaskOp(
const TreeType& fineTree, TreeType& coarseTree,
size_t grainSize = 1)
691 : mPool(new
PoolType( coarseTree ) )
706 using IterT =
typename PoolType::const_iterator;
707 for (IterT it=mPool->begin(); it!=mPool->end(); ++it) coarseTree.topologyUnion( *it );
712 Accessor coarseAcc( mPool->local() );
713 for (
typename RangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
714 for (
VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
715 Coord ijk = voxelIter.getCoord();
716 if ( (ijk[2] & 1) || (ijk[1] & 1) || (ijk[0] & 1) )
continue;
724 template<
typename TreeType>
725 template<Index Order>
729 using PoolType = tbb::enumerable_thread_specific<MaskT>;
730 using PoolIterT =
typename PoolType::iterator;
733 using Range1 =
typename Manager1::LeafRange;
734 using Range2 =
typename Manager2::LeafRange;
739 size_t grainSize = 1)
742 , mTree0( &*(parent.mTrees[
size_t(floorf(level))]) )
743 , mTree1( &*(parent.mTrees[
size_t(ceilf(level))]) )
749 MaskT examplar(
false );
750 mPool =
new PoolType( examplar );
758 tbb::parallel_for(tbb::blocked_range<PoolIterT>(mPool->begin(),mPool->end(),1), *
this);
761 for (PoolIterT it=mPool->begin(); it!=mPool->end(); ++it) midTree.topologyUnion( *it );
765 Manager2 manager( midTree );
769 void operator()(
const Range1&
range)
const
771 using VoxelIter =
typename Manager1::LeafNodeType::ValueOnCIter;
782 for (
typename Range1::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
783 for (VoxelIter voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
784 Coord ijk = voxelIter.getCoord();
786 const auto value0 = ijk[0] *
scale;
787 const auto value1 = ijk[1] *
scale;
788 const auto value2 = ijk[2] *
scale;
794 acc.setValueOn( ijk );
798 void operator()(
const tbb::blocked_range<PoolIterT>& range)
const
800 for (PoolIterT it=range.begin(); it!=range.end(); ++it) {
804 void operator()(
const Range2 &
r)
const
806 using VoxelIter =
typename TreeType::LeafNodeType::ValueOnIter;
822 ConstAccessor acc0( *mTree0 ), acc1( *mTree1 );
823 for (
typename Range2::Iterator leafIter = r.begin(); leafIter; ++leafIter) {
824 for (VoxelIter voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
825 const Vec3R xyz =
Vec3R( voxelIter.getCoord().data() );
829 const auto value0 =
a*
v0;
830 const auto value1 = b*
v1;
832 voxelIter.setValue(
ValueType(value0 + value1) );
838 const TreeType *mTree0, *mTree1;
842 template<
typename TreeType>
843 template<
typename OperatorType>
844 struct MultiResGrid<TreeType>::CookOp
846 using ManagerT = tree::LeafManager<TreeType>;
847 using RangeT =
typename ManagerT::LeafRange;
849 CookOp(
const TreeType& srcTree, TreeType& dstTree,
size_t grainSize): acc(srcTree)
851 ManagerT leafs(dstTree);
854 CookOp(
const CookOp &other): acc(other.acc.tree()) {}
856 void operator()(
const RangeT& range)
const
858 for (
auto leafIt = range.begin(); leafIt; ++leafIt) {
859 auto& phi = leafIt.buffer(0);
860 for (
auto voxelIt = leafIt->beginValueOn(); voxelIt; ++voxelIt) {
861 phi.setValue(voxelIt.pos(), OperatorType::run(voxelIt.getCoord(), acc));
866 const ConstAccessor acc;
870 template<
typename TreeType>
882 v += 4*(acc.
getValue(ijk.offsetBy(-1, 0, 0)) + acc.
getValue(ijk.offsetBy( 1, 0, 0)) +
883 acc.
getValue(ijk.offsetBy( 0,-1, 0)) + acc.
getValue(ijk.offsetBy( 0, 1, 0)) +
884 acc.
getValue(ijk.offsetBy( 0, 0,-1)) + acc.
getValue(ijk.offsetBy( 0, 0, 1)));
886 v += 2*(acc.
getValue(ijk.offsetBy(-1,-1, 0)) + acc.
getValue(ijk.offsetBy(-1, 1, 0)) +
887 acc.
getValue(ijk.offsetBy( 1,-1, 0)) + acc.
getValue(ijk.offsetBy( 1, 1, 0)) +
888 acc.
getValue(ijk.offsetBy(-1, 0,-1)) + acc.
getValue(ijk.offsetBy(-1, 0, 1)) +
889 acc.
getValue(ijk.offsetBy( 1, 0,-1)) + acc.
getValue(ijk.offsetBy( 1, 0, 1)) +
890 acc.
getValue(ijk.offsetBy( 0,-1,-1)) + acc.
getValue(ijk.offsetBy( 0,-1, 1)) +
891 acc.
getValue(ijk.offsetBy( 0, 1,-1)) + acc.
getValue(ijk.offsetBy( 0, 1, 1)));
893 for (
int i=-1; i<=1; i+=2) {
894 for (
int j=-1;
j<=1;
j+=2) {
895 for (
int k=-1; k<=1; k+=2) v += acc.
getValue(ijk.offsetBy(i,
j,k));
903 template<
typename TreeType>
911 switch ( (ijk[0] & 1) | ((ijk[1] & 1) << 1) | ((ijk[2] & 1) << 2) ) {
916 acc.
getValue(ijk.offsetBy( 1,0,0)>>1));
919 acc.
getValue(ijk.offsetBy(0, 1,0)>>1));
922 acc.
getValue(ijk.offsetBy(-1, 1,0)>>1) +
923 acc.
getValue(ijk.offsetBy( 1,-1,0)>>1) +
924 acc.
getValue(ijk.offsetBy( 1, 1,0)>>1));
927 acc.
getValue(ijk.offsetBy(0,0, 1)>>1));
930 acc.
getValue(ijk.offsetBy(-1,0, 1)>>1) +
931 acc.
getValue(ijk.offsetBy( 1,0,-1)>>1) +
932 acc.
getValue(ijk.offsetBy( 1,0, 1)>>1));
935 acc.
getValue(ijk.offsetBy(0,-1, 1)>>1) +
936 acc.
getValue(ijk.offsetBy(0, 1,-1)>>1) +
937 acc.
getValue(ijk.offsetBy(0, 1, 1)>>1));
941 for (
int i=-1; i<=1; i+=2) {
942 for (
int j=-1;
j<=1;
j+=2) {
943 for (
int k=-1; k<=1; k+=2) v += acc.
getValue(ijk.offsetBy(i,
j,k)>>1);
956 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
958 #ifdef OPENVDB_INSTANTIATE_MULTIRESGRID
965 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
972 #endif // OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
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)
Type FractionalPart(Type x)
Return the fractional part of x.
GLsizei const GLfloat * value
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
#define OPENVDB_ASSERT(X)
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...
OIIO_UTIL_API void parallel_for(int32_t begin, int32_t end, function_view< void(int32_t)> task, paropt opt=0)
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.