10 #ifndef OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED 11 #define OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED 24 #include <tbb/blocked_range.h> 25 #include <tbb/parallel_for.h> 26 #include <tbb/parallel_reduce.h> 27 #include <tbb/task_group.h> 29 #include <type_traits> 40 template<
typename Gr
idOrTreeT>
41 void csgUnion(GridOrTreeT& a, GridOrTreeT& b,
bool prune =
true);
45 template<
typename Gr
idOrTreeT>
50 template<
typename Gr
idOrTreeT>
56 template<
typename Gr
idOrTreeT>
57 typename GridOrTreeT::Ptr
csgUnionCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
61 template<
typename Gr
idOrTreeT>
66 template<
typename Gr
idOrTreeT>
67 typename GridOrTreeT::Ptr
csgDifferenceCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
71 template<
typename Gr
idOrTreeT>
72 void compMax(GridOrTreeT& a, GridOrTreeT& b);
75 template<
typename Gr
idOrTreeT>
76 void compMin(GridOrTreeT& a, GridOrTreeT& b);
79 template<
typename Gr
idOrTreeT>
80 void compSum(GridOrTreeT& a, GridOrTreeT& b);
83 template<
typename Gr
idOrTreeT>
84 void compMul(GridOrTreeT& a, GridOrTreeT& b);
87 template<
typename Gr
idOrTreeT>
88 void compDiv(GridOrTreeT& a, GridOrTreeT& b);
91 template<
typename Gr
idOrTreeT>
92 void compReplace(GridOrTreeT& a,
const GridOrTreeT& b);
101 template<
typename T>
inline 102 const typename std::enable_if<!VecTraits<T>::IsVec, T>::type&
105 template<
typename T>
inline 106 const typename std::enable_if<!VecTraits<T>::IsVec, T>::type&
111 template<
typename T>
inline 112 const typename std::enable_if<VecTraits<T>::IsVec, T>::type&
113 min(
const T& a,
const T& b)
115 const typename T::ValueType aMag = a.lengthSqr(), bMag = b.lengthSqr();
116 return (aMag < bMag ? a : (bMag < aMag ? b :
std::min(a, b)));
119 template<
typename T>
inline 120 const typename std::enable_if<VecTraits<T>::IsVec, T>::type&
121 max(
const T& a,
const T& b)
123 const typename T::ValueType aMag = a.lengthSqr(), bMag = b.lengthSqr();
124 return (aMag < bMag ? b : (bMag < aMag ? a :
std::max(a, b)));
128 template<
typename T>
inline 130 divide(
const T& a,
const T& b) {
return a / b; }
132 template<
typename T>
inline 137 if (b != zero)
return a / b;
138 if (a == zero)
return 0;
145 inline bool divide(
bool a,
bool ) {
return a; }
150 enum CSGOperation { CSG_UNION, CSG_INTERSECTION, CSG_DIFFERENCE };
152 template<
typename TreeType, CSGOperation Operation>
153 struct BuildPrimarySegment
155 using ValueType =
typename TreeType::ValueType;
156 using TreePtrType =
typename TreeType::Ptr;
157 using LeafNodeType =
typename TreeType::LeafNodeType;
158 using NodeMaskType =
typename LeafNodeType::NodeMaskType;
159 using RootNodeType =
typename TreeType::RootNodeType;
160 using NodeChainType =
typename RootNodeType::NodeChainType;
161 using InternalNodeType =
typename NodeChainType::template Get<1>;
163 BuildPrimarySegment(
const TreeType& lhs,
const TreeType& rhs)
164 : mSegment(
new TreeType(lhs.background()))
170 void operator()()
const 172 std::vector<const LeafNodeType*> leafNodes;
175 std::vector<const InternalNodeType*> internalNodes;
176 mLhsTree->getNodes(internalNodes);
178 ProcessInternalNodes op(internalNodes, *mRhsTree, *mSegment, leafNodes);
179 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
182 ProcessLeafNodes op(leafNodes, *mRhsTree, *mSegment);
183 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
186 TreePtrType& segment() {
return mSegment; }
190 struct ProcessInternalNodes {
192 ProcessInternalNodes(std::vector<const InternalNodeType*>& lhsNodes,
193 const TreeType& rhsTree, TreeType& outputTree,
194 std::vector<const LeafNodeType*>& outputLeafNodes)
195 : mLhsNodes(lhsNodes.empty() ?
nullptr : &lhsNodes.front())
197 , mLocalTree(mRhsTree->background())
198 , mOutputTree(&outputTree)
200 , mOutputLeafNodes(&outputLeafNodes)
204 ProcessInternalNodes(ProcessInternalNodes& other, tbb::split)
205 : mLhsNodes(other.mLhsNodes)
206 , mRhsTree(other.mRhsTree)
207 , mLocalTree(mRhsTree->background())
208 , mOutputTree(&mLocalTree)
210 , mOutputLeafNodes(&mLocalLeafNodes)
214 void join(ProcessInternalNodes& other)
216 mOutputTree->merge(*other.mOutputTree);
217 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
218 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
221 void operator()(
const tbb::blocked_range<size_t>& range)
226 std::vector<const LeafNodeType*> tmpLeafNodes;
228 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
230 const InternalNodeType& lhsNode = *mLhsNodes[n];
231 const Coord& ijk = lhsNode.origin();
232 const InternalNodeType * rhsNode =
233 rhsAcc.template probeConstNode<InternalNodeType>(ijk);
236 lhsNode.getNodes(*mOutputLeafNodes);
238 if (Operation == CSG_INTERSECTION) {
239 if (rhsAcc.
getValue(ijk) < ValueType(0.0)) {
240 tmpLeafNodes.
clear();
241 lhsNode.getNodes(tmpLeafNodes);
242 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
243 outputAcc.
addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
247 if (!(rhsAcc.
getValue(ijk) < ValueType(0.0))) {
248 tmpLeafNodes.clear();
249 lhsNode.getNodes(tmpLeafNodes);
250 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
251 outputAcc.
addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
259 InternalNodeType
const *
const *
const mLhsNodes;
260 TreeType
const *
const mRhsTree;
262 TreeType *
const mOutputTree;
264 std::vector<const LeafNodeType*> mLocalLeafNodes;
265 std::vector<const LeafNodeType*> *
const mOutputLeafNodes;
268 struct ProcessLeafNodes {
270 ProcessLeafNodes(std::vector<const LeafNodeType*>& lhsNodes,
271 const TreeType& rhsTree, TreeType& output)
272 : mLhsNodes(lhsNodes.empty() ?
nullptr : &lhsNodes.front())
274 , mLocalTree(mRhsTree->background())
275 , mOutputTree(&output)
279 ProcessLeafNodes(ProcessLeafNodes& other, tbb::split)
280 : mLhsNodes(other.mLhsNodes)
281 , mRhsTree(other.mRhsTree)
282 , mLocalTree(mRhsTree->background())
283 , mOutputTree(&mLocalTree)
287 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
289 void operator()(
const tbb::blocked_range<size_t>& range)
294 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
296 const LeafNodeType& lhsNode = *mLhsNodes[n];
297 const Coord& ijk = lhsNode.origin();
303 LeafNodeType* outputNode = outputAcc.
touchLeaf(ijk);
304 ValueType * outputData = outputNode->buffer().data();
305 NodeMaskType& outputMask = outputNode->getValueMask();
307 const ValueType * lhsData = lhsNode.buffer().data();
308 const NodeMaskType& lhsMask = lhsNode.getValueMask();
310 const ValueType * rhsData = rhsNodePt->buffer().data();
311 const NodeMaskType& rhsMask = rhsNodePt->getValueMask();
313 if (Operation == CSG_INTERSECTION) {
314 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
315 const bool fromRhs = lhsData[pos] < rhsData[pos];
316 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
317 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
319 }
else if (Operation == CSG_DIFFERENCE){
320 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
322 const bool fromRhs = lhsData[pos] < rhsVal;
323 outputData[pos] = fromRhs ? rhsVal : lhsData[pos];
324 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
327 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
328 const bool fromRhs = lhsData[pos] > rhsData[pos];
329 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
330 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
335 if (Operation == CSG_INTERSECTION) {
336 if (rhsAcc.
getValue(ijk) < ValueType(0.0)) {
337 outputAcc.
addLeaf(
new LeafNodeType(lhsNode));
340 if (!(rhsAcc.
getValue(ijk) < ValueType(0.0))) {
341 outputAcc.
addLeaf(
new LeafNodeType(lhsNode));
348 LeafNodeType
const *
const *
const mLhsNodes;
349 TreeType
const *
const mRhsTree;
351 TreeType *
const mOutputTree;
354 TreePtrType mSegment;
355 TreeType
const *
const mLhsTree;
356 TreeType
const *
const mRhsTree;
360 template<
typename TreeType, CSGOperation Operation>
361 struct BuildSecondarySegment
363 using ValueType =
typename TreeType::ValueType;
364 using TreePtrType =
typename TreeType::Ptr;
365 using LeafNodeType =
typename TreeType::LeafNodeType;
366 using NodeMaskType =
typename LeafNodeType::NodeMaskType;
367 using RootNodeType =
typename TreeType::RootNodeType;
368 using NodeChainType =
typename RootNodeType::NodeChainType;
369 using InternalNodeType =
typename NodeChainType::template Get<1>;
371 BuildSecondarySegment(
const TreeType& lhs,
const TreeType& rhs)
372 : mSegment(
new TreeType(lhs.background()))
378 void operator()()
const 380 std::vector<const LeafNodeType*> leafNodes;
383 std::vector<const InternalNodeType*> internalNodes;
384 mRhsTree->getNodes(internalNodes);
386 ProcessInternalNodes op(internalNodes, *mLhsTree, *mSegment, leafNodes);
387 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
390 ProcessLeafNodes op(leafNodes, *mLhsTree, *mSegment);
391 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
394 TreePtrType& segment() {
return mSegment; }
398 struct ProcessInternalNodes {
400 ProcessInternalNodes(std::vector<const InternalNodeType*>& rhsNodes,
401 const TreeType& lhsTree, TreeType& outputTree,
402 std::vector<const LeafNodeType*>& outputLeafNodes)
403 : mRhsNodes(rhsNodes.empty() ?
nullptr : &rhsNodes.front())
405 , mLocalTree(mLhsTree->background())
406 , mOutputTree(&outputTree)
408 , mOutputLeafNodes(&outputLeafNodes)
412 ProcessInternalNodes(ProcessInternalNodes& other, tbb::split)
413 : mRhsNodes(other.mRhsNodes)
414 , mLhsTree(other.mLhsTree)
415 , mLocalTree(mLhsTree->background())
416 , mOutputTree(&mLocalTree)
418 , mOutputLeafNodes(&mLocalLeafNodes)
422 void join(ProcessInternalNodes& other)
424 mOutputTree->merge(*other.mOutputTree);
425 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
426 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
429 void operator()(
const tbb::blocked_range<size_t>& range)
434 std::vector<const LeafNodeType*> tmpLeafNodes;
436 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
438 const InternalNodeType& rhsNode = *mRhsNodes[n];
439 const Coord& ijk = rhsNode.origin();
440 const InternalNodeType * lhsNode =
441 lhsAcc.template probeConstNode<InternalNodeType>(ijk);
444 rhsNode.getNodes(*mOutputLeafNodes);
446 if (Operation == CSG_INTERSECTION) {
447 if (lhsAcc.
getValue(ijk) < ValueType(0.0)) {
448 tmpLeafNodes.
clear();
449 rhsNode.getNodes(tmpLeafNodes);
450 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
451 outputAcc.
addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
454 }
else if (Operation == CSG_DIFFERENCE) {
455 if (lhsAcc.
getValue(ijk) < ValueType(0.0)) {
456 tmpLeafNodes.clear();
457 rhsNode.getNodes(tmpLeafNodes);
458 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
459 LeafNodeType* outputNode =
new LeafNodeType(*tmpLeafNodes[i]);
460 outputNode->negate();
465 if (!(lhsAcc.
getValue(ijk) < ValueType(0.0))) {
466 tmpLeafNodes.clear();
467 rhsNode.getNodes(tmpLeafNodes);
468 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
469 outputAcc.
addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
477 InternalNodeType
const *
const *
const mRhsNodes;
478 TreeType
const *
const mLhsTree;
480 TreeType *
const mOutputTree;
482 std::vector<const LeafNodeType*> mLocalLeafNodes;
483 std::vector<const LeafNodeType*> *
const mOutputLeafNodes;
486 struct ProcessLeafNodes {
488 ProcessLeafNodes(std::vector<const LeafNodeType*>& rhsNodes,
489 const TreeType& lhsTree, TreeType& output)
490 : mRhsNodes(rhsNodes.empty() ?
nullptr : &rhsNodes.front())
492 , mLocalTree(mLhsTree->background())
493 , mOutputTree(&output)
497 ProcessLeafNodes(ProcessLeafNodes& rhs, tbb::split)
498 : mRhsNodes(rhs.mRhsNodes)
499 , mLhsTree(rhs.mLhsTree)
500 , mLocalTree(mLhsTree->background())
501 , mOutputTree(&mLocalTree)
505 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
507 void operator()(
const tbb::blocked_range<size_t>& range)
512 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
514 const LeafNodeType& rhsNode = *mRhsNodes[n];
515 const Coord& ijk = rhsNode.origin();
520 if (Operation == CSG_INTERSECTION) {
521 if (lhsAcc.
getValue(ijk) < ValueType(0.0)) {
522 outputAcc.
addLeaf(
new LeafNodeType(rhsNode));
524 }
else if (Operation == CSG_DIFFERENCE) {
525 if (lhsAcc.
getValue(ijk) < ValueType(0.0)) {
526 LeafNodeType* outputNode =
new LeafNodeType(rhsNode);
527 outputNode->negate();
531 if (!(lhsAcc.
getValue(ijk) < ValueType(0.0))) {
532 outputAcc.
addLeaf(
new LeafNodeType(rhsNode));
539 LeafNodeType
const *
const *
const mRhsNodes;
540 TreeType
const *
const mLhsTree;
542 TreeType *
const mOutputTree;
545 TreePtrType mSegment;
546 TreeType
const *
const mLhsTree;
547 TreeType
const *
const mRhsTree;
551 template<CSGOperation Operation,
typename TreeType>
552 typename TreeType::Ptr
553 doCSGCopy(
const TreeType& lhs,
const TreeType& rhs)
555 BuildPrimarySegment<TreeType, Operation> primary(lhs, rhs);
556 BuildSecondarySegment<TreeType, Operation> secondary(lhs, rhs);
559 tbb::task_group tasks;
561 tasks.run(secondary);
564 primary.segment()->merge(*secondary.segment());
569 return primary.segment();
576 template<
typename TreeType>
577 struct GridOrTreeConstructor
579 using TreeTypePtr =
typename TreeType::Ptr;
580 static TreeTypePtr construct(
const TreeType&, TreeTypePtr& tree) {
return tree; }
584 template<
typename TreeType>
585 struct GridOrTreeConstructor<Grid<TreeType> >
589 using TreeTypePtr =
typename TreeType::Ptr;
591 static GridTypePtr construct(
const GridType& grid, TreeTypePtr& tree) {
592 GridTypePtr maskGrid(GridType::create(tree));
593 maskGrid->setTransform(grid.transform().copy());
594 maskGrid->insertMeta(grid);
603 template <
typename LeafT>
604 using LeafPairList = std::vector<std::pair<LeafT*, LeafT*>>;
610 template <
typename TreeT>
611 void transferLeafNodes(TreeT &srcTree, TreeT &dstTree,
612 LeafPairList<typename TreeT::LeafNodeType> &overlapping)
614 using LeafT =
typename TreeT::LeafNodeType;
616 std::vector<LeafT*> srcLeafNodes;
617 srcLeafNodes.reserve(srcTree.leafCount());
618 srcTree.stealNodes(srcLeafNodes);
620 for (LeafT *srcLeaf : srcLeafNodes) {
621 LeafT *dstLeaf = acc.
probeLeaf(srcLeaf->origin());
623 overlapping.emplace_back(dstLeaf, srcLeaf);
631 template <
typename TreeT,
typename OpT>
633 typename std::enable_if<
636 std::is_same<
typename TreeT::LeafNodeType::Buffer::ValueType,
637 typename TreeT::LeafNodeType::Buffer::StorageType>
::value>::type
638 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT op)
640 using LeafT =
typename TreeT::LeafNodeType;
641 LeafPairList<LeafT> overlapping;
642 transferLeafNodes(srcTree, dstTree, overlapping);
644 using RangeT = tbb::blocked_range<size_t>;
645 tbb::parallel_for(RangeT(0, overlapping.size()), [op, &overlapping](
const RangeT& r) {
646 for (
auto i = r.begin(); i != r.end(); ++i) {
647 LeafT *dstLeaf = overlapping[i].first, *srcLeaf = overlapping[i].second;
648 dstLeaf->getValueMask() |= srcLeaf->getValueMask();
649 auto *ptr = dstLeaf->buffer().data();
650 for (
auto v = srcLeaf->cbeginValueOn(); v; ++v) op(ptr[v.pos()], *v);
657 template <
typename TreeT,
typename OpT>
659 typename std::enable_if<
662 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT)
664 using LeafT =
typename TreeT::LeafNodeType;
665 LeafPairList<LeafT> overlapping;
666 transferLeafNodes(srcTree, dstTree, overlapping);
668 using RangeT = tbb::blocked_range<size_t>;
669 tbb::parallel_for(RangeT(0, overlapping.size()), [&overlapping](
const RangeT& r) {
670 for (
auto i = r.begin(); i != r.end(); ++i) {
671 overlapping[i].first->getValueMask() |= overlapping[i].second->getValueMask();
672 delete overlapping[i].second;
678 template <
typename TreeT,
typename OpT>
680 typename std::enable_if<
683 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT op)
685 using LeafT =
typename TreeT::LeafNodeType;
686 LeafPairList<LeafT> overlapping;
687 transferLeafNodes(srcTree, dstTree, overlapping);
689 using RangeT = tbb::blocked_range<size_t>;
690 using WordT =
typename LeafT::Buffer::WordType;
691 tbb::parallel_for(RangeT(0, overlapping.size()), [op, &overlapping](
const RangeT& r) {
692 for (
auto i = r.begin(); i != r.end(); ++i) {
693 LeafT *dstLeaf = overlapping[i].first, *srcLeaf = overlapping[i].second;
694 WordT *w1 = dstLeaf->buffer().data();
695 const WordT *w2 = srcLeaf->buffer().data();
696 const WordT *w3 = &(srcLeaf->getValueMask().template getWord<WordT>(0));
697 for (
Index32 n = LeafT::Buffer::WORD_COUNT; n--; ++w1) {
698 WordT tmp = *w1, state = *w3++;
700 *w1 = (state & tmp) | (~state & *w1);
702 dstLeaf->getValueMask() |= srcLeaf->getValueMask();
709 template <
typename TreeT>
712 using ValueT =
typename TreeT::ValueType;
714 void operator()(ValueT& dst,
const ValueT& src)
const { dst = src; }
717 template <
typename TreeT>
718 void validateLevelSet(
const TreeT& tree,
const std::string& gridName = std::string(
""))
720 using ValueT =
typename TreeT::ValueType;
721 const ValueT zero = zeroVal<ValueT>();
722 if (!(tree.background() > zero)) {
723 std::stringstream ss;
724 ss <<
"expected grid ";
725 if (!gridName.empty()) ss << gridName <<
" ";
726 ss <<
"outside value > 0, got " << tree.background();
729 if (!(-tree.background() < zero)) {
730 std::stringstream ss;
731 ss <<
"expected grid ";
732 if (!gridName.empty()) ss << gridName <<
" ";
733 ss <<
"inside value < 0, got " << -tree.background();
743 template<
typename Gr
idOrTreeT>
745 compMax(GridOrTreeT& aTree, GridOrTreeT& bTree)
748 using TreeT =
typename Adapter::TreeType;
749 using ValueT =
typename TreeT::ValueType;
755 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
759 template<
typename Gr
idOrTreeT>
761 compMin(GridOrTreeT& aTree, GridOrTreeT& bTree)
764 using TreeT =
typename Adapter::TreeType;
765 using ValueT =
typename TreeT::ValueType;
771 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
775 template<
typename Gr
idOrTreeT>
777 compSum(GridOrTreeT& aTree, GridOrTreeT& bTree)
780 using TreeT =
typename Adapter::TreeType;
786 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
790 template<
typename Gr
idOrTreeT>
792 compMul(GridOrTreeT& aTree, GridOrTreeT& bTree)
795 using TreeT =
typename Adapter::TreeType;
801 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
805 template<
typename Gr
idOrTreeT>
807 compDiv(GridOrTreeT& aTree, GridOrTreeT& bTree)
810 using TreeT =
typename Adapter::TreeType;
816 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
823 template<
typename TreeT>
831 void operator()(
const typename TreeT::ValueOnCIter& iter)
const 834 iter.getBoundingBox(bbox);
835 aTree->fill(bbox, *iter);
838 void operator()(
const typename TreeT::LeafCIter& leafIter)
const 841 for (
typename TreeT::LeafCIter::LeafNodeT::ValueOnCIter iter =
842 leafIter->cbeginValueOn(); iter; ++iter)
844 acc.
setValue(iter.getCoord(), *iter);
850 template<
typename Gr
idOrTreeT>
855 using TreeT =
typename Adapter::TreeType;
856 using ValueOnCIterT =
typename TreeT::ValueOnCIter;
859 Adapter::tree(aTree).topologyUnion(Adapter::tree(bTree));
864 ValueOnCIterT iter = bTree.cbeginValueOn();
865 iter.setMaxDepth(iter.getLeafDepth() - 1);
866 foreach(iter, op,
false);
869 foreach(Adapter::tree(bTree).cbeginLeaf(), op);
876 template<
typename Gr
idOrTreeT>
881 using TreeT =
typename Adapter::TreeType;
882 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
883 composite::validateLevelSet(aTree,
"A");
884 composite::validateLevelSet(bTree,
"B");
891 template<
typename Gr
idOrTreeT>
896 using TreeT =
typename Adapter::TreeType;
897 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
898 composite::validateLevelSet(aTree,
"A");
899 composite::validateLevelSet(bTree,
"B");
906 template<
typename Gr
idOrTreeT>
911 using TreeT =
typename Adapter::TreeType;
912 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
913 composite::validateLevelSet(aTree,
"A");
914 composite::validateLevelSet(bTree,
"B");
922 template<
typename Gr
idOrTreeT>
923 typename GridOrTreeT::Ptr
927 using TreePtrT =
typename Adapter::TreeType::Ptr;
929 TreePtrT output = composite::doCSGCopy<composite::CSG_UNION>(
930 Adapter::tree(a), Adapter::tree(b));
932 return composite::GridOrTreeConstructor<GridOrTreeT>::construct(a, output);
936 template<
typename Gr
idOrTreeT>
937 typename GridOrTreeT::Ptr
941 using TreePtrT =
typename Adapter::TreeType::Ptr;
943 TreePtrT output = composite::doCSGCopy<composite::CSG_INTERSECTION>(
944 Adapter::tree(a), Adapter::tree(b));
946 return composite::GridOrTreeConstructor<GridOrTreeT>::construct(a, output);
950 template<
typename Gr
idOrTreeT>
951 typename GridOrTreeT::Ptr
955 using TreePtrT =
typename Adapter::TreeType::Ptr;
957 TreePtrT output = composite::doCSGCopy<composite::CSG_DIFFERENCE>(
958 Adapter::tree(a), Adapter::tree(b));
960 return composite::GridOrTreeConstructor<GridOrTreeT>::construct(a, output);
986 template<
typename TreeT,
typename OpT = composite::CopyOp<TreeT> >
990 composite::doCompActiveLeafVoxels<TreeT, OpT>(srcTree, dstTree, op);
999 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 1001 #ifdef OPENVDB_INSTANTIATE_COMPOSITE 1005 #define _FUNCTION(TreeT) \ 1006 void csgUnion(TreeT&, TreeT&, bool) 1010 #define _FUNCTION(TreeT) \ 1011 void csgUnion(Grid<TreeT>&, Grid<TreeT>&, bool) 1015 #define _FUNCTION(TreeT) \ 1016 void csgIntersection(TreeT&, TreeT&, bool) 1020 #define _FUNCTION(TreeT) \ 1021 void csgIntersection(Grid<TreeT>&, Grid<TreeT>&, bool) 1025 #define _FUNCTION(TreeT) \ 1026 void csgDifference(TreeT&, TreeT&, bool) 1030 #define _FUNCTION(TreeT) \ 1031 void csgDifference(Grid<TreeT>&, Grid<TreeT>&, bool) 1035 #define _FUNCTION(TreeT) \ 1036 TreeT::Ptr csgUnionCopy(const TreeT&, const TreeT&) 1040 #define _FUNCTION(TreeT) \ 1041 Grid<TreeT>::Ptr csgUnionCopy(const Grid<TreeT>&, const Grid<TreeT>&) 1045 #define _FUNCTION(TreeT) \ 1046 TreeT::Ptr csgIntersectionCopy(const TreeT&, const TreeT&) 1050 #define _FUNCTION(TreeT) \ 1051 Grid<TreeT>::Ptr csgIntersectionCopy(const Grid<TreeT>&, const Grid<TreeT>&) 1055 #define _FUNCTION(TreeT) \ 1056 TreeT::Ptr csgDifferenceCopy(const TreeT&, const TreeT&) 1060 #define _FUNCTION(TreeT) \ 1061 Grid<TreeT>::Ptr csgDifferenceCopy(const Grid<TreeT>&, const Grid<TreeT>&) 1065 #define _FUNCTION(TreeT) \ 1066 void compMax(TreeT&, TreeT&) 1070 #define _FUNCTION(TreeT) \ 1071 void compMax(Grid<TreeT>&, Grid<TreeT>&) 1075 #define _FUNCTION(TreeT) \ 1076 void compMin(TreeT&, TreeT&) 1080 #define _FUNCTION(TreeT) \ 1081 void compMin(Grid<TreeT>&, Grid<TreeT>&) 1085 #define _FUNCTION(TreeT) \ 1086 void compSum(TreeT&, TreeT&) 1090 #define _FUNCTION(TreeT) \ 1091 void compSum(Grid<TreeT>&, Grid<TreeT>&) 1095 #define _FUNCTION(TreeT) \ 1096 void compDiv(TreeT&, TreeT&) 1100 #define _FUNCTION(TreeT) \ 1101 void compDiv(Grid<TreeT>&, Grid<TreeT>&) 1105 #define _FUNCTION(TreeT) \ 1106 void compReplace(TreeT&, const TreeT&) 1110 #define _FUNCTION(TreeT) \ 1111 void compReplace(Grid<TreeT>&, const Grid<TreeT>&) 1115 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION 1122 #endif // OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED LeafNodeT * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists...
Definition: ValueAccessor.h:379
SharedPtr< Grid > Ptr
Definition: Grid.h:579
#define OPENVDB_VOLUME_TREE_INSTANTIATE(Function)
Definition: version.h.in:150
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Tag dispatch class that distinguishes constructors that steal.
Definition: Types.h:648
const BValueType & b() const
Get the B input value.
Definition: Types.h:571
void foreachTopDown(const NodeOp &op, bool threaded=true, size_t leafGrainSize=1, size_t nonLeafGrainSize=1)
Threaded method that applies a user-supplied functor to all the nodes in the tree.
Definition: NodeManager.h:976
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:219
Definition: Exceptions.h:65
Defined various multi-threaded utility functions for trees.
BBox< Coord > CoordBBox
Definition: NanoVDB.h:1658
void clear() override
Remove all nodes from this cache, then reinsert the root node.
Definition: ValueAccessor.h:393
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:529
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: ValueAccessor.h:250
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
Definition: Exceptions.h:13
ValueT value
Definition: GridBuilder.h:1287
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or nullptr if no such node exists...
Definition: ValueAccessor.h:384
Index32 Index
Definition: Types.h:54
const AValueType & a() const
Get the A input value.
Definition: Types.h:569
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:28
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:127
Functions to efficiently merge grids.
GridType
List of types that are currently supported by NanoVDB.
Definition: NanoVDB.h:216
LeafNodeT * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one, but preserve the values and active states of all voxels.
Definition: ValueAccessor.h:348
CombineArgs & setResult(const AValueType &val)
Set the output value.
Definition: Types.h:579
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)
Definition: version.h.in:147
uint32_t Index32
Definition: Types.h:52
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
Definition: ValueAccessor.h:329
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
Definition: NodeManager.h:36
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:1070
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202