OpenVDB  3.2.0
MultiResGrid.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2016 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
50 
51 #ifndef OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
52 #define OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
53 
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>
67 
68 #include <tbb/enumerable_thread_specific.h>
69 #include <tbb/task_scheduler_init.h>
70 #include <tbb/tbb_thread.h>
71 
72 #include <boost/type_traits/is_floating_point.hpp>
73 #include <boost/utility/enable_if.hpp>
74 
75 #include <iostream>
76 #include <sstream>
77 #include <string>
78 #include <vector>
79 
80 namespace openvdb {
82 namespace OPENVDB_VERSION_NAME {
83 namespace tools {
84 
85 template<typename TreeType>
86 class MultiResGrid: public MetaMap
87 {
88 public:
89 
90  typedef boost::shared_ptr<MultiResGrid> Ptr;
91  typedef boost::shared_ptr<const MultiResGrid> ConstPtr;
92 
93  typedef typename TreeType::ValueType ValueType;
94  typedef typename TreeType::ValueOnCIter ValueOnCIter;
95  typedef typename TreeType::ValueOnIter ValueOnIter;
96  typedef typename TreeType::Ptr TreePtr;
97  typedef typename TreeType::ConstPtr ConstTreePtr;
98  typedef typename Grid<TreeType>::Ptr GridPtr;
100 
102 
108  MultiResGrid(size_t levels, ValueType background, double voxelSize = 1.0);
109 
118  MultiResGrid(size_t levels, const Grid<TreeType> &grid, bool useInjection = false);
119 
129  MultiResGrid(size_t levels, GridPtr grid, bool useInjection = false);
130 
132 
136  size_t numLevels() const { return mTrees.size(); }
137 
139  static size_t finestLevel() { return 0; }
140 
142  size_t coarsestLevel() const { return mTrees.size()-1; }
143 
145 
149  TreeType& tree(size_t level);
150 
154  const TreeType& constTree(size_t level) const;
155 
159  TreePtr treePtr(size_t level);
160 
164  ConstTreePtr constTreePtr(size_t level) const;
165 
167  TreeType& finestTree() { return *mTrees.front(); }
168 
170  const TreeType& finestConstTree() const { return *mTrees.front(); }
171 
173  TreePtr finestTreePtr() { return mTrees.front(); }
174 
176  ConstTreePtr finestConstTreePtr() const { return mTrees.front(); }
177 
179  TreeType& coarsestTree() { return *mTrees.back(); }
180 
182  const TreeType& coarsestConstTree() const { return *mTrees.back(); }
183 
185  TreePtr coarsestTreePtr() { return mTrees.back(); }
186 
188  ConstTreePtr coarsestConstTreePtr() const { return mTrees.back(); }
189 
191 
195  GridPtr grid(size_t level);
196 
200  ConstGridPtr grid(size_t level) const;
201 
209  template<Index Order>
210  GridPtr createGrid(float level, size_t grainSize = 1) const;
211 
215  GridPtrVecPtr grids();
216 
220  GridCPtrVecPtr grids() const;
221 
223 
225  math::Transform& transform() { return *mTransform; }
231  const math::Transform& transform() const { return *mTransform; }
232  const math::Transform& constTransform() const { return *mTransform; }
234 
236 
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);
244 
246 
247 
248 
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;
264 
271  template<Index Order>
272  ValueType sampleValue(const Coord& ijk, double level) const;
273 
281  template<Index Order>
282  ValueType sampleValue(const Vec3R& xyz, double level) const;
283 
285 
292  ValueType prolongateVoxel(const Coord& coords, const size_t level) const;
293 
294 
298  void prolongateActiveVoxels(size_t destlevel, size_t grainSize = 1);
299 
301 
306  ValueType restrictVoxel(Coord ijk, const size_t level, bool useInjection = false) const;
307 
314  void restrictActiveVoxels(size_t destlevel, size_t grainSize = 1);
315 
317  void print(std::ostream& = std::cout, int verboseLevel = 1) const;
318 
320  std::string getName() const
321  {
322  if (Metadata::ConstPtr meta = (*this)[GridBase::META_GRID_NAME]) return meta->str();
323  return "";
324  }
325 
327  void setName(const std::string& name)
328  {
329  this->removeMeta(GridBase::META_GRID_NAME);
330  this->insertMeta(GridBase::META_GRID_NAME, StringMetadata(name));
331  }
332 
335  {
336  typename StringMetadata::ConstPtr s =
337  this->getMetadata<StringMetadata>(GridBase::META_GRID_CLASS);
338  return s ? GridBase::stringToGridClass(s->value()) : GRID_UNKNOWN;
339  }
340 
343  {
345  }
346 
348  void clearGridClass() { this->removeMeta(GridBase::META_GRID_CLASS); }
349 
350 private:
351 
352  MultiResGrid(const MultiResGrid& other);//disallow copy construction
353  MultiResGrid& operator=(const MultiResGrid& other);//disallow copy assignment
354 
355  // For optimal performance we disable registration of the ValueAccessor
358 
359  void topDownRestrict(bool useInjection);
360 
361  inline void initMeta();
362 
363  // Private struct that concurrently creates a mask of active voxel
364  // in a coarse tree from the active voxels in a fine tree
365  struct MaskOp;
366 
368  struct RestrictOp;
369 
371  struct ProlongateOp;
372 
373  // Private struct that performs multi-threaded computation of grids a fraction levels
374  template<Index Order>
375  struct FractionOp;
376 
378  template<typename OpType> struct CookOp;
379 
380  // Array of shared pointer to trees, level 0 has the highest resolution.
381  std::vector<TreePtr> mTrees;
382  // Shared point to a transform associated with the finest level grid
383  typename math::Transform::Ptr mTransform;
384 };// MultiResGrid
385 
386 template<typename TreeType>
388 MultiResGrid(size_t levels, ValueType background, double voxelSize)
389  : mTrees(levels)
390  , mTransform(math::Transform::createLinearTransform( voxelSize ))
391 {
392  this->initMeta();
393  for (size_t i=0; i<levels; ++i) mTrees[i] = TreePtr(new TreeType(background));
394 }
395 
396 template<typename TreeType>
398 MultiResGrid(size_t levels, const Grid<TreeType> &grid, bool useInjection)
399  : MetaMap(grid)
400  , mTrees(levels)
401  , mTransform( grid.transform().copy() )
402 {
403  this->initMeta();
404  mTrees[0].reset( new TreeType( grid.tree() ) );// deep copy input tree
405  mTrees[0]->voxelizeActiveTiles();
406  this->topDownRestrict(useInjection);
407 }
408 
409 template<typename TreeType>
411 MultiResGrid(size_t levels, GridPtr grid, bool useInjection)
412  : MetaMap(*grid)
413  , mTrees(levels)
414  , mTransform( grid->transform().copy() )
415 {
416  this->initMeta();
417  mTrees[0] = grid->treePtr();// steal tree from input grid
418  mTrees[0]->voxelizeActiveTiles();
419  grid->newTree();
420  this->topDownRestrict(useInjection);
421 }
422 
423 template<typename TreeType>
424 inline TreeType& MultiResGrid<TreeType>::
425 tree(size_t level)
426 {
427  assert( level < mTrees.size() );
428  return *mTrees[level];
429 }
430 
431 template<typename TreeType>
432 inline const TreeType& MultiResGrid<TreeType>::
433 constTree(size_t level) const
434 {
435  assert( level < mTrees.size() );
436  return *mTrees[level];
437 }
438 
439 template<typename TreeType>
440 inline typename TreeType::Ptr MultiResGrid<TreeType>::
441 treePtr(size_t level)
442 {
443  assert( level < mTrees.size() );
444  return mTrees[level];
445 }
446 
447 template<typename TreeType>
448 inline typename TreeType::ConstPtr MultiResGrid<TreeType>::
449 constTreePtr(size_t level) const
450 {
451  assert( level < mTrees.size() );
452  return mTrees[level];
453 }
454 
455 template<typename TreeType>
457 grid(size_t level)
458 {
459  typename Grid<TreeType>::Ptr grid = Grid<TreeType>::create(this->treePtr(level));
460  math::Transform::Ptr xform = mTransform->copy();
461  if (level>0) xform->preScale( Real(1 << level) );
462  grid->setTransform( xform );
463  grid->insertMeta( *this->copyMeta() );
464  grid->insertMeta( "MultiResGrid_Level", Int64Metadata(level));
465  std::stringstream ss;
466  ss << this->getName() << "_level_" << level;
467  grid->setName( ss.str() );
468  return grid;
469 }
470 
471 template<typename TreeType>
473 grid(size_t level) const
474 {
475  return const_cast<MultiResGrid*>(this)->grid(level);
476 }
477 
478 template<typename TreeType>
479 template<Index Order>
481 createGrid(float level, size_t grainSize) const
482 {
483  assert( level >= 0.0f && level <= float(mTrees.size()-1) );
484 
485  typename Grid<TreeType>::Ptr grid(new Grid<TreeType>(this->constTree(0).background()));
486  math::Transform::Ptr xform = mTransform->copy();
487  xform->preScale( math::Pow(2.0f, level) );
488  grid->setTransform( xform );
489  grid->insertMeta( *(this->copyMeta()) );
490  grid->insertMeta( "MultiResGrid_Level", FloatMetadata(level) );
491  std::stringstream ss;
492  ss << this->getName() << "_level_" << level;
493  grid->setName( ss.str() );
494 
495  if ( size_t(floorf(level)) == size_t(ceilf(level)) ) {
496  grid->setTree( this->constTree( size_t(floorf(level))).copy() );
497  } else {
498  FractionOp<Order> tmp(*this, grid->tree(), level, grainSize);
499  if ( grid->getGridClass() == GRID_LEVEL_SET ) {
500  signedFloodFill( grid->tree() );
501  pruneLevelSet( grid->tree() );//only creates inactive tiles
502  }
503  }
504 
505  return grid;
506 }
507 
508 template<typename TreeType>
511 {
513  for (size_t level=0; level<mTrees.size(); ++level) grids->push_back(this->grid(level));
514  return grids;
515 }
516 
517 template<typename TreeType>
519 grids() const
520 {
522  for (size_t level=0; level<mTrees.size(); ++level) grids->push_back(this->grid(level));
523  return grids;
524 }
525 
526 template<typename TreeType>
528 xyz(const Coord& in_ijk, size_t in_level, size_t out_level)
529 {
530  return Vec3R( in_ijk.data() ) * Real(1 << in_level) / Real(1 << out_level);
531 }
532 
533 template<typename TreeType>
535 xyz(const Vec3R& in_xyz, size_t in_level, size_t out_level)
536 {
537  return in_xyz * Real(1 << in_level) / Real(1 << out_level);
538 }
539 
540 template<typename TreeType>
542 xyz(const Vec3R& in_xyz, double in_level, double out_level)
543 {
544  return in_xyz * math::Pow(2.0, in_level - out_level);
545 
546 }
547 
548 template<typename TreeType>
549 template<Index Order>
550 typename TreeType::ValueType MultiResGrid<TreeType>::
551 sampleValue(const Coord& in_ijk, size_t in_level, size_t out_level) const
552 {
553  assert( in_level >= 0 && in_level < mTrees.size() );
554  assert( out_level >= 0 && out_level < mTrees.size() );
555  const ConstAccessor acc(*mTrees[out_level]);// has disabled registration!
556  return tools::Sampler<Order>::sample( acc, this->xyz(in_ijk, in_level, out_level) );
557 }
558 
559 template<typename TreeType>
560 template<Index Order>
561 typename TreeType::ValueType MultiResGrid<TreeType>::
562 sampleValue(const Vec3R& in_xyz, size_t in_level, size_t out_level) const
563 {
564  assert( in_level >= 0 && in_level < mTrees.size() );
565  assert( out_level >= 0 && out_level < mTrees.size() );
566  const ConstAccessor acc(*mTrees[out_level]);// has disabled registration!
567  return tools::Sampler<Order>::sample( acc, this->xyz(in_xyz, in_level, out_level) );
568 }
569 
570 template<typename TreeType>
571 template<Index Order>
572 typename TreeType::ValueType MultiResGrid<TreeType>::
573 sampleValue(const Coord& ijk, double level) const
574 {
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 );
581  const ValueType a = ValueType(level1 - level);
582  return a * v0 + (ValueType(1) - a) * v1;
583 }
584 
585 template<typename TreeType>
586 template<Index Order>
587 typename TreeType::ValueType MultiResGrid<TreeType>::
588 sampleValue(const Vec3R& xyz, double level) const
589 {
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 );
596  const ValueType a = ValueType(level1 - level);
597  return a * v0 + (ValueType(1) - a) * v1;
598 }
599 
600 template<typename TreeType>
601 typename TreeType::ValueType MultiResGrid<TreeType>::
602 prolongateVoxel(const Coord& ijk, const size_t level) const
603 {
604  assert( level+1 < mTrees.size() );
605  const ConstAccessor acc(*mTrees[level + 1]);// has disabled registration!
606  return ProlongateOp::run(ijk, acc);
607 }
608 
609 template<typename TreeType>
611 prolongateActiveVoxels(size_t destlevel, size_t grainSize)
612 {
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 );
617 }
618 
619 template<typename TreeType>
620 typename TreeType::ValueType MultiResGrid<TreeType>::
621 restrictVoxel(Coord ijk, const size_t destlevel, bool useInjection) const
622 {
623  assert( destlevel > 0 && destlevel < mTrees.size() );
624  const TreeType &fineTree = *mTrees[ destlevel-1 ];
625  if ( useInjection ) return fineTree.getValue(ijk<<1);
626  const ConstAccessor acc( fineTree );// has disabled registration!
627  return RestrictOp::run( ijk, acc);
628 }
629 
630 template<typename TreeType>
632 restrictActiveVoxels(size_t destlevel, size_t grainSize)
633 {
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 );
638 }
639 
640 template<typename TreeType>
642 print(std::ostream& os, int verboseLevel) const
643 {
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);
648  }
649 
650  if ( MetaMap::metaCount() > 0) {
651  os << "Additional metadata:" << std::endl;
652  for (ConstMetaIterator it = beginMeta(), end = endMeta(); it != end; ++it) {
653  os << " " << it->first;
654  if (it->second) {
655  const std::string value = it->second->str();
656  if (!value.empty()) os << ": " << value;
657  }
658  os << "\n";
659  }
660  }
661 
662  os << "Transform:" << std::endl;
663  transform().print(os, /*indent=*/" ");
664  os << std::endl;
665 }
666 
667 template<typename TreeType>
669 initMeta()
670 {
671  const size_t levels = this->numLevels();
672  if (levels < 2) {
673  OPENVDB_THROW(ValueError, "MultiResGrid: at least two levels are required");
674  }
675  this->insertMeta("MultiResGrid_Levels", Int64Metadata( levels ) );
676 }
677 
678 template<typename TreeType>
680 topDownRestrict(bool useInjection)
681 {
682  const bool isLevelSet = this->getGridClass() == GRID_LEVEL_SET;
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() ) );// empty tree
686  TreeType &coarseTree = *mTrees[n];
687  if (useInjection) {// Restriction by injection
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 );
692  }
693  } else {// Restriction by full-weighting
694  MaskOp tmp(fineTree, coarseTree, 128);
695  this->restrictActiveVoxels(n, 64);
696  }
697  if ( isLevelSet ) {
698  tools::signedFloodFill( coarseTree );
699  tools::pruneLevelSet( coarseTree );//only creates inactive tiles
700  }
701  }// loop over grid levels
702 }
703 
704 template<typename TreeType>
706 {
707  typedef typename TreeType::template ValueConverter<ValueMask>::Type MaskT;
708  typedef tbb::enumerable_thread_specific<TreeType> PoolType;
710  typedef typename ManagerT::LeafRange RangeT;
711  typedef typename ManagerT::LeafNodeType::ValueOnCIter VoxelIterT;
712 
713  MaskOp(const TreeType& fineTree, TreeType& coarseTree, size_t grainSize = 1)
714  : mPool(new PoolType( coarseTree ) )// empty coarse tree acts as examplar
715  {
716  assert( coarseTree.empty() );
717 
718  // Create Mask of restruction performed on fineTree
719  MaskT mask(fineTree, false, true, TopologyCopy() );
720 
721  // Muli-threaded dilation which also linearizes the tree to leaf nodes
723 
724  // Restriction by injection using thread-local storage of coarse tree masks
725  ManagerT leafs( mask );
726  tbb::parallel_for(leafs.leafRange( grainSize ), *this);
727 
728  // multithreaded union of thread-local coarse tree masks with the coarse tree
729  typedef typename PoolType::const_iterator IterT;
730  for (IterT it=mPool->begin(); it!=mPool->end(); ++it) coarseTree.topologyUnion( *it );
731  delete mPool;
732  }
733  void operator()(const RangeT& range) const
734  {
735  Accessor coarseAcc( mPool->local() );// disabled registration
736  for (typename RangeT::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
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;//no overlap
740  coarseAcc.setValueOn( ijk >> 1 );//injection from fine to coarse level
741  }//loop over active voxels in the fine tree
742  }// loop over leaf nodes in the fine tree
743  }
744  PoolType* mPool;
745 };// MaskOp
746 
747 template<typename TreeType>
748 template<Index Order>
750 {
751  typedef typename TreeType::template ValueConverter<ValueMask>::Type MaskT;
752  typedef tbb::enumerable_thread_specific<MaskT> PoolType;
753  typedef typename PoolType::iterator PoolIterT;
754  typedef tree::LeafManager<const TreeType> Manager1;
755  typedef tree::LeafManager<TreeType> Manager2;
756  typedef typename Manager1::LeafRange Range1;
757  typedef typename Manager2::LeafRange Range2;
758 
759  FractionOp(const MultiResGrid& parent,
760  TreeType& midTree,
761  float level,
762  size_t grainSize = 1)
763  : mLevel( level )
764  , mPool( NULL )
765  , mTree0( &*(parent.mTrees[size_t(floorf(level))]) )//high-resolution
766  , mTree1( &*(parent.mTrees[size_t(ceilf(level))]) ) //low-resolution
767  {
768  assert( midTree.empty() );
769  assert( mTree0 != mTree1 );
770 
771  // Create a pool of thread-local masks
772  MaskT examplar( false );
773  mPool = new PoolType( examplar );
774 
775  {// create mask from re-mapping coarse tree to mid-level tree
776  tree::LeafManager<const TreeType> manager( *mTree1 );
777  tbb::parallel_for( manager.leafRange(grainSize), *this );
778  }
779 
780  // Multi-threaded dilation of mask
781  tbb::parallel_for(tbb::blocked_range<PoolIterT>(mPool->begin(),mPool->end(),1), *this);
782 
783  // Union thread-local coarse tree masks into the coarse tree
784  for (PoolIterT it=mPool->begin(); it!=mPool->end(); ++it) midTree.topologyUnion( *it );
785  delete mPool;
786 
787  {// Interpolate values into the static mid level tree
788  Manager2 manager( midTree );
789  tbb::parallel_for(manager.leafRange(grainSize), *this);
790  }
791  }
792  void operator()(const Range1& range) const
793  {
794  typedef typename Manager1::LeafNodeType::ValueOnCIter VoxelIter;
795  // Let mLevel = level + frac, where
796  // level is integer part of mLevel and frac is the fractional part
797  // low-res voxel size in world units = dx1 = 2^(level + 1)
798  // mid-res voxel size in world units = dx = 2^(mLevel) = 2^(level + frac)
799  // low-res index -> world: ijk * dx1
800  // world -> mid-res index: world / dx
801  // low-res index -> mid-res index: (ijk * dx1) / dx = ijk * scale where
802  // scale = dx1/dx = 2^(level+1)/2^(level+frac) = 2^(1-frac)
803  const float scale = math::Pow(2.0f, 1.0f - math::FractionalPart(mLevel));
804  tree::ValueAccessor<MaskT, false> acc( mPool->local() );// disabled registration
805  for (typename Range1::Iterator leafIter = range.begin(); leafIter; ++leafIter) {
806  for (VoxelIter voxelIter = leafIter->cbeginValueOn(); voxelIter; ++voxelIter) {
807  Coord ijk = voxelIter.getCoord();
808  ijk[0] = int(math::Round(ijk[0] * scale));
809  ijk[1] = int(math::Round(ijk[1] * scale));
810  ijk[2] = int(math::Round(ijk[2] * scale));
811  acc.setValueOn( ijk );
812  }//loop over active voxels in the fine tree
813  }// loop over leaf nodes in the fine tree
814  }
815  void operator()(const tbb::blocked_range<PoolIterT>& range) const
816  {
817  for (PoolIterT it=range.begin(); it!=range.end(); ++it) {
819  }
820  }
821  void operator()(const Range2 &r) const
822  {
823  typedef typename TreeType::LeafNodeType::ValueOnIter VoxelIter;
824  // Let mLevel = level + frac, where
825  // level is integer part of mLevel and frac is the fractional part
826  // high-res voxel size in world units = dx0 = 2^(level)
827  // low-res voxel size in world units = dx1 = 2^(level+1)
828  // mid-res voxel size in world units = dx = 2^(mLevel) = 2^(level + frac)
829  // mid-res index -> world: ijk * dx
830  // world -> high-res index: world / dx0
831  // world -> low-res index: world / dx1
832  // mid-res index -> high-res index: (ijk * dx) / dx0 = ijk * scale0 where
833  // scale0 = dx/dx0 = 2^(level+frac)/2^(level) = 2^(frac)
834  // mid-res index -> low-res index: (ijk * dx) / dx1 = ijk * scale1 where
835  // scale1 = dx/dx1 = 2^(level+frac)/2^(level+1) = 2^(frac-1)
836  const float b = math::FractionalPart(mLevel), a = 1.0f - b;
837  const float scale0 = math::Pow( 2.0f, b );
838  const float scale1 = math::Pow( 2.0f,-a );
839  ConstAccessor acc0( *mTree0 ), acc1( *mTree1 );
840  for (typename Range2::Iterator leafIter = r.begin(); leafIter; ++leafIter) {
841  for (VoxelIter voxelIter = leafIter->beginValueOn(); voxelIter; ++voxelIter) {
842  const Vec3R xyz = Vec3R( voxelIter.getCoord().data() );// mid level coord
843  const ValueType v0 = tools::Sampler<Order>::sample( acc0, xyz * scale0 );
844  const ValueType v1 = tools::Sampler<Order>::sample( acc1, xyz * scale1 );
845  voxelIter.setValue( ValueType(a*v0 + b*v1) );
846  }
847  }
848  }
849  const float mLevel;
850  PoolType* mPool;
851  const TreeType *mTree0, *mTree1;
852 };// FractionOp
853 
854 template<typename TreeType>
855 template<typename OperatorType>
857 {
859  typedef typename ManagerT::LeafRange RangeT;
860  CookOp(const TreeType& srcTree, TreeType& dstTree, size_t grainSize) : acc( srcTree )
861  {
862  ManagerT leafs( dstTree );
863  tbb::parallel_for( leafs.leafRange( grainSize ), *this );
864  }
865  CookOp(const CookOp &other) : acc( other.acc.tree() ) {}
866  void operator()(const RangeT& range) const
867  {
868  typedef typename RangeT::Iterator LeafIterT;
869  typedef typename ManagerT::LeafNodeType::ValueOnIter VoxelIterT;
870  for (LeafIterT leaf = range.begin(); leaf; ++leaf) {
871  ValueType* phi = leaf.buffer(0).data();// avoids small overhead of out-of-core
872  for (VoxelIterT voxel = leaf->beginValueOn(); voxel; ++voxel) {
873  phi[ voxel.pos() ] = OperatorType::run(voxel.getCoord(), acc);
874  }
875  }
876  }
877  const ConstAccessor acc;
878 };// CookOp
879 
880 template<typename TreeType>
882 {
886  static ValueType run(Coord ijk, const ConstAccessor &acc)
887  {
888  ijk <<= 1;
889  // Overlapping grid point
890  ValueType v = 8*acc.getValue(ijk);
891  // neighbors in one axial direction
892  v += 4*(acc.getValue(ijk.offsetBy(-1, 0, 0)) + acc.getValue(ijk.offsetBy( 1, 0, 0)) +// x
893  acc.getValue(ijk.offsetBy( 0,-1, 0)) + acc.getValue(ijk.offsetBy( 0, 1, 0)) +// y
894  acc.getValue(ijk.offsetBy( 0, 0,-1)) + acc.getValue(ijk.offsetBy( 0, 0, 1)));// z
895  // neighbors in two axial directions
896  v += 2*(acc.getValue(ijk.offsetBy(-1,-1, 0)) + acc.getValue(ijk.offsetBy(-1, 1, 0)) +// xy
897  acc.getValue(ijk.offsetBy( 1,-1, 0)) + acc.getValue(ijk.offsetBy( 1, 1, 0)) +// xy
898  acc.getValue(ijk.offsetBy(-1, 0,-1)) + acc.getValue(ijk.offsetBy(-1, 0, 1)) +// xz
899  acc.getValue(ijk.offsetBy( 1, 0,-1)) + acc.getValue(ijk.offsetBy( 1, 0, 1)) +// xz
900  acc.getValue(ijk.offsetBy( 0,-1,-1)) + acc.getValue(ijk.offsetBy( 0,-1, 1)) +// yz
901  acc.getValue(ijk.offsetBy( 0, 1,-1)) + acc.getValue(ijk.offsetBy( 0, 1, 1)));// yz
902  // neighbors in three axial directions
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));// xyz
906  }
907  }
908  v *= ValueType(1.0f/64.0f);
909  return v;
910  }
911 };// RestrictOp
912 
913 template<typename TreeType>
915 {
919  static ValueType run(const Coord& ijk, const ConstAccessor &acc)
920  {
921  switch ( (ijk[0] & 1) | ((ijk[1] & 1) << 1) | ((ijk[2] & 1) << 2) ) {
922  case 0:// all even
923  return acc.getValue(ijk>>1);
924  case 1:// x is odd
925  return ValueType(0.5)*(acc.getValue(ijk.offsetBy(-1,0,0)>>1) +
926  acc.getValue(ijk.offsetBy( 1,0,0)>>1));
927  case 2:// y is odd
928  return ValueType(0.5)*(acc.getValue(ijk.offsetBy(0,-1,0)>>1) +
929  acc.getValue(ijk.offsetBy(0, 1,0)>>1));
930  case 3:// x&y are odd
931  return ValueType(0.25)*(acc.getValue(ijk.offsetBy(-1,-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));
935  case 4:// z is odd
936  return ValueType(0.5)*(acc.getValue(ijk.offsetBy(0,0,-1)>>1) +
937  acc.getValue(ijk.offsetBy(0,0, 1)>>1));
938  case 5:// x&z are odd
939  return ValueType(0.25)*(acc.getValue(ijk.offsetBy(-1,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));
943  case 6:// y&z are odd
944  return ValueType(0.25)*(acc.getValue(ijk.offsetBy(0,-1,-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));
948  }
949  // all are odd
950  ValueType v = zeroVal<ValueType>();
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);// xyz
954  }
955  }
956  return ValueType(0.125) * v;
957  }
958 };// ProlongateOp
959 
960 } // namespace tools
961 } // namespace OPENVDB_VERSION_NAME
962 } // namespace openvdb
963 
964 #endif // OPENVDB_TOOLS_MULTIRESGRID_HAS_BEEN_INCLUDED
965 
966 // Copyright (c) 2012-2016 DreamWorks Animation LLC
967 // All rights reserved. This software is distributed under the
968 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
boost::shared_ptr< const TypedMetadata< T > > ConstPtr
Definition: metadata/Metadata.h:143
const TreeType & finestConstTree() const
Return a const reference to the tree at the finest level.
Definition: MultiResGrid.h:170
void signedFloodFill(TreeOrLeafManagerT &tree, bool threaded=true, size_t grainSize=1, Index minLevel=0)
Set the values of all inactive voxels and tiles of a narrow-band level set from the signs of the acti...
Definition: SignedFloodFill.h:294
static const char *const META_GRID_NAME
Definition: Grid.h:281
GridClass
Definition: Types.h:211
MetaMap::Ptr copyMeta() const
Return a copy of this map whose fields are shared with this map.
boost::shared_ptr< const Metadata > ConstPtr
Definition: metadata/Metadata.h:53
std::vector< GridBase::Ptr > GridPtrVec
Definition: Grid.h:420
ConstTreePtr constTreePtr(size_t level) const
Return a const shared pointer to the tree at the specified level.
Definition: MultiResGrid.h:449
ValueType sampleValue(const Coord &in_ijk, size_t in_level, size_t out_level) const
Return the value at the specified coordinate position using interpolation of the specified order into...
size_t coarsestLevel() const
Return the level of the coarsest grid, i.e. numLevels()-1.
Definition: MultiResGrid.h:142
std::vector< GridBase::ConstPtr > GridCPtrVec
Definition: Grid.h:425
Definition: Types.h:442
MetadataMap::const_iterator ConstMetaIterator
Definition: MetaMap.h:54
const math::Transform & constTransform() const
Return a reference to the finest grid&#39;s transform, which might be shared with other grids...
Definition: MultiResGrid.h:232
const TreeType & constTree(size_t level) const
Return a const reference to the tree at the specified level.
Definition: MultiResGrid.h:433
TreeType::ValueOnIter ValueOnIter
Definition: MultiResGrid.h:95
MaskOp(const TreeType &fineTree, TreeType &coarseTree, size_t grainSize=1)
Definition: MultiResGrid.h:713
ValueType prolongateVoxel(const Coord &coords, const size_t level) const
Return the value at coordinate location in level tree from the coarser tree at level+1 using trilinea...
Definition: MultiResGrid.h:602
static GridClass stringToGridClass(const std::string &)
Return the class of volumetric data specified by the given string.
GridClass getGridClass() const
Return the class of volumetric data (level set, fog volume, etc.) stored in this grid.
Definition: MultiResGrid.h:334
TreeType::ConstPtr ConstTreePtr
Definition: MultiResGrid.h:97
TreeType::ValueType ValueType
Definition: MultiResGrid.h:93
static ValueType run(const Coord &ijk, const ConstAccessor &acc)
Interpolate values from a coarse grid (acc) into the index space (ijk) of a fine grid.
Definition: MultiResGrid.h:919
TreeType::ValueOnCIter ValueOnCIter
Definition: MultiResGrid.h:94
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
Definition: Types.h:212
TreePtr finestTreePtr()
Return a shared pointer to the tree at the finest level.
Definition: MultiResGrid.h:173
Container that maps names (strings) to values of arbitrary types.
Definition: MetaMap.h:46
GridPtr grid(size_t level)
Return a shared pointer to the grid at the specified integer level.
Definition: MultiResGrid.h:457
Definition: Morphology.h:102
size_t metaCount() const
Definition: MetaMap.h:118
PoolType * mPool
Definition: MultiResGrid.h:744
Type Pow(Type x, int n)
Return .
Definition: Math.h:527
OPENVDB_STATIC_SPECIALIZATION void dilateVoxels(TreeType &tree, int iterations=1, NearestNeighbors nn=NN_FACE)
Topologically dilate all leaf-level active voxels in a tree using one of three nearest neighbor conne...
Definition: Morphology.h:852
This class manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional auxil...
Definition: LeafManager.h:115
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:47
void print(std::ostream &=std::cout, int verboseLevel=1) const
Output a human-readable description of this MultiResGrid.
Definition: MultiResGrid.h:642
ManagerT::LeafRange RangeT
Definition: MultiResGrid.h:710
const TreeType & coarsestConstTree() const
Return a const reference to the tree at the coarsest level.
Definition: MultiResGrid.h:182
boost::shared_ptr< GridPtrVec > GridPtrVecPtr
Definition: Grid.h:423
TypedMetadata< boost::int64_t > Int64Metadata
Definition: metadata/Metadata.h:380
void pruneLevelSet(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing nodes whose values are all inactive with inactive ...
Definition: Prune.h:429
void setGridClass(GridClass cls)
Specify the class of volumetric data (level set, fog volume, etc.) stored in this grid...
Definition: MultiResGrid.h:342
void prolongateActiveVoxels(size_t destlevel, size_t grainSize=1)
Definition: MultiResGrid.h:611
TreeType & coarsestTree()
Return a reference to the tree at the coarsest level.
Definition: MultiResGrid.h:179
TreeType & tree(size_t level)
Return a reference to the tree at the specified level.
Definition: MultiResGrid.h:425
void setName(const std::string &name)
Set the name of this MultiResGrid.
Definition: MultiResGrid.h:327
boost::shared_ptr< Grid > Ptr
Definition: Grid.h:485
void insertMeta(const Name &, const Metadata &value)
Insert a new metadata field or overwrite the value of an existing field.
Definition: ValueAccessor.h:219
size_t numLevels() const
Return the number of levels, i.e. trees, in this MultiResGrid.
Definition: MultiResGrid.h:136
TreeType & tree()
Return a reference to this grid&#39;s tree, which might be shared with other grids.
Definition: Grid.h:761
ConstTreePtr coarsestConstTreePtr() const
Return a const shared pointer to the tree at the coarsest level.
Definition: MultiResGrid.h:188
TypedMetadata< std::string > StringMetadata
Definition: StringMetadata.h:42
MetaIterator beginMeta()
Definition: MetaMap.h:111
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
ValueType restrictVoxel(Coord ijk, const size_t level, bool useInjection=false) const
Definition: MultiResGrid.h:621
const math::Transform & transform() const
Return a reference to the finest grid&#39;s transform, which might be shared with other grids...
Definition: MultiResGrid.h:231
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
math::Transform & transform()
Return a reference to the finest grid&#39;s transform, which might be shared with other grids...
Definition: MultiResGrid.h:230
Definition: MultiResGrid.h:86
ConstTreePtr finestConstTreePtr() const
Return a const shared pointer to the tree at the finest level.
Definition: MultiResGrid.h:176
TreeType & finestTree()
Return a reference to the tree at the finest level.
Definition: MultiResGrid.h:167
tree::LeafManager< const MaskT > ManagerT
Definition: MultiResGrid.h:709
GridClass getGridClass() const
Return the class of volumetric data (level set, fog volume, etc.) stored in this grid.
void operator()(const RangeT &range) const
Definition: MultiResGrid.h:733
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:256
Definition: MultiResGrid.h:705
void clearGridClass()
Remove the setting specifying the class of this grid&#39;s volumetric data.
Definition: MultiResGrid.h:348
tbb::enumerable_thread_specific< TreeType > PoolType
Definition: MultiResGrid.h:708
Calculate an axis-aligned bounding box in index space from a bounding sphere in world space...
Definition: Transform.h:66
TreeType::template ValueConverter< ValueMask >::Type MaskT
Definition: MultiResGrid.h:707
boost::shared_ptr< MultiResGrid > Ptr
Definition: MultiResGrid.h:90
TreePtr coarsestTreePtr()
Return a shared pointer to the tree at the coarsest level.
Definition: MultiResGrid.h:185
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:111
Definition: Exceptions.h:39
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:594
boost::shared_ptr< const MultiResGrid > ConstPtr
Definition: MultiResGrid.h:91
const Int32 * data() const
Definition: Coord.h:155
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.
boost::shared_ptr< GridCPtrVec > GridCPtrVecPtr
Definition: Grid.h:428
Type FractionalPart(Type x)
Return the fractional part of x.
Definition: Math.h:809
Iterator begin() const
Definition: LeafManager.h:188
void print(std::ostream &os=std::cout, const std::string &indent="") const
Print a description of this transform.
MetaIterator endMeta()
Definition: MetaMap.h:112
std::string getName() const
Return a string with the name of this MultiResGrid.
Definition: MultiResGrid.h:320
ManagerT::LeafNodeType::ValueOnCIter VoxelIterT
Definition: MultiResGrid.h:711
boost::shared_ptr< const Grid > ConstPtr
Definition: Grid.h:486
OPENVDB_STATIC_SPECIALIZATION void dilateActiveValues(TreeType &tree, int iterations=1, NearestNeighbors nn=NN_FACE, TilePolicy mode=PRESERVE_TILES)
Topologically dilate all active values (i.e. both voxels and tiles) in a tree using one of three near...
Definition: Morphology.h:1071
static const char *const META_GRID_CLASS
Definition: Grid.h:279
Definition: Exceptions.h:88
math::Vec3< Real > Vec3R
Definition: Types.h:76
Grid< TreeType >::ConstPtr ConstGridPtr
Definition: MultiResGrid.h:99
static bool sample(const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &result)
Sample inTree at the floating-point index coordinate inCoord and store the result in result...
static ValueType run(Coord ijk, const ConstAccessor &acc)
Static method that performs restriction by full weighting.
Definition: MultiResGrid.h:886
GridPtrVecPtr grids()
Return a shared pointer to a vector of all the base grids in this instance of the MultiResGrid...
Definition: MultiResGrid.h:510
Definition: Types.h:213
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
GridPtr createGrid(float level, size_t grainSize=1) const
Return a shared pointer to a new grid at the specified floating-point level.
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.
boost::shared_ptr< Transform > Ptr
Definition: Transform.h:69
TreeType::Ptr TreePtr
Definition: MultiResGrid.h:96
MultiResGrid(size_t levels, ValueType background, double voxelSize=1.0)
Constructor of empty grids.
Definition: MultiResGrid.h:388
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
Grid< TreeType >::Ptr GridPtr
Definition: MultiResGrid.h:98
static size_t finestLevel()
Return the level of the finest grid (always 0)
Definition: MultiResGrid.h:139
TreePtr treePtr(size_t level)
Return a shared pointer to the tree at the specified level.
Definition: MultiResGrid.h:441
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:381
static Vec3R xyz(const Coord &in_ijk, size_t in_level, size_t out_level)
Return the floating-point index coordinate at out_level given the index coordinate in_xyz at in_level...
Definition: MultiResGrid.h:528
void restrictActiveVoxels(size_t destlevel, size_t grainSize=1)
Definition: MultiResGrid.h:632