OpenVDB  5.2.0
DenseSparseTools.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2018 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 //
30 
31 #ifndef OPENVDB_TOOLS_DENSESPARSETOOLS_HAS_BEEN_INCLUDED
32 #define OPENVDB_TOOLS_DENSESPARSETOOLS_HAS_BEEN_INCLUDED
33 
34 #include <tbb/parallel_reduce.h>
35 #include <tbb/blocked_range3d.h>
36 #include <tbb/blocked_range2d.h>
37 #include <tbb/blocked_range.h>
38 #include <openvdb/Types.h>
39 #include <openvdb/tree/LeafManager.h>
40 #include "Dense.h"
41 
42 
43 namespace openvdb {
45 namespace OPENVDB_VERSION_NAME {
46 namespace tools {
47 
114 template<typename OpType, typename DenseType>
115 typename OpType::ResultTreeType::Ptr
116 extractSparseTree(const DenseType& dense, const OpType& functor,
117  const typename OpType::ResultValueType& background,
118  bool threaded = true);
119 
123 template <typename DenseType, typename TreeType> struct DSConverter {
124  typedef typename DenseType::ValueType ValueType;
125 
126  typedef typename TreeType::template ValueConverter<ValueType>::Type Type;
127 };
128 
129 
139 template<typename DenseType, typename MaskTreeType>
141 extractSparseTreeWithMask(const DenseType& dense,
142  const MaskTreeType& mask,
143  const typename DenseType::ValueType& background,
144  bool threaded = true);
145 
146 
167 template<typename ValueT, typename OpType>
169  const openvdb::CoordBBox& bbox, const OpType& op, bool parallel=true);
170 
175 };
176 
184 template<DSCompositeOp, typename TreeT>
186  const TreeT& source,
187  const TreeT& alpha,
188  const typename TreeT::ValueType beta,
189  const typename TreeT::ValueType strength,
190  bool threaded = true);
191 
192 
196 template<typename OpType, typename DenseType>
198 {
199 
200 public:
201 
202  typedef openvdb::math::Coord::ValueType Index;
203 
204  typedef typename DenseType::ValueType DenseValueType;
205  typedef typename OpType::ResultTreeType ResultTreeType;
206  typedef typename ResultTreeType::ValueType ResultValueType;
207  typedef typename ResultTreeType::LeafNodeType ResultLeafNodeType;
208  typedef typename ResultTreeType::template ValueConverter<ValueMask>::Type MaskTree;
209 
210  typedef tbb::blocked_range3d<Index, Index, Index> Range3d;
211 
212 
213 private:
214 
215  const DenseType& mDense;
216  const OpType& mFunctor;
217  const ResultValueType mBackground;
218  const openvdb::math::CoordBBox mBBox;
219  const Index mWidth;
220  typename ResultTreeType::Ptr mMask;
221  openvdb::math::Coord mMin;
222 
223 
224 public:
225 
226  SparseExtractor(const DenseType& dense, const OpType& functor,
227  const ResultValueType background) :
228  mDense(dense), mFunctor(functor),
229  mBackground(background),
230  mBBox(dense.bbox()),
231  mWidth(ResultLeafNodeType::DIM),
232  mMask( new ResultTreeType(mBackground))
233  {}
234 
235 
236  SparseExtractor(const DenseType& dense,
237  const openvdb::math::CoordBBox& bbox,
238  const OpType& functor,
239  const ResultValueType background) :
240  mDense(dense), mFunctor(functor),
241  mBackground(background),
242  mBBox(bbox),
243  mWidth(ResultLeafNodeType::DIM),
244  mMask( new ResultTreeType(mBackground))
245  {
246  // mBBox must be inside the coordinate rage of the dense grid
247  if (!dense.bbox().isInside(mBBox)) {
248  OPENVDB_THROW(ValueError, "Data extraction window out of bound");
249  }
250  }
251 
252 
253  SparseExtractor(SparseExtractor& other, tbb::split):
254  mDense(other.mDense), mFunctor(other.mFunctor),
255  mBackground(other.mBackground), mBBox(other.mBBox),
256  mWidth(other.mWidth),
257  mMask(new ResultTreeType(mBackground)),
258  mMin(other.mMin)
259  {}
260 
261  typename ResultTreeType::Ptr extract(bool threaded = true) {
262 
263 
264  // Construct 3D range of leaf nodes that
265  // intersect mBBox.
266 
267  // Snap the bbox to nearest leaf nodes min and max
268 
269  openvdb::math::Coord padded_min = mBBox.min();
270  openvdb::math::Coord padded_max = mBBox.max();
271 
272 
273  padded_min &= ~(mWidth - 1);
274  padded_max &= ~(mWidth - 1);
275 
276  padded_max[0] += mWidth - 1;
277  padded_max[1] += mWidth - 1;
278  padded_max[2] += mWidth - 1;
279 
280 
281  // number of leaf nodes in each direction
282  // division by leaf width, e.g. 8 in most cases
283 
284  const Index xleafCount = ( padded_max.x() - padded_min.x() + 1 ) / mWidth;
285  const Index yleafCount = ( padded_max.y() - padded_min.y() + 1 ) / mWidth;
286  const Index zleafCount = ( padded_max.z() - padded_min.z() + 1 ) / mWidth;
287 
288  mMin = padded_min;
289 
290 
291  Range3d leafRange(0, xleafCount, 1,
292  0, yleafCount, 1,
293  0, zleafCount, 1);
294 
295 
296  // Iterate over the leafnodes applying *this as a functor.
297  if (threaded) {
298  tbb::parallel_reduce(leafRange, *this);
299  } else {
300  (*this)(leafRange);
301  }
302 
303  return mMask;
304  }
305 
306 
307  void operator()(const Range3d& range) {
308 
309  ResultLeafNodeType* leaf = NULL;
310 
311  // Unpack the range3d item.
312  const Index imin = range.pages().begin();
313  const Index imax = range.pages().end();
314 
315  const Index jmin = range.rows().begin();
316  const Index jmax = range.rows().end();
317 
318  const Index kmin = range.cols().begin();
319  const Index kmax = range.cols().end();
320 
321 
322  // loop over all the candidate leafs. Adding only those with 'true' values
323  // to the tree
324 
325  for (Index i = imin; i < imax; ++i) {
326  for (Index j = jmin; j < jmax; ++j) {
327  for (Index k = kmin; k < kmax; ++k) {
328 
329  // Calculate the origin of candidate leaf
330  const openvdb::math::Coord origin =
331  mMin + openvdb::math::Coord(mWidth * i,
332  mWidth * j,
333  mWidth * k );
334 
335  if (leaf == NULL) {
336  leaf = new ResultLeafNodeType(origin, mBackground);
337  } else {
338  leaf->setOrigin(origin);
339  leaf->fill(mBackground);
340  leaf->setValuesOff();
341  }
342 
343  // The bounding box for this leaf
344 
345  openvdb::math::CoordBBox localBBox = leaf->getNodeBoundingBox();
346 
347  // Shrink to the intersection with mBBox (i.e. the dense
348  // volume)
349 
350  localBBox.intersect(mBBox);
351 
352  // Early out for non-intersecting leafs
353 
354  if (localBBox.empty()) continue;
355 
356 
357  const openvdb::math::Coord start = localBBox.getStart();
358  const openvdb::math::Coord end = localBBox.getEnd();
359 
360  // Order the looping to respect the memory layout in
361  // the Dense source
362 
363  if (mDense.memoryLayout() == openvdb::tools::LayoutZYX) {
364 
365  openvdb::math::Coord ijk;
366  Index offset;
367  const DenseValueType* dp;
368  for (ijk[0] = start.x(); ijk[0] < end.x(); ++ijk[0] ) {
369  for (ijk[1] = start.y(); ijk[1] < end.y(); ++ijk[1] ) {
370  for (ijk[2] = start.z(),
371  offset = ResultLeafNodeType::coordToOffset(ijk),
372  dp = &mDense.getValue(ijk);
373  ijk[2] < end.z(); ++ijk[2], ++offset, ++dp) {
374 
375  mFunctor(*dp, offset, leaf);
376  }
377  }
378  }
379 
380  } else {
381 
382  openvdb::math::Coord ijk;
383  const DenseValueType* dp;
384  for (ijk[2] = start.z(); ijk[2] < end.z(); ++ijk[2]) {
385  for (ijk[1] = start.y(); ijk[1] < end.y(); ++ijk[1]) {
386  for (ijk[0] = start.x(),
387  dp = &mDense.getValue(ijk);
388  ijk[0] < end.x(); ++ijk[0], ++dp) {
389 
390  mFunctor(*dp, ijk, leaf);
391 
392  }
393  }
394  }
395  }
396 
397  // Only add non-empty leafs (empty is defined as all inactive)
398 
399  if (!leaf->isEmpty()) {
400  mMask->addLeaf(leaf);
401  leaf = NULL;
402  }
403 
404  }
405  }
406  }
407 
408  // Clean up an unused leaf.
409 
410  if (leaf != NULL) delete leaf;
411  }
412 
413  void join(SparseExtractor& rhs) {
414  mMask->merge(*rhs.mMask);
415  }
416 }; // class SparseExtractor
417 
418 
419 template<typename OpType, typename DenseType>
420 typename OpType::ResultTreeType::Ptr
421 extractSparseTree(const DenseType& dense, const OpType& functor,
422  const typename OpType::ResultValueType& background,
423  bool threaded)
424 {
425 
426  // Construct the mask using a parallel reduce pattern.
427  // Each thread computes disjoint mask-trees. The join merges
428  // into a single tree.
429 
430  SparseExtractor<OpType, DenseType> extractor(dense, functor, background);
431 
432  return extractor.extract(threaded);
433 }
434 
435 
439 template <typename DenseType, typename MaskTreeType>
441 {
442 public:
443 
445  typedef _ResultTreeType ResultTreeType;
446  typedef typename ResultTreeType::LeafNodeType ResultLeafNodeType;
447  typedef typename ResultTreeType::ValueType ResultValueType;
448  typedef ResultValueType DenseValueType;
449 
450  typedef typename ResultTreeType::template ValueConverter<ValueMask>::Type MaskTree;
452  typedef std::vector<const typename MaskTree::LeafNodeType*> MaskLeafVec;
453 
454 
455  SparseMaskedExtractor(const DenseType& dense,
456  const ResultValueType& background,
457  const MaskLeafVec& leafVec
458  ):
459  mDense(dense), mBackground(background), mBBox(dense.bbox()),
460  mLeafVec(leafVec),
461  mResult(new ResultTreeType(mBackground))
462  {}
463 
464 
465 
466  SparseMaskedExtractor(const SparseMaskedExtractor& other, tbb::split):
467  mDense(other.mDense), mBackground(other.mBackground), mBBox(other.mBBox),
468  mLeafVec(other.mLeafVec), mResult( new ResultTreeType(mBackground))
469  {}
470 
471  typename ResultTreeType::Ptr extract(bool threaded = true) {
472 
473  tbb::blocked_range<size_t> range(0, mLeafVec.size());
474 
475  if (threaded) {
476  tbb::parallel_reduce(range, *this);
477  } else {
478  (*this)(range);
479  }
480 
481  return mResult;
482  }
483 
484 
485  // Used in looping over leaf nodes in the masked grid
486  // and using the active mask to select data to
487  void operator()(const tbb::blocked_range<size_t>& range) {
488 
489  ResultLeafNodeType* leaf = NULL;
490 
491 
492  // loop over all the candidate leafs. Adding only those with 'true' values
493  // to the tree
494 
495  for (size_t idx = range.begin(); idx < range.end(); ++ idx) {
496 
497  const typename MaskTree::LeafNodeType* maskLeaf = mLeafVec[idx];
498 
499  // The bounding box for this leaf
500 
501  openvdb::math::CoordBBox localBBox = maskLeaf->getNodeBoundingBox();
502 
503  // Shrink to the intersection with the dense volume
504 
505  localBBox.intersect(mBBox);
506 
507  // Early out if there was no intersection
508 
509  if (localBBox.empty()) continue;
510 
511  // Reset or allocate the target leaf
512 
513  if (leaf == NULL) {
514  leaf = new ResultLeafNodeType(maskLeaf->origin(), mBackground);
515  } else {
516  leaf->setOrigin(maskLeaf->origin());
517  leaf->fill(mBackground);
518  leaf->setValuesOff();
519  }
520 
521 
522  // Iterate over the intersecting bounding box
523  // copying active values to the result tree
524 
525  const openvdb::math::Coord start = localBBox.getStart();
526  const openvdb::math::Coord end = localBBox.getEnd();
527 
528 
529  openvdb::math::Coord ijk;
530 
531  if (mDense.memoryLayout() == openvdb::tools::LayoutZYX
532  && maskLeaf->isDense()) {
533 
534  Index offset;
535  const DenseValueType* src;
536  for (ijk[0] = start.x(); ijk[0] < end.x(); ++ijk[0] ) {
537  for (ijk[1] = start.y(); ijk[1] < end.y(); ++ijk[1] ) {
538  for (ijk[2] = start.z(),
539  offset = ResultLeafNodeType::coordToOffset(ijk),
540  src = &mDense.getValue(ijk);
541  ijk[2] < end.z(); ++ijk[2], ++offset, ++src) {
542 
543  // copy into leaf
544  leaf->setValueOn(offset, *src);
545  }
546 
547  }
548  }
549 
550  } else {
551 
552  Index offset;
553  for (ijk[0] = start.x(); ijk[0] < end.x(); ++ijk[0] ) {
554  for (ijk[1] = start.y(); ijk[1] < end.y(); ++ijk[1] ) {
555  for (ijk[2] = start.z(),
556  offset = ResultLeafNodeType::coordToOffset(ijk);
557  ijk[2] < end.z(); ++ijk[2], ++offset) {
558 
559  if (maskLeaf->isValueOn(offset)) {
560  const ResultValueType denseValue = mDense.getValue(ijk);
561  leaf->setValueOn(offset, denseValue);
562  }
563  }
564  }
565  }
566  }
567  // Only add non-empty leafs (empty is defined as all inactive)
568 
569  if (!leaf->isEmpty()) {
570  mResult->addLeaf(leaf);
571  leaf = NULL;
572  }
573  }
574 
575  // Clean up an unused leaf.
576 
577  if (leaf != NULL) delete leaf;
578  }
579 
581  mResult->merge(*rhs.mResult);
582  }
583 
584 
585 private:
586  const DenseType& mDense;
587  const ResultValueType mBackground;
588  const openvdb::math::CoordBBox& mBBox;
589  const MaskLeafVec& mLeafVec;
590 
591  typename ResultTreeType::Ptr mResult;
592 
593 }; // class SparseMaskedExtractor
594 
595 
597 template<typename _ResultTreeType, typename DenseValueType>
599 {
600  typedef _ResultTreeType ResultTreeType;
601  typedef typename ResultTreeType::LeafNodeType ResultLeafNodeType;
602 
603  template<typename CoordOrIndex> inline void
604  operator()(const DenseValueType& a, const CoordOrIndex& offset, ResultLeafNodeType* leaf) const
605  {
606  leaf->setValueOn(offset, a);
607  }
608 };
609 
610 
611 template <typename DenseType, typename MaskTreeType>
613 extractSparseTreeWithMask(const DenseType& dense,
614  const MaskTreeType& maskProxy,
615  const typename DenseType::ValueType& background,
616  bool threaded)
617 {
619  typedef typename LeafExtractor::DenseValueType DenseValueType;
620  typedef typename LeafExtractor::ResultTreeType ResultTreeType;
621  typedef typename LeafExtractor::MaskLeafVec MaskLeafVec;
622  typedef typename LeafExtractor::MaskTree MaskTree;
623  typedef typename LeafExtractor::MaskLeafCIter MaskLeafCIter;
624  typedef ExtractAll<ResultTreeType, DenseValueType> ExtractionRule;
625 
626  // Use Mask tree to hold the topology
627 
628  MaskTree maskTree(maskProxy, false, TopologyCopy());
629 
630  // Construct an array of pointers to the mask leafs.
631 
632  const size_t leafCount = maskTree.leafCount();
633  MaskLeafVec leafarray(leafCount);
634  MaskLeafCIter leafiter = maskTree.cbeginLeaf();
635  for (size_t n = 0; n != leafCount; ++n, ++leafiter) {
636  leafarray[n] = leafiter.getLeaf();
637  }
638 
639 
640  // Extract the data that is masked leaf nodes in the mask.
641 
642  LeafExtractor leafextractor(dense, background, leafarray);
643  typename ResultTreeType::Ptr resultTree = leafextractor.extract(threaded);
644 
645 
646  // Extract data that is masked by tiles in the mask.
647 
648 
649  // Loop over the mask tiles, extracting the data into new trees.
650  // These trees will be leaf-orthogonal to the leafTree (i.e. no leaf
651  // nodes will overlap). Merge these trees into the result.
652 
653  typename MaskTreeType::ValueOnCIter tileIter(maskProxy);
654  tileIter.setMaxDepth(MaskTreeType::ValueOnCIter::LEAF_DEPTH - 1);
655 
656  // Return the leaf tree if the mask had no tiles
657 
658  if (!tileIter) return resultTree;
659 
660  ExtractionRule allrule;
661 
662  // Loop over the tiles in series, but the actual data extraction
663  // is in parallel.
664 
665  CoordBBox bbox;
666  for ( ; tileIter; ++tileIter) {
667 
668  // Find the intersection of the tile with the dense grid.
669 
670  tileIter.getBoundingBox(bbox);
671  bbox.intersect(dense.bbox());
672 
673  if (bbox.empty()) continue;
674 
675  SparseExtractor<ExtractionRule, DenseType> copyData(dense, bbox, allrule, background);
676  typename ResultTreeType::Ptr fromTileTree = copyData.extract(threaded);
677  resultTree->merge(*fromTileTree);
678  }
679 
680  return resultTree;
681 }
682 
683 
687 template <typename _ValueT, typename OpType>
689 {
690 public:
691 
692  typedef _ValueT ValueT;
694  typedef openvdb::math::Coord::ValueType IntType;
695  typedef tbb::blocked_range2d<IntType, IntType> RangeType;
696 
697 
698 private:
699 
700  DenseT& mDense;
701  const OpType& mOp;
702  openvdb::math::CoordBBox mBBox;
703 
704 public:
705  DenseTransformer(DenseT& dense,
706  const openvdb::math::CoordBBox& bbox,
707  const OpType& functor):
708  mDense(dense), mOp(functor), mBBox(dense.bbox())
709  {
710  // The iteration space is the intersection of the
711  // input bbox and the index-space covered by the dense grid
712  mBBox.intersect(bbox);
713  }
714 
716  mDense(other.mDense), mOp(other.mOp), mBBox(other.mBBox) {}
717 
718  void apply(bool threaded = true) {
719 
720  // Early out if the iteration space is empty
721 
722  if (mBBox.empty()) return;
723 
724 
725  const openvdb::math::Coord start = mBBox.getStart();
726  const openvdb::math::Coord end = mBBox.getEnd();
727 
728  // The iteration range only the slower two directions.
729  const RangeType range(start.x(), end.x(), 1,
730  start.y(), end.y(), 1);
731 
732  if (threaded) {
733  tbb::parallel_for(range, *this);
734  } else {
735  (*this)(range);
736  }
737  }
738 
739  void operator()(const RangeType& range) const {
740 
741  // The stride in the z-direction.
742  // Note: the bbox is [inclusive, inclusive]
743 
744  const size_t zlength = size_t(mBBox.max().z() - mBBox.min().z() + 1);
745 
746  const IntType imin = range.rows().begin();
747  const IntType imax = range.rows().end();
748  const IntType jmin = range.cols().begin();
749  const IntType jmax = range.cols().end();
750 
751 
752  openvdb::math::Coord xyz(imin, jmin, mBBox.min().z());
753  for (xyz[0] = imin; xyz[0] != imax; ++xyz[0]) {
754  for (xyz[1] = jmin; xyz[1] != jmax; ++xyz[1]) {
755 
756  mOp.transform(mDense, xyz, zlength);
757  }
758  }
759  }
760 }; // class DenseTransformer
761 
762 
766 template <typename ValueT, typename PointWiseOp>
768 {
769  ContiguousOp(const PointWiseOp& op) : mOp(op){}
770 
772  inline void transform(DenseT& dense, openvdb::math::Coord& ijk, size_t size) const
773  {
774  ValueT* dp = const_cast<ValueT*>(&dense.getValue(ijk));
775 
776  for (size_t offset = 0; offset < size; ++offset) {
777  dp[offset] = mOp(dp[offset]);
778  }
779  }
780 
781  const PointWiseOp mOp;
782 };
783 
784 
786 template <typename ValueT, typename PointwiseOpT>
787 void
789  const openvdb::CoordBBox& bbox,
790  const PointwiseOpT& functor, bool parallel)
791 {
793 
794  // Convert the Op so it operates on a contiguous line in memory
795 
796  OpT op(functor);
797 
798  // Apply to the index space intersection in the dense grid
799  DenseTransformer<ValueT, OpT> transformer(dense, bbox, op);
800  transformer.apply(parallel);
801 }
802 
803 
804 template <typename CompositeMethod, typename _TreeT>
806 {
807 
808 public:
809  typedef _TreeT TreeT;
810  typedef typename TreeT::ValueType ValueT;
811  typedef typename TreeT::LeafNodeType LeafT;
812  typedef typename TreeT::template ValueConverter<ValueMask>::Type MaskTreeT;
813  typedef typename MaskTreeT::LeafNodeType MaskLeafT;
815  typedef openvdb::math::Coord::ValueType Index;
816  typedef tbb::blocked_range3d<Index, Index, Index> Range3d;
817 
818  SparseToDenseCompositor(DenseT& dense, const TreeT& source, const TreeT& alpha,
819  const ValueT beta, const ValueT strength) :
820  mDense(dense), mSource(source), mAlpha(alpha), mBeta(beta), mStrength(strength)
821  {}
822 
824  mDense(other.mDense), mSource(other.mSource), mAlpha(other.mAlpha),
825  mBeta(other.mBeta), mStrength(other.mStrength) {}
826 
827 
828 
829  void sparseComposite(bool threaded) {
830 
831  const ValueT beta = mBeta;
832  const ValueT strenght = mStrength;
833 
834  // construct a tree that defines the iteration space
835 
836  MaskTreeT maskTree(mSource, false /*background*/, openvdb::TopologyCopy());
837  maskTree.topologyUnion(mAlpha);
838 
839  // Composite regions that are represented by leafnodes in either mAlpha or mSource
840  // Parallelize over bool-leafs
841 
842  openvdb::tree::LeafManager<const MaskTreeT> maskLeafs(maskTree);
843  maskLeafs.foreach(*this, threaded);
844 
845  // Composite regions that are represented by tiles
846  // Parallelize within each tile.
847 
848  typename MaskTreeT::ValueOnCIter citer = maskTree.cbeginValueOn();
849  citer.setMaxDepth(MaskTreeT::ValueOnCIter::LEAF_DEPTH - 1);
850 
851  if (!citer) return;
852 
853  typename tree::ValueAccessor<const TreeT> alphaAccessor(mAlpha);
854  typename tree::ValueAccessor<const TreeT> sourceAccessor(mSource);
855 
856  for (; citer; ++citer) {
857 
858  const openvdb::math::Coord org = citer.getCoord();
859 
860  // Early out if both alpha and source are zero in this tile.
861 
862  const ValueT alphaValue = alphaAccessor.getValue(org);
863  const ValueT sourceValue = sourceAccessor.getValue(org);
864 
865  if (openvdb::math::isZero(alphaValue) &&
866  openvdb::math::isZero(sourceValue) ) continue;
867 
868  // Compute overlap of tile with the dense grid
869 
870  openvdb::math::CoordBBox localBBox = citer.getBoundingBox();
871  localBBox.intersect(mDense.bbox());
872 
873  // Early out if there is no intersection
874 
875  if (localBBox.empty()) continue;
876 
877  // Composite the tile-uniform values into the dense grid.
878  compositeFromTile(mDense, localBBox, sourceValue,
879  alphaValue, beta, strenght, threaded);
880  }
881  }
882 
883  // Composites leaf values where the alpha values are active.
884  // Used in sparseComposite
885  void inline operator()(const MaskLeafT& maskLeaf, size_t /*i*/) const
886  {
887 
888  typedef UniformLeaf ULeaf;
889  openvdb::math::CoordBBox localBBox = maskLeaf.getNodeBoundingBox();
890  localBBox.intersect(mDense.bbox());
891 
892  // Early out for non-overlapping leafs
893 
894  if (localBBox.empty()) return;
895 
896  const openvdb::math::Coord org = maskLeaf.origin();
897  const LeafT* alphaLeaf = mAlpha.probeLeaf(org);
898  const LeafT* sourceLeaf = mSource.probeLeaf(org);
899 
900  if (!sourceLeaf) {
901 
902  // Create a source leaf proxy with the correct value
903  ULeaf uniformSource(mSource.getValue(org));
904 
905  if (!alphaLeaf) {
906 
907  // Create an alpha leaf proxy with the correct value
908  ULeaf uniformAlpha(mAlpha.getValue(org));
909 
910  compositeFromLeaf(mDense, localBBox, uniformSource, uniformAlpha,
911  mBeta, mStrength);
912  } else {
913 
914  compositeFromLeaf(mDense, localBBox, uniformSource, *alphaLeaf,
915  mBeta, mStrength);
916  }
917  } else {
918  if (!alphaLeaf) {
919 
920  // Create an alpha leaf proxy with the correct value
921  ULeaf uniformAlpha(mAlpha.getValue(org));
922 
923  compositeFromLeaf(mDense, localBBox, *sourceLeaf, uniformAlpha,
924  mBeta, mStrength);
925  } else {
926 
927  compositeFromLeaf(mDense, localBBox, *sourceLeaf, *alphaLeaf,
928  mBeta, mStrength);
929  }
930  }
931  }
932  // i.e. it assumes that all valueOff Alpha voxels have value 0.
933 
934  template <typename LeafT1, typename LeafT2>
935  inline static void compositeFromLeaf(DenseT& dense, const openvdb::math::CoordBBox& bbox,
936  const LeafT1& source, const LeafT2& alpha,
937  const ValueT beta, const ValueT strength)
938  {
939  typedef openvdb::math::Coord::ValueType IntType;
940 
941  const ValueT sbeta = strength * beta;
942  openvdb::math::Coord ijk = bbox.min();
943 
944 
945  if (alpha.isDense() /*all active values*/) {
946 
947  // Optimal path for dense alphaLeaf
948  const IntType size = bbox.max().z() + 1 - bbox.min().z();
949 
950  for (ijk[0] = bbox.min().x(); ijk[0] < bbox.max().x() + 1; ++ijk[0]) {
951  for (ijk[1] = bbox.min().y(); ijk[1] < bbox.max().y() + 1; ++ijk[1]) {
952 
953  ValueT* d = const_cast<ValueT*>(&dense.getValue(ijk));
954  const ValueT* a = &alpha.getValue(ijk);
955  const ValueT* s = &source.getValue(ijk);
956 
957  for (IntType idx = 0; idx < size; ++idx) {
958  d[idx] = CompositeMethod::apply(d[idx], a[idx], s[idx],
959  strength, beta, sbeta);
960  }
961  }
962  }
963  } else {
964 
965  // AlphaLeaf has non-active cells.
966 
967  for (ijk[0] = bbox.min().x(); ijk[0] < bbox.max().x() + 1; ++ijk[0]) {
968  for (ijk[1] = bbox.min().y(); ijk[1] < bbox.max().y() + 1; ++ijk[1]) {
969  for (ijk[2] = bbox.min().z(); ijk[2] < bbox.max().z() + 1; ++ijk[2]) {
970 
971  if (alpha.isValueOn(ijk)) {
972 
973  dense.setValue(ijk,
974  CompositeMethod::apply(dense.getValue(ijk),
975  alpha.getValue(ijk), source.getValue(ijk),
976  strength, beta, sbeta)
977  );
978  }
979  }
980  }
981  }
982  }
983  }
984 
985  inline static void compositeFromTile(DenseT& dense, openvdb::math::CoordBBox& bbox,
986  const ValueT& sourceValue, const ValueT& alphaValue,
987  const ValueT& beta, const ValueT& strength,
988  bool threaded)
989  {
990 
991  typedef UniformTransformer TileTransformer;
992  TileTransformer functor(sourceValue, alphaValue, beta, strength);
993 
994  // Transform the data inside the bbox according to the TileTranformer.
995 
996  transformDense(dense, bbox, functor, threaded);
997 
998  }
999 
1000 
1001  void denseComposite(bool threaded)
1002  {
1005  const openvdb::math::CoordBBox& bbox = mDense.bbox();
1006 
1007  Range3d range(bbox.min().x(), bbox.max().x(), LeafT::DIM,
1008  bbox.min().y(), bbox.max().y(), LeafT::DIM,
1009  bbox.min().z(), bbox.max().z(), LeafT::DIM);
1010 
1011  // Iterate over the range, compositing into
1012  // the dense grid using value accessors for
1013  // sparse the grids.
1014  if (threaded) {
1015  tbb::parallel_for(range, *this);
1016  } else {
1017  (*this)(range);
1018  }
1019 
1020  }
1021 
1022  // Composites a dense region using value accessors
1023  // into a dense grid
1024  void inline operator()(const Range3d& range) const
1025  {
1026  // Use value accessors to alpha and source
1027 
1028  typename tree::ValueAccessor<const TreeT> alphaAccessor(mAlpha);
1029  typename tree::ValueAccessor<const TreeT> sourceAccessor(mSource);
1030 
1031  const ValueT strength = mStrength;
1032  const ValueT beta = mBeta;
1033  const ValueT sbeta = strength * beta;
1034 
1035  // Unpack the range3d item.
1036  const Index imin = range.pages().begin();
1037  const Index imax = range.pages().end();
1038 
1039  const Index jmin = range.rows().begin();
1040  const Index jmax = range.rows().end();
1041 
1042  const Index kmin = range.cols().begin();
1043  const Index kmax = range.cols().end();
1044 
1045  openvdb::Coord ijk;
1046  for (ijk[0] = imin; ijk[0] < imax; ++ijk[0]) {
1047  for (ijk[1] = jmin; ijk[1] < jmax; ++ijk[1]) {
1048  for (ijk[2] = kmin; ijk[2] < kmax; ++ijk[2]) {
1049  const ValueT d_old = mDense.getValue(ijk);
1050  const ValueT& alpha = alphaAccessor.getValue(ijk);
1051  const ValueT& src = sourceAccessor.getValue(ijk);
1052 
1053  mDense.setValue(ijk, CompositeMethod::apply(d_old, alpha, src,
1054  strength, beta, sbeta));
1055  }
1056  }
1057  }
1058 
1059  }
1060 
1061 
1062 private:
1063 
1064  // Internal class that wraps the templated composite method
1065  // for use when both alpha and source are uniform over
1066  // a prescribed bbox (e.g. a tile).
1067  class UniformTransformer
1068  {
1069  public:
1070  UniformTransformer(const ValueT& source, const ValueT& alpha, const ValueT& _beta,
1071  const ValueT& _strength) :
1072  mSource(source), mAlpha(alpha), mBeta(_beta),
1073  mStrength(_strength), mSBeta(_strength * _beta)
1074  {}
1075 
1076  ValueT operator()(const ValueT& input) const
1077  {
1078  return CompositeMethod::apply(input, mAlpha, mSource,
1079  mStrength, mBeta, mSBeta);
1080  }
1081 
1082  private:
1083  const ValueT mSource; const ValueT mAlpha; const ValueT mBeta;
1084  const ValueT mStrength; const ValueT mSBeta;
1085  };
1086 
1087 
1088  // Simple Class structure that mimics a leaf
1089  // with uniform values. Holds LeafT::DIM copies
1090  // of a value in an array.
1091  struct Line { ValueT mValues[LeafT::DIM]; };
1092  class UniformLeaf : private Line
1093  {
1094  public:
1095  typedef typename LeafT::ValueType ValueT;
1096 
1097  typedef Line BaseT;
1098  UniformLeaf(const ValueT& value) : BaseT(init(value)) {}
1099 
1100  static const BaseT init(const ValueT& value) {
1101  BaseT tmp;
1102  for (openvdb::Index i = 0; i < LeafT::DIM; ++i) {
1103  tmp.mValues[i] = value;
1104  }
1105  return tmp;
1106  }
1107 
1108  bool isDense() const { return true; }
1109  bool isValueOn(openvdb::math::Coord&) const { return true; }
1110 
1111  inline const ValueT& getValue(const openvdb::math::Coord& ) const
1112  {return BaseT::mValues[0];}
1113  };
1114 
1115 private:
1116  DenseT& mDense;
1117  const TreeT& mSource;
1118  const TreeT& mAlpha;
1119  ValueT mBeta;
1120  ValueT mStrength;
1121 }; // class SparseToDenseCompositor
1122 
1123 
1124 namespace ds
1125 {
1127  template <typename ValueT>
1129  struct OpOver
1130  {
1131  static inline ValueT apply(const ValueT u, const ValueT alpha,
1132  const ValueT v,
1133  const ValueT strength,
1134  const ValueT beta,
1135  const ValueT /*sbeta*/)
1136  { return (u + strength * alpha * (beta * v - u)); }
1137  };
1138 
1139 
1140  template <typename ValueT>
1141  struct OpAdd
1142  {
1143  static inline ValueT apply(const ValueT u, const ValueT alpha,
1144  const ValueT v,
1145  const ValueT /*strength*/,
1146  const ValueT /*beta*/,
1147  const ValueT sbeta)
1148  { return (u + sbeta * alpha * v); }
1149  };
1150 
1151  template <typename ValueT>
1152  struct OpSub
1153  {
1154  static inline ValueT apply(const ValueT u, const ValueT alpha,
1155  const ValueT v,
1156  const ValueT /*strength*/,
1157  const ValueT /*beta*/,
1158  const ValueT sbeta)
1159  { return (u - sbeta * alpha * v); }
1160  };
1161 
1162  template <typename ValueT>
1163  struct OpMin
1164  {
1165  static inline ValueT apply(const ValueT u, const ValueT alpha,
1166  const ValueT v,
1167  const ValueT s /*trength*/,
1168  const ValueT beta,
1169  const ValueT /*sbeta*/)
1170  { return ( ( 1 - s * alpha) * u + s * alpha * std::min(u, beta * v) ); }
1171  };
1172 
1173 
1174  template <typename ValueT>
1175  struct OpMax
1176  {
1177  static inline ValueT apply(const ValueT u, const ValueT alpha,
1178  const ValueT v,
1179  const ValueT s/*trength*/,
1180  const ValueT beta,
1181  const ValueT /*sbeta*/)
1182  { return ( ( 1 - s * alpha ) * u + s * alpha * std::min(u, beta * v) ); }
1183  };
1184 
1185  template <typename ValueT>
1186  struct OpMult
1187  {
1188  static inline ValueT apply(const ValueT u, const ValueT alpha,
1189  const ValueT v,
1190  const ValueT s/*trength*/,
1191  const ValueT /*beta*/,
1192  const ValueT sbeta)
1193  { return ( ( 1 + alpha * (sbeta * v - s)) * u ); }
1194  };
1196 
1198  template <DSCompositeOp OP, typename ValueT>
1201 
1202  template <typename ValueT>
1204 
1205  template <typename ValueT>
1207 
1208  template <typename ValueT>
1210 
1211  template <typename ValueT>
1213 
1214  template <typename ValueT>
1216 
1217  template <typename ValueT>
1220 
1221 } // namespace ds
1222 
1223 
1224 template <DSCompositeOp OpT, typename TreeT>
1227  const TreeT& source, const TreeT& alpha,
1228  const typename TreeT::ValueType beta,
1229  const typename TreeT::ValueType strength,
1230  bool threaded)
1231 {
1232  typedef typename TreeT::ValueType ValueT;
1234  typedef typename Translator::OpT Method;
1235 
1236  if (openvdb::math::isZero(strength)) return;
1237 
1238  SparseToDenseCompositor<Method, TreeT> tool(dense, source, alpha, beta, strength);
1239 
1240  if (openvdb::math::isZero(alpha.background()) &&
1241  openvdb::math::isZero(source.background()))
1242  {
1243  // Use the sparsity of (alpha U source) as the iteration space.
1244  tool.sparseComposite(threaded);
1245  } else {
1246  // Use the bounding box of dense as the iteration space.
1247  tool.denseComposite(threaded);
1248  }
1249 }
1250 
1251 } // namespace tools
1252 } // namespace OPENVDB_VERSION_NAME
1253 } // namespace openvdb
1254 
1255 #endif //OPENVDB_TOOLS_DENSESPARSETOOLS_HAS_BEEN_INCLUDED
1256 
1257 // Copyright (c) 2012-2018 DreamWorks Animation LLC
1258 // All rights reserved. This software is distributed under the
1259 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
bool empty() const
Return true if this bounding box is empty (i.e., encloses no coordinates).
Definition: Coord.h:372
typename RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:212
void operator()(const RangeType &range) const
Definition: DenseSparseTools.h:739
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:264
SparseToDenseCompositor(DenseT &dense, const TreeT &source, const TreeT &alpha, const ValueT beta, const ValueT strength)
Definition: DenseSparseTools.h:818
SparseToDenseCompositor(const SparseToDenseCompositor &other)
Definition: DenseSparseTools.h:823
_TreeT TreeT
Definition: DenseSparseTools.h:809
openvdb::math::Coord::ValueType Index
Definition: DenseSparseTools.h:202
TreeT::LeafNodeType LeafT
Definition: DenseSparseTools.h:811
static ValueT apply(const ValueT u, const ValueT alpha, const ValueT v, const ValueT s, const ValueT beta, const ValueT)
Definition: DenseSparseTools.h:1165
a wrapper struct used to avoid unnecessary computation of memory access from Coord when all offsets a...
Definition: DenseSparseTools.h:767
_ValueT ValueT
Definition: DenseSparseTools.h:692
Dense< ValueT, openvdb::tools::LayoutZYX > DenseT
Definition: DenseSparseTools.h:771
SparseExtractor(const DenseType &dense, const openvdb::math::CoordBBox &bbox, const OpType &functor, const ResultValueType background)
Definition: DenseSparseTools.h:236
Functor-based class used to extract data that satisfies some criteria defined by the embedded OpType ...
Definition: DenseSparseTools.h:197
MaskTree::LeafCIter MaskLeafCIter
Definition: DenseSparseTools.h:451
Definition: DenseSparseTools.h:174
Definition: DenseSparseTools.h:1141
ResultTreeType::LeafNodeType ResultLeafNodeType
Definition: DenseSparseTools.h:601
OpMax< ValueT > OpT
Definition: DenseSparseTools.h:1215
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
OpAdd< ValueT > OpT
Definition: DenseSparseTools.h:1206
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
DSConverter< DenseType, MaskTreeType >::Type::Ptr extractSparseTreeWithMask(const DenseType &dense, const MaskTreeType &mask, const typename DenseType::ValueType &background, bool threaded=true)
Copy data from the intersection of a sparse tree and a dense input grid. The resulting tree has the s...
Definition: DenseSparseTools.h:613
Definition: DenseSparseTools.h:174
static ValueT apply(const ValueT u, const ValueT alpha, const ValueT v, const ValueT, const ValueT, const ValueT sbeta)
Definition: DenseSparseTools.h:1143
void operator()(const DenseValueType &a, const CoordOrIndex &offset, ResultLeafNodeType *leaf) const
Definition: DenseSparseTools.h:604
Translator that converts an enum to compositing functor types.
Definition: DenseSparseTools.h:1200
SparseMaskedExtractor(const SparseMaskedExtractor &other, tbb::split)
Definition: DenseSparseTools.h:466
DSCompositeOp
Definition: DenseSparseTools.h:173
This file defines a simple dense grid and efficient converters to and from VDB grids.
static void compositeFromTile(DenseT &dense, openvdb::math::CoordBBox &bbox, const ValueT &sourceValue, const ValueT &alphaValue, const ValueT &beta, const ValueT &strength, bool threaded)
Definition: DenseSparseTools.h:985
Definition: DenseSparseTools.h:1175
ResultValueType DenseValueType
Definition: DenseSparseTools.h:448
static ValueT apply(const ValueT u, const ValueT alpha, const ValueT v, const ValueT s, const ValueT beta, const ValueT)
Definition: DenseSparseTools.h:1177
OpMin< ValueT > OpT
Definition: DenseSparseTools.h:1212
static ValueT apply(const ValueT u, const ValueT alpha, const ValueT v, const ValueT s, const ValueT, const ValueT sbeta)
Definition: DenseSparseTools.h:1188
OpType::ResultTreeType::Ptr extractSparseTree(const DenseType &dense, const OpType &functor, const typename OpType::ResultValueType &background, bool threaded=true)
Selectively extract and transform data from a dense grid, producing a sparse tree with leaf nodes onl...
Definition: DenseSparseTools.h:421
LeafNodeT * getLeaf() const
Return the leaf node to which the iterator is pointing.
Definition: TreeIterator.h:1278
Definition: DenseSparseTools.h:1186
ResultTreeType::template ValueConverter< ValueMask >::Type MaskTree
Definition: DenseSparseTools.h:450
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:129
OpType::ResultTreeType ResultTreeType
Definition: DenseSparseTools.h:205
ResultTreeType::ValueType ResultValueType
Definition: DenseSparseTools.h:447
void operator()(const MaskLeafT &maskLeaf, size_t) const
Definition: DenseSparseTools.h:885
static void compositeFromLeaf(DenseT &dense, const openvdb::math::CoordBBox &bbox, const LeafT1 &source, const LeafT2 &alpha, const ValueT beta, const ValueT strength)
Definition: DenseSparseTools.h:935
ResultTreeType::LeafNodeType ResultLeafNodeType
Definition: DenseSparseTools.h:446
Definition: DenseSparseTools.h:1152
tbb::blocked_range3d< Index, Index, Index > Range3d
Definition: DenseSparseTools.h:210
Index32 leafCount() const override
Return the number of leaf nodes.
Definition: Tree.h:368
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
void join(SparseExtractor &rhs)
Definition: DenseSparseTools.h:413
DenseType::ValueType ValueType
Definition: DenseSparseTools.h:124
void transformDense(Dense< ValueT, openvdb::tools::LayoutZYX > &dense, const openvdb::CoordBBox &bbox, const PointwiseOpT &functor, bool parallel)
Apply a point-wise functor to the intersection of a dense grid and a given bounding box...
Definition: DenseSparseTools.h:788
_ResultTreeType ResultTreeType
Definition: DenseSparseTools.h:600
_ResultTreeType ResultTreeType
Definition: DenseSparseTools.h:445
Dense< ValueT, openvdb::tools::LayoutZYX > DenseT
Definition: DenseSparseTools.h:814
Definition: Exceptions.h:92
OpMult< ValueT > OpT
Definition: DenseSparseTools.h:1218
TreeT::ValueType ValueT
Definition: DenseSparseTools.h:810
Definition: DenseSparseTools.h:174
void compositeToDense(Dense< typename TreeT::ValueType, LayoutZYX > &dense, const TreeT &source, const TreeT &alpha, const typename TreeT::ValueType beta, const typename TreeT::ValueType strength, bool threaded=true)
Composite data from a sparse tree into a dense array of the same value type.
Definition: DenseSparseTools.h:1225
static ValueT apply(const ValueT u, const ValueT alpha, const ValueT v, const ValueT strength, const ValueT beta, const ValueT)
Definition: DenseSparseTools.h:1131
tbb::blocked_range3d< Index, Index, Index > Range3d
Definition: DenseSparseTools.h:816
ContiguousOp(const PointWiseOp &op)
Definition: DenseSparseTools.h:769
Definition: Exceptions.h:40
const ValueT & getValue(size_t offset) const
Return a const reference to the value of the voxel at the given array offset.
Definition: Dense.h:290
LeafCIter cbeginLeaf() const
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1181
Definition: DenseSparseTools.h:805
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels) ...
Definition: TreeIterator.h:1235
const PointWiseOp mOp
Definition: DenseSparseTools.h:781
void setValue(size_t offset, const ValueT &value)
Set the value of the voxel at the given array offset.
Definition: Dense.h:287
void operator()(const Range3d &range)
Definition: DenseSparseTools.h:307
OpOver< ValueT > OpT
Definition: DenseSparseTools.h:1203
Class that applies a functor to the index space intersection of a prescribed bounding box and the den...
Definition: DenseSparseTools.h:688
Index32 Index
Definition: Types.h:61
ResultTreeType::ValueType ResultValueType
Definition: DenseSparseTools.h:206
Point wise methods used to apply various compositing operations.
Definition: DenseSparseTools.h:1129
tbb::blocked_range2d< IntType, IntType > RangeType
Definition: DenseSparseTools.h:695
void join(SparseMaskedExtractor &rhs)
Definition: DenseSparseTools.h:580
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:257
ResultTreeType::LeafNodeType ResultLeafNodeType
Definition: DenseSparseTools.h:207
openvdb::math::Coord::ValueType Index
Definition: DenseSparseTools.h:815
Definition: DenseSparseTools.h:174
Definition: DenseSparseTools.h:174
std::vector< const typename MaskTree::LeafNodeType * > MaskLeafVec
Definition: DenseSparseTools.h:452
Definition: Dense.h:95
DenseType::ValueType DenseValueType
Definition: DenseSparseTools.h:204
Dense< ValueT, openvdb::tools::LayoutZYX > DenseT
Definition: DenseSparseTools.h:693
SparseExtractor(SparseExtractor &other, tbb::split)
Definition: DenseSparseTools.h:253
void intersect(const CoordBBox &bbox)
Intersect this bounding box with the given bounding box.
Definition: Coord.h:448
static ValueT apply(const ValueT u, const ValueT alpha, const ValueT v, const ValueT, const ValueT, const ValueT sbeta)
Definition: DenseSparseTools.h:1154
Dense is a simple dense grid API used by the CopyToDense and CopyFromDense classes defined below...
Definition: Dense.h:209
Functor-based class used to extract data from a dense grid, at the index-space intersection with a su...
Definition: DenseSparseTools.h:440
Definition: DenseSparseTools.h:1163
a simple utility class used by extractSparseTreeWithMask
Definition: DenseSparseTools.h:598
Definition: DenseSparseTools.h:174
ResultTreeType::template ValueConverter< ValueMask >::Type MaskTree
Definition: DenseSparseTools.h:208
Definition: DenseSparseTools.h:123
openvdb::math::Coord::ValueType IntType
Definition: DenseSparseTools.h:694
MaskTreeT::LeafNodeType MaskLeafT
Definition: DenseSparseTools.h:813
DenseTransformer(DenseT &dense, const openvdb::math::CoordBBox &bbox, const OpType &functor)
Definition: DenseSparseTools.h:705
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
tree::Tree4< ValueMask, 5, 4, 3 >::Type MaskTree
Definition: openvdb.h:54
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition: Math.h:308
TreeType::template ValueConverter< ValueType >::Type Type
Definition: DenseSparseTools.h:126
void operator()(const tbb::blocked_range< size_t > &range)
Definition: DenseSparseTools.h:487
void apply(bool threaded=true)
Definition: DenseSparseTools.h:718
void operator()(const Range3d &range) const
Definition: DenseSparseTools.h:1024
Definition: DenseSparseTools.h:174
DSConverter< DenseType, MaskTreeType >::Type _ResultTreeType
Definition: DenseSparseTools.h:444
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:518
TreeT::template ValueConverter< ValueMask >::Type MaskTreeT
Definition: DenseSparseTools.h:812
DenseTransformer(const DenseTransformer &other)
Definition: DenseSparseTools.h:715
void transform(DenseT &dense, openvdb::math::Coord &ijk, size_t size) const
Definition: DenseSparseTools.h:772
void sparseComposite(bool threaded)
Definition: DenseSparseTools.h:829
void denseComposite(bool threaded)
Definition: DenseSparseTools.h:1001
SparseMaskedExtractor(const DenseType &dense, const ResultValueType &background, const MaskLeafVec &leafVec)
Definition: DenseSparseTools.h:455
ResultTreeType::Ptr extract(bool threaded=true)
Definition: DenseSparseTools.h:261
ResultTreeType::Ptr extract(bool threaded=true)
Definition: DenseSparseTools.h:471
SparseExtractor(const DenseType &dense, const OpType &functor, const ResultValueType background)
Definition: DenseSparseTools.h:226
OpSub< ValueT > OpT
Definition: DenseSparseTools.h:1209