51 #ifndef OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED 52 #define OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED 54 #include <openvdb/Grid.h> 55 #include <openvdb/math/FiniteDifference.h> 56 #include <openvdb/math/Math.h> 57 #include <openvdb/math/Operators.h> 58 #include <openvdb/math/Stencils.h> 59 #include <openvdb/metadata/StringMetadata.h> 60 #include <openvdb/tools/Interpolation.h> 61 #include <openvdb/tools/Morphology.h> 62 #include <openvdb/tools/Prune.h> 63 #include <openvdb/tools/SignedFloodFill.h> 64 #include <openvdb/tools/ValueTransformer.h> 65 #include <openvdb/tree/LeafManager.h> 66 #include <openvdb/tree/NodeManager.h> 68 #include <tbb/enumerable_thread_specific.h> 69 #include <tbb/task_scheduler_init.h> 70 #include <tbb/tbb_thread.h> 72 #include <boost/type_traits/is_floating_point.hpp> 73 #include <boost/utility/enable_if.hpp> 85 template<
typename TreeType>
90 typedef boost::shared_ptr<MultiResGrid>
Ptr;
91 typedef boost::shared_ptr<const MultiResGrid>
ConstPtr;
108 MultiResGrid(
size_t levels, ValueType background,
double voxelSize = 1.0);
129 MultiResGrid(
size_t levels, GridPtr grid,
bool useInjection =
false);
149 TreeType& tree(
size_t level);
154 const TreeType& constTree(
size_t level)
const;
159 TreePtr treePtr(
size_t level);
164 ConstTreePtr constTreePtr(
size_t level)
const;
195 GridPtr grid(
size_t level);
200 ConstGridPtr grid(
size_t level)
const;
209 template<Index Order>
210 GridPtr
createGrid(
float level,
size_t grainSize = 1)
const;
238 static Vec3R xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level);
241 static Vec3R xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level);
242 static Vec3R xyz(
const Vec3R& in_xyz,
double in_level,
double out_level);
250 template<Index Order>
260 ValueType sampleValue(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
const;
261 template<Index Order>
262 ValueType sampleValue(
const Vec3R& in_ijk,
size_t in_level,
size_t out_level)
const;
271 template<Index Order>
272 ValueType sampleValue(
const Coord& ijk,
double level)
const;
281 template<Index Order>
282 ValueType sampleValue(
const Vec3R& xyz,
double level)
const;
292 ValueType prolongateVoxel(
const Coord& coords,
const size_t level)
const;
298 void prolongateActiveVoxels(
size_t destlevel,
size_t grainSize = 1);
306 ValueType restrictVoxel(Coord ijk,
const size_t level,
bool useInjection =
false)
const;
314 void restrictActiveVoxels(
size_t destlevel,
size_t grainSize = 1);
317 void print(std::ostream& = std::cout,
int verboseLevel = 1)
const;
359 void topDownRestrict(
bool useInjection);
361 inline void initMeta();
374 template<Index Order>
378 template<
typename OpType>
struct CookOp;
381 std::vector<TreePtr> mTrees;
386 template<
typename TreeType>
390 , mTransform(math::Transform::createLinearTransform( voxelSize ))
393 for (
size_t i=0; i<levels; ++i) mTrees[i] =
TreePtr(
new TreeType(background));
396 template<
typename TreeType>
404 mTrees[0].reset(
new TreeType( grid.
tree() ) );
405 mTrees[0]->voxelizeActiveTiles();
406 this->topDownRestrict(useInjection);
409 template<
typename TreeType>
417 mTrees[0] = grid->treePtr();
418 mTrees[0]->voxelizeActiveTiles();
420 this->topDownRestrict(useInjection);
423 template<
typename TreeType>
427 assert( level < mTrees.size() );
428 return *mTrees[level];
431 template<
typename TreeType>
435 assert( level < mTrees.size() );
436 return *mTrees[level];
439 template<
typename TreeType>
443 assert( level < mTrees.size() );
444 return mTrees[level];
447 template<
typename TreeType>
451 assert( level < mTrees.size() );
452 return mTrees[level];
455 template<
typename TreeType>
461 if (level>0) xform->preScale(
Real(1 << level) );
465 std::stringstream ss;
466 ss << this->
getName() <<
"_level_" << level;
471 template<
typename TreeType>
478 template<
typename TreeType>
479 template<Index Order>
483 assert( level >= 0.0f && level <=
float(mTrees.size()-1) );
487 xform->preScale(
math::Pow(2.0f, level) );
491 std::stringstream ss;
492 ss << this->
getName() <<
"_level_" << level;
495 if (
size_t(floorf(level)) == size_t(ceilf(level)) ) {
498 FractionOp<Order> tmp(*
this, grid->
tree(), level, grainSize);
508 template<
typename TreeType>
513 for (
size_t level=0; level<mTrees.size(); ++level) grids->push_back(this->grid(level));
517 template<
typename TreeType>
522 for (
size_t level=0; level<mTrees.size(); ++level) grids->push_back(this->grid(level));
526 template<
typename TreeType>
528 xyz(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
530 return Vec3R( in_ijk.data() ) *
Real(1 << in_level) /
Real(1 << out_level);
533 template<
typename TreeType>
535 xyz(
const Vec3R& in_xyz,
size_t in_level,
size_t out_level)
537 return in_xyz *
Real(1 << in_level) /
Real(1 << out_level);
540 template<
typename TreeType>
542 xyz(
const Vec3R& in_xyz,
double in_level,
double out_level)
544 return in_xyz *
math::Pow(2.0, in_level - out_level);
548 template<
typename TreeType>
549 template<Index Order>
551 sampleValue(
const Coord& in_ijk,
size_t in_level,
size_t out_level)
const 553 assert( in_level >= 0 && in_level < mTrees.size() );
554 assert( out_level >= 0 && out_level < mTrees.size() );
559 template<
typename TreeType>
560 template<Index Order>
564 assert( in_level >= 0 && in_level < mTrees.size() );
565 assert( out_level >= 0 && out_level < mTrees.size() );
570 template<
typename TreeType>
571 template<Index Order>
575 assert( level >= 0.0 && level <=
double(mTrees.size()-1) );
576 const size_t level0 = size_t(floor(level)), level1 = size_t(ceil(level));
577 const ValueType v0 = this->
template sampleValue<Order>( ijk, 0, level0 );
578 if ( level0 == level1 )
return v0;
579 assert( level1 - level0 == 1 );
580 const ValueType v1 = this->
template sampleValue<Order>( ijk, 0, level1 );
585 template<
typename TreeType>
586 template<Index Order>
590 assert( level >= 0.0 && level <=
double(mTrees.size()-1) );
591 const size_t level0 = size_t(floor(level)), level1 = size_t(ceil(level));
592 const ValueType v0 = this->
template sampleValue<Order>(
xyz, 0, level0 );
593 if ( level0 == level1 )
return v0;
594 assert( level1 - level0 == 1 );
595 const ValueType v1 = this->
template sampleValue<Order>(
xyz, 0, level1 );
600 template<
typename TreeType>
604 assert( level+1 < mTrees.size() );
609 template<
typename TreeType>
613 assert( destlevel < mTrees.size()-1 );
614 TreeType &fineTree = *mTrees[ destlevel ];
615 const TreeType &coarseTree = *mTrees[ destlevel+1 ];
616 CookOp<ProlongateOp> tmp( coarseTree, fineTree, grainSize );
619 template<
typename TreeType>
623 assert( destlevel > 0 && destlevel < mTrees.size() );
624 const TreeType &fineTree = *mTrees[ destlevel-1 ];
625 if ( useInjection )
return fineTree.getValue(ijk<<1);
630 template<
typename TreeType>
634 assert( destlevel > 0 && destlevel < mTrees.size() );
635 const TreeType &fineTree = *mTrees[ destlevel-1 ];
636 TreeType &coarseTree = *mTrees[ destlevel ];
637 CookOp<RestrictOp> tmp( fineTree, coarseTree, grainSize );
640 template<
typename TreeType>
642 print(std::ostream& os,
int verboseLevel)
const 644 os <<
"MultiResGrid with " << mTrees.size() <<
" levels\n";
645 for (
size_t i=0; i<mTrees.size(); ++i) {
646 os <<
"Level " << i <<
": ";
647 mTrees[i]->print(os, verboseLevel);
651 os <<
"Additional metadata:" << std::endl;
653 os <<
" " << it->first;
655 const std::string value = it->second->str();
656 if (!value.empty()) os <<
": " << value;
662 os <<
"Transform:" << std::endl;
667 template<
typename TreeType>
678 template<
typename TreeType>
683 for (
size_t n=1; n<mTrees.size(); ++n) {
684 const TreeType &fineTree = *mTrees[n-1];
685 mTrees[n] =
TreePtr(
new TreeType( fineTree.background() ) );
686 TreeType &coarseTree = *mTrees[n];
688 for (
ValueOnCIter it = fineTree.cbeginValueOn(); it; ++it) {
689 const Coord ijk = it.getCoord();
690 if ( (ijk[0] & 1) || (ijk[1] & 1) || (ijk[2] & 1) )
continue;
691 coarseTree.setValue( ijk >> 1, *it );
694 MaskOp tmp(fineTree, coarseTree, 128);
704 template<
typename TreeType>
707 typedef typename TreeType::template ValueConverter<ValueMask>::Type
MaskT;
708 typedef tbb::enumerable_thread_specific<TreeType>
PoolType;
711 typedef typename ManagerT::LeafNodeType::ValueOnCIter
VoxelIterT;
713 MaskOp(
const TreeType& fineTree, TreeType& coarseTree,
size_t grainSize = 1)
714 : mPool(new PoolType( coarseTree ) )
716 assert( coarseTree.empty() );
725 ManagerT leafs( mask );
726 tbb::parallel_for(leafs.
leafRange( grainSize ), *
this);
729 typedef typename PoolType::const_iterator IterT;
730 for (IterT it=mPool->begin(); it!=mPool->end(); ++it) coarseTree.topologyUnion( *it );
735 Accessor coarseAcc( mPool->local() );
737 for (VoxelIterT voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
738 Coord ijk = voxelIter.getCoord();
739 if ( (ijk[2] & 1) || (ijk[1] & 1) || (ijk[0] & 1) )
continue;
747 template<
typename TreeType>
748 template<Index Order>
751 typedef typename TreeType::template ValueConverter<ValueMask>::Type
MaskT;
752 typedef tbb::enumerable_thread_specific<MaskT>
PoolType;
753 typedef typename PoolType::iterator PoolIterT;
756 typedef typename Manager1::LeafRange Range1;
757 typedef typename Manager2::LeafRange Range2;
762 size_t grainSize = 1)
765 , mTree0( &*(parent.mTrees[
size_t(floorf(level))]) )
766 , mTree1( &*(parent.mTrees[
size_t(ceilf(level))]) )
768 assert( midTree.empty() );
769 assert( mTree0 != mTree1 );
772 MaskT examplar(
false );
773 mPool =
new PoolType( examplar );
777 tbb::parallel_for( manager.
leafRange(grainSize), *this );
781 tbb::parallel_for(tbb::blocked_range<PoolIterT>(mPool->begin(),mPool->end(),1), *
this);
784 for (PoolIterT it=mPool->begin(); it!=mPool->end(); ++it) midTree.topologyUnion( *it );
788 Manager2 manager( midTree );
789 tbb::parallel_for(manager.leafRange(grainSize), *
this);
792 void operator()(
const Range1& range)
const 794 typedef typename Manager1::LeafNodeType::ValueOnCIter VoxelIter;
805 for (
typename Range1::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
806 for (VoxelIter voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
807 Coord ijk = voxelIter.getCoord();
811 acc.setValueOn( ijk );
815 void operator()(
const tbb::blocked_range<PoolIterT>& range)
const 817 for (PoolIterT it=range.begin(); it!=range.end(); ++it) {
821 void operator()(
const Range2 &r)
const 823 typedef typename TreeType::LeafNodeType::ValueOnIter VoxelIter;
837 const float scale0 =
math::Pow( 2.0f, b );
838 const float scale1 =
math::Pow( 2.0f,-a );
840 for (
typename Range2::Iterator leafIter = r.begin(); leafIter; ++leafIter) {
841 for (VoxelIter voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
845 voxelIter.setValue(
ValueType(a*v0 + b*v1) );
851 const TreeType *mTree0, *mTree1;
854 template<
typename TreeType>
855 template<
typename OperatorType>
860 CookOp(
const TreeType& srcTree, TreeType& dstTree,
size_t grainSize) : acc( srcTree )
862 ManagerT leafs( dstTree );
863 tbb::parallel_for( leafs.
leafRange( grainSize ), *this );
865 CookOp(
const CookOp &other) : acc( other.acc.tree() ) {}
866 void operator()(
const RangeT& range)
const 869 typedef typename ManagerT::LeafNodeType::ValueOnIter
VoxelIterT;
870 for (LeafIterT leaf = range.
begin(); leaf; ++leaf) {
872 for (VoxelIterT voxel = leaf->beginValueOn(); voxel; ++voxel) {
873 phi[ voxel.pos() ] = OperatorType::run(voxel.getCoord(), acc);
880 template<
typename TreeType>
892 v += 4*(acc.
getValue(ijk.offsetBy(-1, 0, 0)) + acc.
getValue(ijk.offsetBy( 1, 0, 0)) +
893 acc.
getValue(ijk.offsetBy( 0,-1, 0)) + acc.
getValue(ijk.offsetBy( 0, 1, 0)) +
894 acc.
getValue(ijk.offsetBy( 0, 0,-1)) + acc.
getValue(ijk.offsetBy( 0, 0, 1)));
896 v += 2*(acc.
getValue(ijk.offsetBy(-1,-1, 0)) + acc.
getValue(ijk.offsetBy(-1, 1, 0)) +
897 acc.
getValue(ijk.offsetBy( 1,-1, 0)) + acc.
getValue(ijk.offsetBy( 1, 1, 0)) +
898 acc.
getValue(ijk.offsetBy(-1, 0,-1)) + acc.
getValue(ijk.offsetBy(-1, 0, 1)) +
899 acc.
getValue(ijk.offsetBy( 1, 0,-1)) + acc.
getValue(ijk.offsetBy( 1, 0, 1)) +
900 acc.
getValue(ijk.offsetBy( 0,-1,-1)) + acc.
getValue(ijk.offsetBy( 0,-1, 1)) +
901 acc.
getValue(ijk.offsetBy( 0, 1,-1)) + acc.
getValue(ijk.offsetBy( 0, 1, 1)));
903 for (
int i=-1; i<=1; i+=2) {
904 for (
int j=-1; j<=1; j+=2) {
905 for (
int k=-1; k<=1; k+=2) v += acc.
getValue(ijk.offsetBy(i,j,k));
913 template<
typename TreeType>
921 switch ( (ijk[0] & 1) | ((ijk[1] & 1) << 1) | ((ijk[2] & 1) << 2) ) {
926 acc.
getValue(ijk.offsetBy( 1,0,0)>>1));
929 acc.
getValue(ijk.offsetBy(0, 1,0)>>1));
932 acc.
getValue(ijk.offsetBy(-1, 1,0)>>1) +
933 acc.
getValue(ijk.offsetBy( 1,-1,0)>>1) +
934 acc.
getValue(ijk.offsetBy( 1, 1,0)>>1));
937 acc.
getValue(ijk.offsetBy(0,0, 1)>>1));
940 acc.
getValue(ijk.offsetBy(-1,0, 1)>>1) +
941 acc.
getValue(ijk.offsetBy( 1,0,-1)>>1) +
942 acc.
getValue(ijk.offsetBy( 1,0, 1)>>1));
945 acc.
getValue(ijk.offsetBy(0,-1, 1)>>1) +
946 acc.
getValue(ijk.offsetBy(0, 1,-1)>>1) +
947 acc.
getValue(ijk.offsetBy(0, 1, 1)>>1));
951 for (
int i=-1; i<=1; i+=2) {
952 for (
int j=-1; j<=1; j+=2) {
953 for (
int k=-1; k<=1; k+=2) v += acc.
getValue(ijk.offsetBy(i,j,k)>>1);
964 #endif // OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
static const char *const META_GRID_NAME
Definition: Grid.h:281
GridClass
Definition: Types.h:211
Definition: LeafManager.h:132
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:420
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:381
std::vector< GridBase::ConstPtr > GridCPtrVec
Definition: Grid.h:425
static GridClass stringToGridClass(const std::string &)
Return the class of volumetric data specified by the given string.
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
Type Pow(Type x, int n)
Return .
Definition: Math.h:527
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:115
boost::shared_ptr< GridPtrVec > GridPtrVecPtr
Definition: Grid.h:423
TypedMetadata< boost::int64_t > Int64Metadata
Definition: metadata/Metadata.h:380
boost::shared_ptr< Grid > Ptr
Definition: Grid.h:485
Definition: ValueAccessor.h:219
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: ValueAccessor.h:292
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:761
TypedMetadata< std::string > StringMetadata
Definition: StringMetadata.h:42
double Real
Definition: Types.h:64
virtual void setTree(TreeBase::Ptr)
Associate the given tree with this grid, in place of its existing tree.
Definition: Grid.h:1174
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:256
TypedMetadata< float > FloatMetadata
Definition: metadata/Metadata.h:378
static Ptr create()
Return a new grid with background value zero.
Definition: Grid.h:1104
#define OPENVDB_VERSION_NAME
Definition: version.h:43
Definition: Exceptions.h:39
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:594
BufferType & buffer(size_t bufferIdx)
Return the nth buffer for the leaf node to which this iterator is pointing, where n = bufferIdx and n...
Definition: LeafManager.h:154
static std::string gridClassToString(GridClass)
Return the metadata string value for the given class of volumetric data.
Iterator begin() const
Definition: LeafManager.h:188
boost::shared_ptr< GridCPtrVec > GridCPtrVecPtr
Definition: Grid.h:428
Type FractionalPart(Type x)
Return the fractional part of x.
Definition: Math.h:809
boost::shared_ptr< const Grid > ConstPtr
Definition: Grid.h:486
static const char *const META_GRID_CLASS
Definition: Grid.h:279
Definition: LeafManager.h:135
Definition: Exceptions.h:88
math::Vec3< Real > Vec3R
Definition: Types.h:76
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
GridType::Ptr createGrid(const typename GridType::ValueType &background)
Create a new grid of type GridType with a given background value.
Definition: Grid.h:1380
void setTransform(math::Transform::Ptr)
Associate the given transform with this grid, in place of its existing transform. ...
Definition: Grid.h:1039
void setName(const std::string &)
Specify a name for this grid.
GridClass getGridClass() const
Return the class of volumetric data (level set, fog volume, etc.) stored in this grid.
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:785
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54