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> 41 template<
typename Gr
idOrTreeT>
42 void csgUnion(GridOrTreeT& a, GridOrTreeT& b,
bool prune =
true,
bool pruneCancelledTiles =
false);
47 template<
typename Gr
idOrTreeT>
48 void csgIntersection(GridOrTreeT& a, GridOrTreeT& b,
bool prune =
true,
bool pruneCancelledTiles =
false);
53 template<
typename Gr
idOrTreeT>
54 void csgDifference(GridOrTreeT& a, GridOrTreeT& b,
bool prune =
true,
bool pruneCancelledTiles =
false);
59 template<
typename Gr
idOrTreeT>
60 typename GridOrTreeT::Ptr
csgUnionCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
64 template<
typename Gr
idOrTreeT>
69 template<
typename Gr
idOrTreeT>
70 typename GridOrTreeT::Ptr
csgDifferenceCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
74 template<
typename Gr
idOrTreeT>
75 void compMax(GridOrTreeT& a, GridOrTreeT& b);
78 template<
typename Gr
idOrTreeT>
79 void compMin(GridOrTreeT& a, GridOrTreeT& b);
82 template<
typename Gr
idOrTreeT>
83 void compSum(GridOrTreeT& a, GridOrTreeT& b);
86 template<
typename Gr
idOrTreeT>
87 void compMul(GridOrTreeT& a, GridOrTreeT& b);
90 template<
typename Gr
idOrTreeT>
91 void compDiv(GridOrTreeT& a, GridOrTreeT& b);
94 template<
typename Gr
idOrTreeT>
95 void compReplace(GridOrTreeT& a,
const GridOrTreeT& b);
101 namespace composite {
104 template<
typename T>
inline 105 const typename std::enable_if<!VecTraits<T>::IsVec, T>::type&
108 template<
typename T>
inline 109 const typename std::enable_if<!VecTraits<T>::IsVec, T>::type&
114 template<
typename T>
inline 115 const typename std::enable_if<VecTraits<T>::IsVec, T>::type&
116 min(
const T& a,
const T& b)
118 const typename T::ValueType aMag = a.lengthSqr(), bMag = b.lengthSqr();
119 return (aMag < bMag ? a : (bMag < aMag ? b :
std::min(a, b)));
122 template<
typename T>
inline 123 const typename std::enable_if<VecTraits<T>::IsVec, T>::type&
124 max(
const T& a,
const T& b)
126 const typename T::ValueType aMag = a.lengthSqr(), bMag = b.lengthSqr();
127 return (aMag < bMag ? b : (bMag < aMag ? a :
std::max(a, b)));
131 template<
typename T>
inline 132 typename std::enable_if<!std::is_integral<T>::value, T>::type
133 divide(
const T& a,
const T& b) {
return a / b; }
135 template<
typename T>
inline 136 typename std::enable_if<std::is_integral<T>::value, T>::type
140 if (b != zero)
return a / b;
141 if (a == zero)
return 0;
148 inline bool divide(
bool a,
bool ) {
return a; }
153 enum CSGOperation { CSG_UNION, CSG_INTERSECTION, CSG_DIFFERENCE };
155 template<
typename TreeType, CSGOperation Operation>
156 struct BuildPrimarySegment
158 using ValueType =
typename TreeType::ValueType;
159 using TreePtrType =
typename TreeType::Ptr;
160 using LeafNodeType =
typename TreeType::LeafNodeType;
161 using NodeMaskType =
typename LeafNodeType::NodeMaskType;
162 using RootNodeType =
typename TreeType::RootNodeType;
163 using NodeChainType =
typename RootNodeType::NodeChainType;
164 using InternalNodeType =
typename NodeChainType::template Get<1>;
166 BuildPrimarySegment(
const TreeType& lhs,
const TreeType& rhs)
167 : mSegment(
new TreeType(lhs.background()))
173 void operator()()
const 175 std::vector<const LeafNodeType*> leafNodes;
178 std::vector<const InternalNodeType*> internalNodes;
179 mLhsTree->getNodes(internalNodes);
181 ProcessInternalNodes
op(internalNodes, *mRhsTree, *mSegment, leafNodes);
182 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
185 ProcessLeafNodes
op(leafNodes, *mRhsTree, *mSegment);
186 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
189 TreePtrType& segment() {
return mSegment; }
193 struct ProcessInternalNodes {
195 ProcessInternalNodes(std::vector<const InternalNodeType*>& lhsNodes,
196 const TreeType& rhsTree, TreeType& outputTree,
197 std::vector<const LeafNodeType*>& outputLeafNodes)
198 : mLhsNodes(lhsNodes.empty() ?
nullptr : &lhsNodes.front())
200 , mLocalTree(mRhsTree->background())
201 , mOutputTree(&outputTree)
203 , mOutputLeafNodes(&outputLeafNodes)
207 ProcessInternalNodes(ProcessInternalNodes& other,
tbb::split)
208 : mLhsNodes(other.mLhsNodes)
209 , mRhsTree(other.mRhsTree)
210 , mLocalTree(mRhsTree->background())
211 , mOutputTree(&mLocalTree)
213 , mOutputLeafNodes(&mLocalLeafNodes)
217 void join(ProcessInternalNodes& other)
219 mOutputTree->merge(*other.mOutputTree);
220 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
221 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
224 void operator()(
const tbb::blocked_range<size_t>& range)
229 std::vector<const LeafNodeType*> tmpLeafNodes;
231 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
233 const InternalNodeType& lhsNode = *mLhsNodes[n];
234 const Coord& ijk = lhsNode.origin();
235 const InternalNodeType * rhsNode =
236 rhsAcc.template probeConstNode<InternalNodeType>(ijk);
239 lhsNode.getNodes(*mOutputLeafNodes);
241 if (Operation == CSG_INTERSECTION) {
242 if (rhsAcc.
getValue(ijk) < ValueType(0.0)) {
243 tmpLeafNodes.
clear();
244 lhsNode.getNodes(tmpLeafNodes);
245 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
246 outputAcc.
addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
250 if (!(rhsAcc.
getValue(ijk) < ValueType(0.0))) {
251 tmpLeafNodes.clear();
252 lhsNode.getNodes(tmpLeafNodes);
253 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
254 outputAcc.
addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
262 InternalNodeType
const *
const *
const mLhsNodes;
263 TreeType
const *
const mRhsTree;
265 TreeType *
const mOutputTree;
267 std::vector<const LeafNodeType*> mLocalLeafNodes;
268 std::vector<const LeafNodeType*> *
const mOutputLeafNodes;
271 struct ProcessLeafNodes {
273 ProcessLeafNodes(std::vector<const LeafNodeType*>& lhsNodes,
274 const TreeType& rhsTree, TreeType& output)
275 : mLhsNodes(lhsNodes.empty() ?
nullptr : &lhsNodes.front())
277 , mLocalTree(mRhsTree->background())
278 , mOutputTree(&output)
282 ProcessLeafNodes(ProcessLeafNodes& other,
tbb::split)
283 : mLhsNodes(other.mLhsNodes)
284 , mRhsTree(other.mRhsTree)
285 , mLocalTree(mRhsTree->background())
286 , mOutputTree(&mLocalTree)
290 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
292 void operator()(
const tbb::blocked_range<size_t>& range)
297 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
299 const LeafNodeType& lhsNode = *mLhsNodes[n];
300 const Coord& ijk = lhsNode.origin();
306 LeafNodeType* outputNode = outputAcc.
touchLeaf(ijk);
307 ValueType * outputData = outputNode->buffer().data();
308 NodeMaskType& outputMask = outputNode->getValueMask();
310 const ValueType * lhsData = lhsNode.buffer().data();
311 const NodeMaskType& lhsMask = lhsNode.getValueMask();
313 const ValueType * rhsData = rhsNodePt->buffer().data();
314 const NodeMaskType& rhsMask = rhsNodePt->getValueMask();
316 if (Operation == CSG_INTERSECTION) {
317 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
318 const bool fromRhs = lhsData[pos] < rhsData[pos];
319 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
320 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
322 }
else if (Operation == CSG_DIFFERENCE){
323 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
325 const bool fromRhs = lhsData[pos] < rhsVal;
326 outputData[pos] = fromRhs ? rhsVal : lhsData[pos];
327 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
330 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
331 const bool fromRhs = lhsData[pos] > rhsData[pos];
332 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
333 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
338 if (Operation == CSG_INTERSECTION) {
339 if (rhsAcc.
getValue(ijk) < ValueType(0.0)) {
340 outputAcc.
addLeaf(
new LeafNodeType(lhsNode));
343 if (!(rhsAcc.
getValue(ijk) < ValueType(0.0))) {
344 outputAcc.
addLeaf(
new LeafNodeType(lhsNode));
351 LeafNodeType
const *
const *
const mLhsNodes;
352 TreeType
const *
const mRhsTree;
354 TreeType *
const mOutputTree;
357 TreePtrType mSegment;
358 TreeType
const *
const mLhsTree;
359 TreeType
const *
const mRhsTree;
363 template<
typename TreeType, CSGOperation Operation>
364 struct BuildSecondarySegment
366 using ValueType =
typename TreeType::ValueType;
367 using TreePtrType =
typename TreeType::Ptr;
368 using LeafNodeType =
typename TreeType::LeafNodeType;
369 using NodeMaskType =
typename LeafNodeType::NodeMaskType;
370 using RootNodeType =
typename TreeType::RootNodeType;
371 using NodeChainType =
typename RootNodeType::NodeChainType;
372 using InternalNodeType =
typename NodeChainType::template Get<1>;
374 BuildSecondarySegment(
const TreeType& lhs,
const TreeType& rhs)
375 : mSegment(
new TreeType(lhs.background()))
381 void operator()()
const 383 std::vector<const LeafNodeType*> leafNodes;
386 std::vector<const InternalNodeType*> internalNodes;
387 mRhsTree->getNodes(internalNodes);
389 ProcessInternalNodes
op(internalNodes, *mLhsTree, *mSegment, leafNodes);
390 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
393 ProcessLeafNodes
op(leafNodes, *mLhsTree, *mSegment);
394 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
397 TreePtrType& segment() {
return mSegment; }
401 struct ProcessInternalNodes {
403 ProcessInternalNodes(std::vector<const InternalNodeType*>& rhsNodes,
404 const TreeType& lhsTree, TreeType& outputTree,
405 std::vector<const LeafNodeType*>& outputLeafNodes)
406 : mRhsNodes(rhsNodes.empty() ?
nullptr : &rhsNodes.front())
408 , mLocalTree(mLhsTree->background())
409 , mOutputTree(&outputTree)
411 , mOutputLeafNodes(&outputLeafNodes)
415 ProcessInternalNodes(ProcessInternalNodes& other,
tbb::split)
416 : mRhsNodes(other.mRhsNodes)
417 , mLhsTree(other.mLhsTree)
418 , mLocalTree(mLhsTree->background())
419 , mOutputTree(&mLocalTree)
421 , mOutputLeafNodes(&mLocalLeafNodes)
425 void join(ProcessInternalNodes& other)
427 mOutputTree->merge(*other.mOutputTree);
428 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
429 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
432 void operator()(
const tbb::blocked_range<size_t>& range)
437 std::vector<const LeafNodeType*> tmpLeafNodes;
439 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
441 const InternalNodeType& rhsNode = *mRhsNodes[n];
442 const Coord& ijk = rhsNode.origin();
443 const InternalNodeType * lhsNode =
444 lhsAcc.template probeConstNode<InternalNodeType>(ijk);
447 rhsNode.getNodes(*mOutputLeafNodes);
449 if (Operation == CSG_INTERSECTION) {
450 if (lhsAcc.
getValue(ijk) < ValueType(0.0)) {
451 tmpLeafNodes.
clear();
452 rhsNode.getNodes(tmpLeafNodes);
453 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
454 outputAcc.
addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
457 }
else if (Operation == CSG_DIFFERENCE) {
458 if (lhsAcc.
getValue(ijk) < ValueType(0.0)) {
459 tmpLeafNodes.clear();
460 rhsNode.getNodes(tmpLeafNodes);
461 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
462 LeafNodeType* outputNode =
new LeafNodeType(*tmpLeafNodes[i]);
463 outputNode->negate();
468 if (!(lhsAcc.
getValue(ijk) < ValueType(0.0))) {
469 tmpLeafNodes.clear();
470 rhsNode.getNodes(tmpLeafNodes);
471 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
472 outputAcc.
addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
480 InternalNodeType
const *
const *
const mRhsNodes;
481 TreeType
const *
const mLhsTree;
483 TreeType *
const mOutputTree;
485 std::vector<const LeafNodeType*> mLocalLeafNodes;
486 std::vector<const LeafNodeType*> *
const mOutputLeafNodes;
489 struct ProcessLeafNodes {
491 ProcessLeafNodes(std::vector<const LeafNodeType*>& rhsNodes,
492 const TreeType& lhsTree, TreeType& output)
493 : mRhsNodes(rhsNodes.empty() ?
nullptr : &rhsNodes.front())
495 , mLocalTree(mLhsTree->background())
496 , mOutputTree(&output)
500 ProcessLeafNodes(ProcessLeafNodes& rhs,
tbb::split)
501 : mRhsNodes(rhs.mRhsNodes)
502 , mLhsTree(rhs.mLhsTree)
503 , mLocalTree(mLhsTree->background())
504 , mOutputTree(&mLocalTree)
508 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
510 void operator()(
const tbb::blocked_range<size_t>& range)
515 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
517 const LeafNodeType& rhsNode = *mRhsNodes[n];
518 const Coord& ijk = rhsNode.origin();
523 if (Operation == CSG_INTERSECTION) {
524 if (lhsAcc.
getValue(ijk) < ValueType(0.0)) {
525 outputAcc.
addLeaf(
new LeafNodeType(rhsNode));
527 }
else if (Operation == CSG_DIFFERENCE) {
528 if (lhsAcc.
getValue(ijk) < ValueType(0.0)) {
529 LeafNodeType* outputNode =
new LeafNodeType(rhsNode);
530 outputNode->negate();
534 if (!(lhsAcc.
getValue(ijk) < ValueType(0.0))) {
535 outputAcc.
addLeaf(
new LeafNodeType(rhsNode));
542 LeafNodeType
const *
const *
const mRhsNodes;
543 TreeType
const *
const mLhsTree;
545 TreeType *
const mOutputTree;
548 TreePtrType mSegment;
549 TreeType
const *
const mLhsTree;
550 TreeType
const *
const mRhsTree;
554 template<CSGOperation Operation,
typename TreeType>
555 typename TreeType::Ptr
556 doCSGCopy(
const TreeType& lhs,
const TreeType& rhs)
558 BuildPrimarySegment<TreeType, Operation> primary(lhs, rhs);
559 BuildSecondarySegment<TreeType, Operation> secondary(lhs, rhs);
562 tbb::task_group tasks;
564 tasks.run(secondary);
567 primary.segment()->merge(*secondary.segment());
572 return primary.segment();
579 template<
typename TreeType>
580 struct GridOrTreeConstructor
582 using TreeTypePtr =
typename TreeType::Ptr;
583 static TreeTypePtr construct(
const TreeType&, TreeTypePtr& tree) {
return tree; }
587 template<
typename TreeType>
588 struct GridOrTreeConstructor<Grid<TreeType> >
592 using TreeTypePtr =
typename TreeType::Ptr;
594 static GridTypePtr construct(
const GridType& grid, TreeTypePtr& tree) {
595 GridTypePtr maskGrid(GridType::create(tree));
596 maskGrid->setTransform(grid.transform().copy());
597 maskGrid->insertMeta(grid);
606 template <
typename LeafT>
607 using LeafPairList = std::vector<std::pair<LeafT*, LeafT*>>;
613 template <
typename TreeT>
614 void transferLeafNodes(TreeT &srcTree, TreeT &dstTree,
615 LeafPairList<typename TreeT::LeafNodeType> &overlapping)
617 using LeafT =
typename TreeT::LeafNodeType;
619 std::vector<LeafT*> srcLeafNodes;
620 srcLeafNodes.reserve(srcTree.leafCount());
621 srcTree.stealNodes(srcLeafNodes);
623 for (LeafT *srcLeaf : srcLeafNodes) {
624 LeafT *dstLeaf = acc.
probeLeaf(srcLeaf->origin());
626 overlapping.emplace_back(dstLeaf, srcLeaf);
634 template <
typename TreeT,
typename OpT>
636 typename std::enable_if<
637 !std::is_same<typename TreeT::ValueType, bool>::value &&
638 !std::is_same<typename TreeT::BuildType, ValueMask>::value &&
639 std::is_same<
typename TreeT::LeafNodeType::Buffer::ValueType,
640 typename TreeT::LeafNodeType::Buffer::StorageType>::value>::type
641 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT
op)
643 using LeafT =
typename TreeT::LeafNodeType;
644 LeafPairList<LeafT> overlapping;
645 transferLeafNodes(srcTree, dstTree, overlapping);
647 using RangeT = tbb::blocked_range<size_t>;
648 tbb::parallel_for(RangeT(0, overlapping.size()), [op, &overlapping](
const RangeT& r) {
649 for (
auto i = r.begin(); i != r.end(); ++i) {
650 LeafT *dstLeaf = overlapping[i].first, *srcLeaf = overlapping[i].second;
651 dstLeaf->getValueMask() |= srcLeaf->getValueMask();
652 auto *ptr = dstLeaf->buffer().data();
653 for (
auto v = srcLeaf->cbeginValueOn(); v; ++v)
op(ptr[v.pos()], *v);
660 template <
typename TreeT,
typename OpT>
662 typename std::enable_if<
663 std::is_same<typename TreeT::BuildType, ValueMask>::value &&
664 std::is_same<typename TreeT::ValueType, bool>::value>::type
665 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT)
667 using LeafT =
typename TreeT::LeafNodeType;
668 LeafPairList<LeafT> overlapping;
669 transferLeafNodes(srcTree, dstTree, overlapping);
671 using RangeT = tbb::blocked_range<size_t>;
672 tbb::parallel_for(RangeT(0, overlapping.size()), [&overlapping](
const RangeT& r) {
673 for (
auto i = r.begin(); i != r.end(); ++i) {
674 overlapping[i].first->getValueMask() |= overlapping[i].second->getValueMask();
675 delete overlapping[i].second;
681 template <
typename TreeT,
typename OpT>
683 typename std::enable_if<
684 std::is_same<typename TreeT::ValueType, bool>::value &&
685 !std::is_same<typename TreeT::BuildType, ValueMask>::value>::type
686 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT op)
688 using LeafT =
typename TreeT::LeafNodeType;
689 LeafPairList<LeafT> overlapping;
690 transferLeafNodes(srcTree, dstTree, overlapping);
692 using RangeT = tbb::blocked_range<size_t>;
693 using WordT =
typename LeafT::Buffer::WordType;
694 tbb::parallel_for(RangeT(0, overlapping.size()), [op, &overlapping](
const RangeT& r) {
695 for (
auto i = r.begin(); i != r.end(); ++i) {
696 LeafT *dstLeaf = overlapping[i].first, *srcLeaf = overlapping[i].second;
697 WordT *w1 = dstLeaf->buffer().data();
698 const WordT *w2 = srcLeaf->buffer().data();
699 const WordT *w3 = &(srcLeaf->getValueMask().template getWord<WordT>(0));
700 for (
Index32 n = LeafT::Buffer::WORD_COUNT; n--; ++w1) {
701 WordT tmp = *w1, state = *w3++;
703 *w1 = (state & tmp) | (~state & *w1);
705 dstLeaf->getValueMask() |= srcLeaf->getValueMask();
712 template <
typename TreeT>
715 using ValueT =
typename TreeT::ValueType;
717 void operator()(ValueT& dst,
const ValueT& src)
const { dst = src; }
720 template <
typename TreeT>
721 void validateLevelSet(
const TreeT& tree,
const std::string& gridName = std::string(
""))
723 using ValueT =
typename TreeT::ValueType;
724 const ValueT zero = zeroVal<ValueT>();
725 if (!(tree.background() > zero)) {
726 std::stringstream ss;
727 ss <<
"expected grid ";
728 if (!gridName.empty()) ss << gridName <<
" ";
729 ss <<
"outside value > 0, got " << tree.background();
732 if (!(-tree.background() < zero)) {
733 std::stringstream ss;
734 ss <<
"expected grid ";
735 if (!gridName.empty()) ss << gridName <<
" ";
736 ss <<
"inside value < 0, got " << -tree.background();
746 template<
typename Gr
idOrTreeT>
748 compMax(GridOrTreeT& aTree, GridOrTreeT& bTree)
751 using TreeT =
typename Adapter::TreeType;
752 using ValueT =
typename TreeT::ValueType;
758 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree),
Local::op,
false);
762 template<
typename Gr
idOrTreeT>
764 compMin(GridOrTreeT& aTree, GridOrTreeT& bTree)
767 using TreeT =
typename Adapter::TreeType;
768 using ValueT =
typename TreeT::ValueType;
774 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree),
Local::op,
false);
778 template<
typename Gr
idOrTreeT>
780 compSum(GridOrTreeT& aTree, GridOrTreeT& bTree)
783 using TreeT =
typename Adapter::TreeType;
789 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree),
Local::op,
false);
793 template<
typename Gr
idOrTreeT>
795 compMul(GridOrTreeT& aTree, GridOrTreeT& bTree)
798 using TreeT =
typename Adapter::TreeType;
799 using ValueT =
typename GridOrTreeT::ValueType;
802 if constexpr(std::is_same<ValueT, bool>::value) {
809 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree),
Local::op,
false);
813 template<
typename Gr
idOrTreeT>
815 compDiv(GridOrTreeT& aTree, GridOrTreeT& bTree)
818 using TreeT =
typename Adapter::TreeType;
824 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree),
Local::op,
false);
831 template<
typename TreeT>
839 void operator()(
const typename TreeT::ValueOnCIter& iter)
const 842 iter.getBoundingBox(bbox);
843 aTree->fill(bbox, *iter);
846 void operator()(
const typename TreeT::LeafCIter& leafIter)
const 849 for (
typename TreeT::LeafCIter::LeafNodeT::ValueOnCIter iter =
850 leafIter->cbeginValueOn(); iter; ++iter)
852 acc.
setValue(iter.getCoord(), *iter);
858 template<
typename Gr
idOrTreeT>
863 using TreeT =
typename Adapter::TreeType;
864 using ValueOnCIterT =
typename TreeT::ValueOnCIter;
867 Adapter::tree(aTree).topologyUnion(Adapter::tree(bTree));
872 ValueOnCIterT iter = bTree.cbeginValueOn();
873 iter.setMaxDepth(iter.getLeafDepth() - 1);
874 foreach(iter, op,
false);
877 foreach(Adapter::tree(bTree).cbeginLeaf(),
op);
884 template<
typename Gr
idOrTreeT>
886 csgUnion(GridOrTreeT& a, GridOrTreeT& b,
bool prune,
bool pruneCancelledTiles)
889 using TreeT =
typename Adapter::TreeType;
890 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
891 composite::validateLevelSet(aTree,
"A");
892 composite::validateLevelSet(bTree,
"B");
900 template<
typename Gr
idOrTreeT>
905 using TreeT =
typename Adapter::TreeType;
906 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
907 composite::validateLevelSet(aTree,
"A");
908 composite::validateLevelSet(bTree,
"B");
916 template<
typename Gr
idOrTreeT>
921 using TreeT =
typename Adapter::TreeType;
922 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
923 composite::validateLevelSet(aTree,
"A");
924 composite::validateLevelSet(bTree,
"B");
933 template<
typename Gr
idOrTreeT>
934 typename GridOrTreeT::Ptr
938 using TreePtrT =
typename Adapter::TreeType::Ptr;
940 TreePtrT output = composite::doCSGCopy<composite::CSG_UNION>(
941 Adapter::tree(a), Adapter::tree(b));
943 return composite::GridOrTreeConstructor<GridOrTreeT>::construct(a, output);
947 template<
typename Gr
idOrTreeT>
948 typename GridOrTreeT::Ptr
952 using TreePtrT =
typename Adapter::TreeType::Ptr;
954 TreePtrT output = composite::doCSGCopy<composite::CSG_INTERSECTION>(
955 Adapter::tree(a), Adapter::tree(b));
957 return composite::GridOrTreeConstructor<GridOrTreeT>::construct(a, output);
961 template<
typename Gr
idOrTreeT>
962 typename GridOrTreeT::Ptr
966 using TreePtrT =
typename Adapter::TreeType::Ptr;
968 TreePtrT output = composite::doCSGCopy<composite::CSG_DIFFERENCE>(
969 Adapter::tree(a), Adapter::tree(b));
971 return composite::GridOrTreeConstructor<GridOrTreeT>::construct(a, output);
997 template<
typename TreeT,
typename OpT = composite::CopyOp<TreeT> >
1001 composite::doCompActiveLeafVoxels<TreeT, OpT>(srcTree, dstTree,
op);
1010 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 1012 #ifdef OPENVDB_INSTANTIATE_COMPOSITE 1016 #define _FUNCTION(TreeT) \ 1017 void csgUnion(TreeT&, TreeT&, bool, bool) 1021 #define _FUNCTION(TreeT) \ 1022 void csgUnion(Grid<TreeT>&, Grid<TreeT>&, bool, bool) 1026 #define _FUNCTION(TreeT) \ 1027 void csgIntersection(TreeT&, TreeT&, bool, bool) 1031 #define _FUNCTION(TreeT) \ 1032 void csgIntersection(Grid<TreeT>&, Grid<TreeT>&, bool, bool) 1036 #define _FUNCTION(TreeT) \ 1037 void csgDifference(TreeT&, TreeT&, bool, bool) 1041 #define _FUNCTION(TreeT) \ 1042 void csgDifference(Grid<TreeT>&, Grid<TreeT>&, bool, bool) 1046 #define _FUNCTION(TreeT) \ 1047 TreeT::Ptr csgUnionCopy(const TreeT&, const TreeT&) 1051 #define _FUNCTION(TreeT) \ 1052 Grid<TreeT>::Ptr csgUnionCopy(const Grid<TreeT>&, const Grid<TreeT>&) 1056 #define _FUNCTION(TreeT) \ 1057 TreeT::Ptr csgIntersectionCopy(const TreeT&, const TreeT&) 1061 #define _FUNCTION(TreeT) \ 1062 Grid<TreeT>::Ptr csgIntersectionCopy(const Grid<TreeT>&, const Grid<TreeT>&) 1066 #define _FUNCTION(TreeT) \ 1067 TreeT::Ptr csgDifferenceCopy(const TreeT&, const TreeT&) 1071 #define _FUNCTION(TreeT) \ 1072 Grid<TreeT>::Ptr csgDifferenceCopy(const Grid<TreeT>&, const Grid<TreeT>&) 1076 #define _FUNCTION(TreeT) \ 1077 void compMax(TreeT&, TreeT&) 1081 #define _FUNCTION(TreeT) \ 1082 void compMax(Grid<TreeT>&, Grid<TreeT>&) 1086 #define _FUNCTION(TreeT) \ 1087 void compMin(TreeT&, TreeT&) 1091 #define _FUNCTION(TreeT) \ 1092 void compMin(Grid<TreeT>&, Grid<TreeT>&) 1096 #define _FUNCTION(TreeT) \ 1097 void compSum(TreeT&, TreeT&) 1101 #define _FUNCTION(TreeT) \ 1102 void compSum(Grid<TreeT>&, Grid<TreeT>&) 1106 #define _FUNCTION(TreeT) \ 1107 void compDiv(TreeT&, TreeT&) 1111 #define _FUNCTION(TreeT) \ 1112 void compDiv(Grid<TreeT>&, Grid<TreeT>&) 1116 #define _FUNCTION(TreeT) \ 1117 void compReplace(TreeT&, const TreeT&) 1121 #define _FUNCTION(TreeT) \ 1122 void compReplace(Grid<TreeT>&, const Grid<TreeT>&) 1126 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION 1133 #endif // OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED
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:977
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:568
#define OPENVDB_VOLUME_TREE_INSTANTIATE(Function)
Definition: version.h.in:165
The Value Accessor Implementation and API methods. The majoirty of the API matches the API of a compa...
Definition: ValueAccessor.h:68
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Definition: NodeManager.h:37
const AValueType & a() const
Get the A input value.
Definition: Types.h:608
Index32 Index
Definition: Types.h:54
Defined various multi-threaded utility functions for trees.
Definition: Exceptions.h:65
LeafNodeT * touchLeaf(const Coord &xyz)
Returns the leaf node that contains voxel (x, y, z) and if it doesn't exist, create it...
Definition: ValueAccessor.h:715
void split(ContainerT &out, const std::string &in, const char delim)
Definition: Name.h:43
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:128
void clear() override final
Remove all the cached nodes and invalidate the corresponding hash-keys.
Definition: ValueAccessor.h:880
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:1059
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
Tag dispatch class that distinguishes constructors that steal.
Definition: Types.h:687
SharedPtr< Grid > Ptr
Definition: Grid.h:573
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains the voxel coordinate xyz. If no LeafNode exists...
Definition: ValueAccessor.h:838
Definition: Exceptions.h:13
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:729
Functions to efficiently merge grids.
GridType
List of types that are currently supported by NanoVDB.
Definition: NanoVDB.h:219
uint32_t Index32
Definition: Types.h:52
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:455
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)
Definition: version.h.in:162
const BValueType & b() const
Get the B input value.
Definition: Types.h:610
LeafNodeT * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains the voxel coordinate xyz. If no LeafNode exists...
Definition: ValueAccessor.h:836
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:28
CombineArgs & setResult(const AValueType &val)
Set the output value.
Definition: Types.h:618
void setValue(const Coord &xyz, const ValueType &value)
Set a particular value at the given coordinate and mark the coordinate as active. ...
Definition: ValueAccessor.h:550
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218