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>
40template<
typename Gr
idOrTreeT>
41void csgUnion(GridOrTreeT& a, GridOrTreeT& b,
bool prune =
true);
45template<
typename Gr
idOrTreeT>
50template<
typename Gr
idOrTreeT>
56template<
typename Gr
idOrTreeT>
57typename GridOrTreeT::Ptr
csgUnionCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
61template<
typename Gr
idOrTreeT>
66template<
typename Gr
idOrTreeT>
67typename GridOrTreeT::Ptr
csgDifferenceCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
71template<
typename Gr
idOrTreeT>
72void compMax(GridOrTreeT& a, GridOrTreeT& b);
75template<
typename Gr
idOrTreeT>
76void compMin(GridOrTreeT& a, GridOrTreeT& b);
79template<
typename Gr
idOrTreeT>
80void compSum(GridOrTreeT& a, GridOrTreeT& b);
83template<
typename Gr
idOrTreeT>
84void compMul(GridOrTreeT& a, GridOrTreeT& b);
87template<
typename Gr
idOrTreeT>
88void compDiv(GridOrTreeT& a, GridOrTreeT& b);
91template<
typename Gr
idOrTreeT>
92void compReplace(GridOrTreeT& a,
const GridOrTreeT& b);
101template<
typename T>
inline
102const typename std::enable_if<!VecTraits<T>::IsVec, T>::type&
105template<
typename T>
inline
106const typename std::enable_if<!VecTraits<T>::IsVec, T>::type&
111template<
typename T>
inline
112const typename std::enable_if<VecTraits<T>::IsVec, T>::type&
113min(
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)));
119template<
typename T>
inline
120const typename std::enable_if<VecTraits<T>::IsVec, T>::type&
121max(
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)));
128template<
typename T>
inline
130divide(
const T& a,
const T& b) {
return a / b; }
132template<
typename T>
inline
137 if (b != zero)
return a / b;
138 if (a == zero)
return 0;
145inline bool divide(
bool a,
bool ) {
return a; }
150enum CSGOperation { CSG_UNION, CSG_INTERSECTION, CSG_DIFFERENCE };
152template<
typename TreeType, CSGOperation Operation>
153struct 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)
223 tree::ValueAccessor<const TreeType> rhsAcc(*mRhsTree);
224 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
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)
291 tree::ValueAccessor<const TreeType> rhsAcc(*mRhsTree);
292 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
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();
299 const LeafNodeType* rhsNodePt = rhsAcc.probeConstLeaf(ijk);
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;
360template<
typename TreeType, CSGOperation Operation>
361struct 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)
431 tree::ValueAccessor<const TreeType> lhsAcc(*mLhsTree);
432 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
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();
461 outputAcc.addLeaf(outputNode);
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)
509 tree::ValueAccessor<const TreeType> lhsAcc(*mLhsTree);
510 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
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();
517 const LeafNodeType* lhsNode = lhsAcc.probeConstLeaf(ijk);
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();
528 outputAcc.addLeaf(outputNode);
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;
551template<CSGOperation Operation,
typename TreeType>
552typename TreeType::Ptr
553doCSGCopy(
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();
576template<
typename TreeType>
577struct GridOrTreeConstructor
579 using TreeTypePtr =
typename TreeType::Ptr;
580 static TreeTypePtr construct(
const TreeType&, TreeTypePtr& tree) {
return tree; }
584template<
typename TreeType>
585struct 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);
603template <
typename LeafT>
604using LeafPairList = std::vector<std::pair<LeafT*, LeafT*>>;
610template <
typename TreeT>
611void transferLeafNodes(TreeT &srcTree, TreeT &dstTree,
612 LeafPairList<typename TreeT::LeafNodeType> &overlapping)
614 using LeafT =
typename TreeT::LeafNodeType;
615 tree::ValueAccessor<TreeT> acc(dstTree);
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);
625 acc.addLeaf(srcLeaf);
631template <
typename TreeT,
typename OpT>
633typename std::enable_if<
636 std::is_same<
typename TreeT::LeafNodeType::Buffer::ValueType,
637 typename TreeT::LeafNodeType::Buffer::StorageType>
::value>::type
638doCompActiveLeafVoxels(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);
657template <
typename TreeT,
typename OpT>
659typename std::enable_if<
662doCompActiveLeafVoxels(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;
678template <
typename TreeT,
typename OpT>
680typename std::enable_if<
683doCompActiveLeafVoxels(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();
709template <
typename TreeT>
712 using ValueT =
typename TreeT::ValueType;
714 void operator()(ValueT& dst,
const ValueT& src)
const { dst = src; }
717template <
typename TreeT>
718void 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();
743template<
typename Gr
idOrTreeT>
745compMax(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);
759template<
typename Gr
idOrTreeT>
761compMin(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);
775template<
typename Gr
idOrTreeT>
777compSum(GridOrTreeT& aTree, GridOrTreeT& bTree)
780 using TreeT =
typename Adapter::TreeType;
786 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
790template<
typename Gr
idOrTreeT>
792compMul(GridOrTreeT& aTree, GridOrTreeT& bTree)
795 using TreeT =
typename Adapter::TreeType;
801 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
805template<
typename Gr
idOrTreeT>
807compDiv(GridOrTreeT& aTree, GridOrTreeT& bTree)
810 using TreeT =
typename Adapter::TreeType;
816 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
823template<
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);
850template<
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);
876template<
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");
891template<
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");
906template<
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");
922template<
typename Gr
idOrTreeT>
923typename 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);
936template<
typename Gr
idOrTreeT>
937typename 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);
950template<
typename Gr
idOrTreeT>
951typename 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);
986template<
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>&)
ValueT value
Definition: GridBuilder.h:1287
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Functions to efficiently merge grids.
Defined various multi-threaded utility functions for trees.
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:451
const BValueType & b() const
Get the B input value.
Definition: Types.h:492
const AValueType & a() const
Get the A input value.
Definition: Types.h:490
CombineArgs & setResult(const AValueType &val)
Set the output value.
Definition: Types.h:500
SharedPtr< Grid > Ptr
Definition: Grid.h:579
Tag dispatch class that distinguishes constructors that steal.
Definition: Types.h:568
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:248
Definition: NodeManager.h:890
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
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
GridType
List of types that are currently supported by NanoVDB.
Definition: NanoVDB.h:216
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:127
Index32 Index
Definition: Types.h:54
openvdb::GridBase Grid
Definition: Utils.h:34
Definition: Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:1071
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)
Definition: version.h.in:147
#define OPENVDB_VOLUME_TREE_INSTANTIATE(Function)
Definition: version.h.in:150