HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DenseSparseTools.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////
2 //
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 //
29 ///////////////////////////////////////////////////////////////////////////
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>
40 #include "Dense.h"
41 
42 
43 namespace openvdb {
45 namespace OPENVDB_VERSION_NAME {
46 namespace tools {
47 
48 /// @brief Selectively extract and transform data from a dense grid, producing a
49 /// sparse tree with leaf nodes only (e.g. create a tree from the square
50 /// of values greater than a cutoff.)
51 /// @param dense A dense grid that acts as a data source
52 /// @param functor A functor that selects and transforms data for output
53 /// @param background The background value of the resulting sparse grid
54 /// @param threaded Option to use threaded or serial code path
55 /// @return @c Ptr to tree with the valuetype and configuration defined
56 /// by typedefs in the @c functor.
57 /// @note To achieve optimal sparsity consider calling the prune()
58 /// method on the result.
59 /// @note To simply copy the all the data from a Dense grid to a
60 /// OpenVDB Grid, use tools::copyFromDense() for better performance.
61 ///
62 /// The type of the sparse tree is determined by the specified OtpType
63 /// functor by means of the typedef OptType::ResultTreeType
64 ///
65 /// The OptType function is responsible for the the transformation of
66 /// dense grid data to sparse grid data on a per-voxel basis.
67 ///
68 /// Only leaf nodes with active values will be added to the sparse grid.
69 ///
70 /// The OpType must struct that defines a the minimal form
71 /// @code
72 /// struct ExampleOp
73 /// {
74 /// typedef DesiredTreeType ResultTreeType;
75 ///
76 /// template<typename IndexOrCoord>
77 /// void OpType::operator() (const DenseValueType a, const IndexOrCoord& ijk,
78 /// ResultTreeType::LeafNodeType* leaf);
79 /// };
80 /// @endcode
81 ///
82 /// For example, to generate a <ValueType, 5, 4, 3> tree with valuesOn
83 /// at locations greater than a given maskvalue
84 /// @code
85 /// template <typename ValueType>
86 /// class Rule
87 /// {
88 /// public:
89 /// // Standard tree type (e.g. MaskTree or FloatTree in openvdb.h)
90 /// typedef typename openvdb::tree::Tree4<ValueType, 5, 4, 3>::Type ResultTreeType;
91 ///
92 /// typedef typename ResultTreeType::LeafNodeType ResultLeafNodeType;
93 /// typedef typename ResultTreeType::ValueType ResultValueType;
94 ///
95 /// typedef float DenseValueType;
96 ///
97 /// typedef vdbmath::Coord::ValueType Index;
98 ///
99 /// Rule(const DenseValueType& value): mMaskValue(value){};
100 ///
101 /// template <typename IndexOrCoord>
102 /// void operator()(const DenseValueType& a, const IndexOrCoord& offset,
103 /// ResultLeafNodeType* leaf) const
104 /// {
105 /// if (a > mMaskValue) {
106 /// leaf->setValueOn(offset, a);
107 /// }
108 /// }
109 ///
110 /// private:
111 /// const DenseValueType mMaskValue;
112 /// };
113 /// @endcode
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 
120 /// This struct that aids template resolution of a new tree type
121 /// has the same configuration at TreeType, but the ValueType from
122 /// DenseType.
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 
130 /// @brief Copy data from the intersection of a sparse tree and a dense input grid.
131 /// The resulting tree has the same configuration as the sparse tree, but holds
132 /// the data type specified by the dense input.
133 /// @param dense A dense grid that acts as a data source
134 /// @param mask The active voxels and tiles intersected with dense define iteration mask
135 /// @param background The background value of the resulting sparse grid
136 /// @param threaded Option to use threaded or serial code path
137 /// @return @c Ptr to tree with the same configuration as @c mask but of value type
138 /// defined by @c dense.
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 
147 /// Apply a point-wise functor to the intersection of a dense grid and a given bounding box
148 /// @param dense A dense grid to be transformed
149 /// @param bbox Index space bounding box, define region where the transformation is applied
150 /// @param op A functor that acts on the dense grid value type
151 /// @param parallel Used to select multithreaded or single threaded
152 /// Minimally, the @c op class has to support a @c operator() method,
153 /// @code
154 /// // Square values in a grid
155 /// struct Op
156 /// {
157 /// ValueT operator()(const ValueT& in) const
158 /// {
159 /// // do work
160 /// ValueT result = in * in;
161 ///
162 /// return result;
163 /// }
164 /// };
165 /// @endcode
166 /// NB: only Dense grids with memory layout zxy are supported
167 template<typename ValueT, typename OpType>
169  const openvdb::CoordBBox& bbox, const OpType& op, bool parallel=true);
170 
171 /// We currrently support the following operations when compositing sparse
172 /// data into a dense grid.
175 };
176 
177 /// @brief Composite data from a sparse tree into a dense array of the same value type.
178 /// @param dense Dense grid to be altered by the operation
179 /// @param source Sparse data to composite into @c dense
180 /// @param alpha Sparse Alpha mask used in compositing operations.
181 /// @param beta Constant multiplier on src
182 /// @param strength Constant multiplier on alpha
183 /// @param threaded Enable threading for this operation.
184 template<DSCompositeOp, typename TreeT>
185 void compositeToDense(Dense<typename TreeT::ValueType, LayoutZYX>& dense,
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 
193 /// @brief Functor-based class used to extract data that satisfies some
194 /// criteria defined by the embedded @c OpType functor. The @c extractSparseTree
195 /// function wraps this class.
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 
436 /// @brief Functor-based class used to extract data from a dense grid, at
437 /// the index-space intersection with a supplied mask in the form of a sparse tree.
438 /// The @c extractSparseTreeWithMask function wraps this class.
439 template <typename DenseType, typename MaskTreeType>
441 {
442 public:
443 
446  typedef typename ResultTreeType::LeafNodeType ResultLeafNodeType;
447  typedef typename ResultTreeType::ValueType ResultValueType;
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,
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 
596 /// @brief a simple utility class used by @c extractSparseTreeWithMask
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>
612 typename DSConverter<DenseType, MaskTreeType>::Type::Ptr
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 
684 /// @brief Class that applies a functor to the index space intersection
685 /// of a prescribed bounding box and the dense grid.
686 /// NB: This class only supports DenseGrids with ZYX memory layout.
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:
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 
763 /// @brief a wrapper struct used to avoid unnecessary computation of
764 /// memory access from @c Coord when all offsets are guaranteed to be
765 /// within the dense grid.
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 
785 /// Apply a point-wise functor to the intersection of a dense grid and a given bounding box
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 
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  {
1003  /// Construct a range that corresponds to the
1004  /// bounding box of the dense volume
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 {
1126  //@{
1127  /// @brief Point wise methods used to apply various compositing operations.
1128  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  };
1195  //@}
1196 
1197  //@{
1198  /// Translator that converts an enum to compositing functor types
1199  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>
1219  //@}
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/ )
void operator()(const tbb::blocked_range< size_t > &range)
GLenum GLint * range
Definition: glcorearb.h:1924
static void compositeFromTile(DenseT &dense, openvdb::math::CoordBBox &bbox, const ValueT &sourceValue, const ValueT &alphaValue, const ValueT &beta, const ValueT &strength, bool threaded)
LeafCIter cbeginLeaf() const
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1181
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...
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...
const GLdouble * v
Definition: glcorearb.h:836
GLuint start
Definition: glcorearb.h:474
DenseTransformer(DenseT &dense, const openvdb::math::CoordBBox &bbox, const OpType &functor)
Functor-based class used to extract data from a dense grid, at the index-space intersection with a su...
SparseMaskedExtractor(const SparseMaskedExtractor &other, tbb::split)
png_infop png_color_16p * background
Definition: png.h:2326
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
GLint GLuint mask
Definition: glcorearb.h:123
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:189
tree::Tree4< ValueMask, 5, 4, 3 >::Type MaskTree
Definition: openvdb.h:54
TreeT::template ValueConverter< ValueMask >::Type MaskTreeT
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.
void setValue(size_t offset, const ValueT &value)
Set the value of the voxel at the given array offset.
Definition: Dense.h:287
static ValueT apply(const ValueT u, const ValueT alpha, const ValueT v, const ValueT s, const ValueT beta, const ValueT)
png_uint_32 i
Definition: png.h:2877
GLsizeiptr size
Definition: glcorearb.h:663
Class that applies a functor to the index space intersection of a prescribed bounding box and the den...
static ValueT apply(const ValueT u, const ValueT alpha, const ValueT v, const ValueT strength, const ValueT beta, const ValueT)
void transformDense(Dense< ValueT, openvdb::tools::LayoutZYX > &dense, const openvdb::CoordBBox &bbox, const OpType &op, bool parallel=true)
GLdouble n
Definition: glcorearb.h:2007
void transform(DenseT &dense, openvdb::math::Coord &ijk, size_t size) const
static ValueT apply(const ValueT u, const ValueT alpha, const ValueT v, const ValueT s, const ValueT beta, const ValueT)
This file defines a simple dense grid and efficient converters to and from VDB grids.
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
tbb::blocked_range3d< Index, Index, Index > Range3d
tbb::blocked_range3d< Index, Index, Index > Range3d
Translator that converts an enum to compositing functor types.
GLuint GLuint end
Definition: glcorearb.h:474
Index32 leafCount() const override
Return the number of leaf nodes.
Definition: Tree.h:368
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:802
GLintptr offset
Definition: glcorearb.h:664
Dense is a simple dense grid API used by the CopyToDense and CopyFromDense classes defined below...
Definition: Dense.h:209
void operator()(const MaskLeafT &maskLeaf, size_t) const
Dense< ValueT, openvdb::tools::LayoutZYX > DenseT
GLfloat GLfloat GLfloat alpha
Definition: glcorearb.h:111
SparseExtractor(SparseExtractor &other, tbb::split)
Functor-based class used to extract data that satisfies some criteria defined by the embedded OpType ...
static ValueT apply(const ValueT u, const ValueT alpha, const ValueT v, const ValueT s, const ValueT, const ValueT sbeta)
SparseMaskedExtractor(const DenseType &dense, const ResultValueType &background, const MaskLeafVec &leafVec)
a wrapper struct used to avoid unnecessary computation of memory access from Coord when all offsets a...
ResultTreeType::Ptr extract(bool threaded=true)
GLsizei const GLfloat * value
Definition: glcorearb.h:823
a simple utility class used by extractSparseTreeWithMask
typename RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:212
TreeType::template ValueConverter< ValueType >::Type Type
Dense< ValueT, openvdb::tools::LayoutZYX > DenseT
SparseExtractor(const DenseType &dense, const OpType &functor, const ResultValueType background)
static ValueT apply(const ValueT u, const ValueT alpha, const ValueT v, const ValueT, const ValueT, const ValueT sbeta)
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
void operator()(const DenseValueType &a, const CoordOrIndex &offset, ResultLeafNodeType *leaf) const
static ValueT apply(const ValueT u, const ValueT alpha, const ValueT v, const ValueT, const ValueT, const ValueT sbeta)
ResultTreeType::template ValueConverter< ValueMask >::Type MaskTree
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:518
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
Dense< ValueT, openvdb::tools::LayoutZYX > DenseT
DSConverter< DenseType, MaskTreeType >::Type _ResultTreeType
const CoordBBox & bbox() const
Return the bounding box of the signed index domain of this grid.
Definition: Dense.h:278
LeafNodeT * getLeaf() const
Return the leaf node to which the iterator is pointing.
std::vector< const typename MaskTree::LeafNodeType * > MaskLeafVec
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:129
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:135
static void compositeFromLeaf(DenseT &dense, const openvdb::math::CoordBBox &bbox, const LeafT1 &source, const LeafT2 &alpha, const ValueT beta, const ValueT strength)
tbb::blocked_range2d< IntType, IntType > RangeType
SparseToDenseCompositor(const SparseToDenseCompositor &other)
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition: Math.h:308
Point wise methods used to apply various compositing operations.
ResultTreeType::template ValueConverter< ValueMask >::Type MaskTree
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
SparseToDenseCompositor(DenseT &dense, const TreeT &source, const TreeT &alpha, const ValueT beta, const ValueT strength)
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels) ...
SparseExtractor(const DenseType &dense, const openvdb::math::CoordBBox &bbox, const OpType &functor, const ResultValueType background)
GLenum src
Definition: glcorearb.h:1792