OpenVDB: DenseSparseTools.h Source File

OpenVDB 6.1.0

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