10 #ifndef OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED
11 #define OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED
23 #include <tbb/blocked_range.h>
24 #include <tbb/parallel_for.h>
25 #include <tbb/parallel_reduce.h>
26 #include <tbb/task_group.h>
27 #include <tbb/task_scheduler_init.h>
29 #include <type_traits>
40 template<
typename Gr
idOrTreeT>
41 inline 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 inline typename GridOrTreeT::Ptr
csgUnionCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
61 template<
typename Gr
idOrTreeT>
62 inline typename GridOrTreeT::Ptr
csgIntersectionCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
66 template<
typename Gr
idOrTreeT>
67 inline typename GridOrTreeT::Ptr
csgDifferenceCopy(
const GridOrTreeT& a,
const GridOrTreeT& b);
71 template<
typename Gr
idOrTreeT>
72 inline void compMax(GridOrTreeT& a, GridOrTreeT& b);
75 template<
typename Gr
idOrTreeT>
76 inline void compMin(GridOrTreeT& a, GridOrTreeT& b);
79 template<
typename Gr
idOrTreeT>
80 inline void compSum(GridOrTreeT& a, GridOrTreeT& b);
83 template<
typename Gr
idOrTreeT>
84 inline void compMul(GridOrTreeT& a, GridOrTreeT& b);
87 template<
typename Gr
idOrTreeT>
88 inline void compDiv(GridOrTreeT& a, GridOrTreeT& b);
91 template<
typename Gr
idOrTreeT>
92 inline 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
129 typename std::enable_if<!std::is_integral<T>::value, T>::type
130 divide(
const T& a,
const T& b) {
return a / b; }
132 template<
typename T>
inline
133 typename std::enable_if<std::is_integral<T>::value, T>::type
137 if (b != zero)
return a / b;
138 if (a == zero)
return 0;
145 inline bool divide(
bool a,
bool ) {
return a; }
150 template<
typename TreeType, CSGOperation Operation>
162 : mSegment(new TreeType(lhs.background()))
170 std::vector<const LeafNodeType*> leafNodes;
173 std::vector<const InternalNodeType*> internalNodes;
174 mLhsTree->getNodes(internalNodes);
176 ProcessInternalNodes op(internalNodes, *mRhsTree, *mSegment, leafNodes);
177 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
180 ProcessLeafNodes op(leafNodes, *mRhsTree, *mSegment);
181 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
188 struct ProcessInternalNodes {
190 ProcessInternalNodes(std::vector<const InternalNodeType*>& lhsNodes,
191 const TreeType& rhsTree, TreeType& outputTree,
192 std::vector<const LeafNodeType*>& outputLeafNodes)
193 : mLhsNodes(lhsNodes.empty() ? nullptr : &lhsNodes.front())
195 , mLocalTree(mRhsTree->background())
196 , mOutputTree(&outputTree)
198 , mOutputLeafNodes(&outputLeafNodes)
202 ProcessInternalNodes(ProcessInternalNodes& other, tbb::split)
203 : mLhsNodes(other.mLhsNodes)
204 , mRhsTree(other.mRhsTree)
205 , mLocalTree(mRhsTree->background())
206 , mOutputTree(&mLocalTree)
208 , mOutputLeafNodes(&mLocalLeafNodes)
212 void join(ProcessInternalNodes& other)
214 mOutputTree->merge(*other.mOutputTree);
215 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
216 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
219 void operator()(
const tbb::blocked_range<size_t>& range)
224 std::vector<const LeafNodeType*> tmpLeafNodes;
226 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
228 const InternalNodeType& lhsNode = *mLhsNodes[n];
229 const Coord& ijk = lhsNode.origin();
230 const InternalNodeType * rhsNode =
231 rhsAcc.template probeConstNode<InternalNodeType>(ijk);
234 lhsNode.getNodes(*mOutputLeafNodes);
237 if (rhsAcc.getValue(ijk) < ValueType(0.0)) {
238 tmpLeafNodes.clear();
239 lhsNode.getNodes(tmpLeafNodes);
240 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
241 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
245 if (!(rhsAcc.getValue(ijk) < ValueType(0.0))) {
246 tmpLeafNodes.clear();
247 lhsNode.getNodes(tmpLeafNodes);
248 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
249 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
257 InternalNodeType
const *
const *
const mLhsNodes;
258 TreeType
const *
const mRhsTree;
260 TreeType *
const mOutputTree;
262 std::vector<const LeafNodeType*> mLocalLeafNodes;
263 std::vector<const LeafNodeType*> *
const mOutputLeafNodes;
266 struct ProcessLeafNodes {
268 ProcessLeafNodes(std::vector<const LeafNodeType*>& lhsNodes,
269 const TreeType& rhsTree, TreeType& output)
270 : mLhsNodes(lhsNodes.empty() ? nullptr : &lhsNodes.front())
272 , mLocalTree(mRhsTree->background())
273 , mOutputTree(&output)
277 ProcessLeafNodes(ProcessLeafNodes& other, tbb::split)
278 : mLhsNodes(other.mLhsNodes)
279 , mRhsTree(other.mRhsTree)
280 , mLocalTree(mRhsTree->background())
281 , mOutputTree(&mLocalTree)
285 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
287 void operator()(
const tbb::blocked_range<size_t>& range)
289 tree::ValueAccessor<const TreeType> rhsAcc(*mRhsTree);
290 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
292 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
294 const LeafNodeType& lhsNode = *mLhsNodes[n];
295 const Coord& ijk = lhsNode.origin();
297 const LeafNodeType* rhsNodePt = rhsAcc.probeConstLeaf(ijk);
301 LeafNodeType* outputNode = outputAcc.touchLeaf(ijk);
302 ValueType * outputData = outputNode->buffer().
data();
303 NodeMaskType& outputMask = outputNode->getValueMask();
305 const ValueType * lhsData = lhsNode.buffer().data();
306 const NodeMaskType& lhsMask = lhsNode.getValueMask();
308 const ValueType * rhsData = rhsNodePt->buffer().data();
309 const NodeMaskType& rhsMask = rhsNodePt->getValueMask();
312 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
313 const bool fromRhs = lhsData[pos] < rhsData[pos];
314 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
315 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
318 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
320 const bool fromRhs = lhsData[pos] < rhsVal;
321 outputData[pos] = fromRhs ? rhsVal : lhsData[pos];
322 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
325 for (
Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
326 const bool fromRhs = lhsData[pos] > rhsData[pos];
327 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
328 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
334 if (rhsAcc.getValue(ijk) < ValueType(0.0)) {
335 outputAcc.addLeaf(
new LeafNodeType(lhsNode));
338 if (!(rhsAcc.getValue(ijk) < ValueType(0.0))) {
339 outputAcc.addLeaf(
new LeafNodeType(lhsNode));
346 LeafNodeType
const *
const *
const mLhsNodes;
347 TreeType
const *
const mRhsTree;
349 TreeType *
const mOutputTree;
352 TreePtrType mSegment;
353 TreeType
const *
const mLhsTree;
354 TreeType
const *
const mRhsTree;
358 template<
typename TreeType, CSGOperation Operation>
370 : mSegment(new TreeType(lhs.background()))
378 std::vector<const LeafNodeType*> leafNodes;
381 std::vector<const InternalNodeType*> internalNodes;
382 mRhsTree->getNodes(internalNodes);
384 ProcessInternalNodes op(internalNodes, *mLhsTree, *mSegment, leafNodes);
385 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
388 ProcessLeafNodes op(leafNodes, *mLhsTree, *mSegment);
389 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
396 struct ProcessInternalNodes {
398 ProcessInternalNodes(std::vector<const InternalNodeType*>& rhsNodes,
399 const TreeType& lhsTree, TreeType& outputTree,
400 std::vector<const LeafNodeType*>& outputLeafNodes)
401 : mRhsNodes(rhsNodes.empty() ? nullptr : &rhsNodes.front())
403 , mLocalTree(mLhsTree->background())
404 , mOutputTree(&outputTree)
406 , mOutputLeafNodes(&outputLeafNodes)
410 ProcessInternalNodes(ProcessInternalNodes& other, tbb::split)
411 : mRhsNodes(other.mRhsNodes)
412 , mLhsTree(other.mLhsTree)
413 , mLocalTree(mLhsTree->background())
414 , mOutputTree(&mLocalTree)
416 , mOutputLeafNodes(&mLocalLeafNodes)
420 void join(ProcessInternalNodes& other)
422 mOutputTree->merge(*other.mOutputTree);
423 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
424 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
427 void operator()(
const tbb::blocked_range<size_t>& range)
432 std::vector<const LeafNodeType*> tmpLeafNodes;
434 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
436 const InternalNodeType& rhsNode = *mRhsNodes[n];
437 const Coord& ijk = rhsNode.origin();
438 const InternalNodeType * lhsNode =
439 lhsAcc.template probeConstNode<InternalNodeType>(ijk);
442 rhsNode.getNodes(*mOutputLeafNodes);
445 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
446 tmpLeafNodes.clear();
447 rhsNode.getNodes(tmpLeafNodes);
448 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
449 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
453 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
454 tmpLeafNodes.clear();
455 rhsNode.getNodes(tmpLeafNodes);
456 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
457 LeafNodeType* outputNode =
new LeafNodeType(*tmpLeafNodes[i]);
458 outputNode->negate();
459 outputAcc.addLeaf(outputNode);
463 if (!(lhsAcc.getValue(ijk) < ValueType(0.0))) {
464 tmpLeafNodes.clear();
465 rhsNode.getNodes(tmpLeafNodes);
466 for (
size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
467 outputAcc.addLeaf(
new LeafNodeType(*tmpLeafNodes[i]));
475 InternalNodeType
const *
const *
const mRhsNodes;
476 TreeType
const *
const mLhsTree;
478 TreeType *
const mOutputTree;
480 std::vector<const LeafNodeType*> mLocalLeafNodes;
481 std::vector<const LeafNodeType*> *
const mOutputLeafNodes;
484 struct ProcessLeafNodes {
486 ProcessLeafNodes(std::vector<const LeafNodeType*>& rhsNodes,
487 const TreeType& lhsTree, TreeType& output)
488 : mRhsNodes(rhsNodes.empty() ? nullptr : &rhsNodes.front())
490 , mLocalTree(mLhsTree->background())
491 , mOutputTree(&output)
495 ProcessLeafNodes(ProcessLeafNodes& rhs, tbb::split)
496 : mRhsNodes(rhs.mRhsNodes)
497 , mLhsTree(rhs.mLhsTree)
498 , mLocalTree(mLhsTree->background())
499 , mOutputTree(&mLocalTree)
503 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
505 void operator()(
const tbb::blocked_range<size_t>& range)
507 tree::ValueAccessor<const TreeType> lhsAcc(*mLhsTree);
508 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
510 for (
size_t n = range.begin(), N = range.end(); n < N; ++n) {
512 const LeafNodeType& rhsNode = *mRhsNodes[n];
513 const Coord& ijk = rhsNode.origin();
515 const LeafNodeType* lhsNode = lhsAcc.probeConstLeaf(ijk);
519 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
520 outputAcc.addLeaf(
new LeafNodeType(rhsNode));
523 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
524 LeafNodeType* outputNode =
new LeafNodeType(rhsNode);
525 outputNode->negate();
526 outputAcc.addLeaf(outputNode);
529 if (!(lhsAcc.getValue(ijk) < ValueType(0.0))) {
530 outputAcc.addLeaf(
new LeafNodeType(rhsNode));
537 LeafNodeType
const *
const *
const mRhsNodes;
538 TreeType
const *
const mLhsTree;
540 TreeType *
const mOutputTree;
543 TreePtrType mSegment;
544 TreeType
const *
const mLhsTree;
545 TreeType
const *
const mRhsTree;
549 template<CSGOperation Operation,
typename TreeType>
550 inline typename TreeType::Ptr
557 tbb::task_group tasks;
559 tasks.run(secondary);
574 template<
typename TreeType>
582 template<
typename TreeType>
592 maskGrid->insertMeta(grid);
602 template <
typename LeafT>
603 using LeafPairList = std::vector<std::pair<LeafT*, LeafT*>>;
611 template <
typename TreeT>
612 inline void transferLeafNodes(TreeT &srcTree, TreeT &dstTree,
613 LeafPairList<typename TreeT::LeafNodeType> &overlapping)
615 using LeafT =
typename TreeT::LeafNodeType;
617 std::vector<LeafT*> srcLeafNodes;
618 srcLeafNodes.reserve(srcTree.leafCount());
619 srcTree.stealNodes(srcLeafNodes);
621 for (LeafT *srcLeaf : srcLeafNodes) {
622 LeafT *dstLeaf = acc.probeLeaf(srcLeaf->origin());
624 overlapping.emplace_back(dstLeaf, srcLeaf);
626 acc.addLeaf(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);
662 template <
typename TreeT,
typename OpT>
664 typename std::enable_if<
665 std::is_same<typename TreeT::BuildType, ValueMask>::value &&
666 std::is_same<typename TreeT::ValueType, bool>::value>::type
667 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT)
669 using LeafT =
typename TreeT::LeafNodeType;
670 LeafPairList<LeafT> overlapping;
671 transferLeafNodes(srcTree, dstTree, overlapping);
673 using RangeT = tbb::blocked_range<size_t>;
674 tbb::parallel_for(RangeT(0, overlapping.size()), [&overlapping](
const RangeT& r) {
675 for (auto i = r.begin(); i != r.end(); ++i) {
676 overlapping[i].first->getValueMask() |= overlapping[i].second->getValueMask();
677 delete overlapping[i].second;
684 template <
typename TreeT,
typename OpT>
686 typename std::enable_if<
687 std::is_same<typename TreeT::ValueType, bool>::value &&
688 !std::is_same<typename TreeT::BuildType, ValueMask>::value>::type
689 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT op)
691 using LeafT =
typename TreeT::LeafNodeType;
692 LeafPairList<LeafT> overlapping;
693 transferLeafNodes(srcTree, dstTree, overlapping);
695 using RangeT = tbb::blocked_range<size_t>;
696 using WordT =
typename LeafT::Buffer::WordType;
697 tbb::parallel_for(RangeT(0, overlapping.size()), [op, &overlapping](
const RangeT& r) {
698 for (auto i = r.begin(); i != r.end(); ++i) {
699 LeafT *dstLeaf = overlapping[i].first, *srcLeaf = overlapping[i].second;
700 WordT *w1 = dstLeaf->buffer().data();
701 const WordT *w2 = srcLeaf->buffer().data();
702 const WordT *w3 = &(srcLeaf->getValueMask().template getWord<WordT>(0));
703 for (Index32 n = LeafT::Buffer::WORD_COUNT; n--; ++w1) {
704 WordT tmp = *w1, state = *w3++;
706 *w1 = (state & tmp) | (~state & *w1);
708 dstLeaf->getValueMask() |= srcLeaf->getValueMask();
717 template <
typename TreeT>
720 using ValueT =
typename TreeT::ValueType;
722 void operator()(ValueT& dst,
const ValueT& src)
const { dst = src; }
726 template <
typename TreeT>
727 inline void validateLevelSet(
const TreeT& tree,
const std::string& gridName = std::string(
""))
729 using ValueT =
typename TreeT::ValueType;
730 const ValueT zero = zeroVal<ValueT>();
731 if (!(tree.background() > zero)) {
732 std::stringstream ss;
733 ss <<
"expected grid ";
734 if (!gridName.empty()) ss << gridName <<
" ";
735 ss <<
"outside value > 0, got " << tree.background();
738 if (!(-tree.background() < zero)) {
739 std::stringstream ss;
740 ss <<
"expected grid ";
741 if (!gridName.empty()) ss << gridName <<
" ";
742 ss <<
"inside value < 0, got " << -tree.background();
750 template<
typename Gr
idOrTreeT>
752 compMax(GridOrTreeT& aTree, GridOrTreeT& bTree)
755 using TreeT =
typename Adapter::TreeType;
756 using ValueT =
typename TreeT::ValueType;
762 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
766 template<
typename Gr
idOrTreeT>
768 compMin(GridOrTreeT& aTree, GridOrTreeT& bTree)
771 using TreeT =
typename Adapter::TreeType;
772 using ValueT =
typename TreeT::ValueType;
778 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
782 template<
typename Gr
idOrTreeT>
784 compSum(GridOrTreeT& aTree, GridOrTreeT& bTree)
787 using TreeT =
typename Adapter::TreeType;
793 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
797 template<
typename Gr
idOrTreeT>
799 compMul(GridOrTreeT& aTree, GridOrTreeT& bTree)
802 using TreeT =
typename Adapter::TreeType;
808 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
812 template<
typename Gr
idOrTreeT>
814 compDiv(GridOrTreeT& aTree, GridOrTreeT& bTree)
817 using TreeT =
typename Adapter::TreeType;
823 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op,
false);
830 template<
typename TreeT>
838 void operator()(
const typename TreeT::ValueOnCIter& iter)
const
841 iter.getBoundingBox(bbox);
842 aTree->fill(bbox, *iter);
845 void operator()(
const typename TreeT::LeafCIter& leafIter)
const
848 for (
typename TreeT::LeafCIter::LeafNodeT::ValueOnCIter iter =
849 leafIter->cbeginValueOn(); iter; ++iter)
851 acc.
setValue(iter.getCoord(), *iter);
857 template<
typename Gr
idOrTreeT>
862 using TreeT =
typename Adapter::TreeType;
863 using ValueOnCIterT =
typename TreeT::ValueOnCIter;
866 Adapter::tree(aTree).topologyUnion(Adapter::tree(bTree));
871 ValueOnCIterT iter = bTree.cbeginValueOn();
872 iter.setMaxDepth(iter.getLeafDepth() - 1);
873 foreach(iter, op,
false);
876 foreach(Adapter::tree(bTree).cbeginLeaf(), op);
883 template<
typename Gr
idOrTreeT>
888 using TreeT =
typename Adapter::TreeType;
889 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
898 template<
typename Gr
idOrTreeT>
903 using TreeT =
typename Adapter::TreeType;
904 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
913 template<
typename Gr
idOrTreeT>
918 using TreeT =
typename Adapter::TreeType;
919 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
929 template<
typename Gr
idOrTreeT>
930 inline typename GridOrTreeT::Ptr
934 using TreePtrT =
typename Adapter::TreeType::Ptr;
936 TreePtrT output = composite::doCSGCopy<composite::CSG_UNION>(
937 Adapter::tree(a), Adapter::tree(b));
943 template<
typename Gr
idOrTreeT>
944 inline typename GridOrTreeT::Ptr
948 using TreePtrT =
typename Adapter::TreeType::Ptr;
950 TreePtrT output = composite::doCSGCopy<composite::CSG_INTERSECTION>(
951 Adapter::tree(a), Adapter::tree(b));
957 template<
typename Gr
idOrTreeT>
958 inline typename GridOrTreeT::Ptr
962 using TreePtrT =
typename Adapter::TreeType::Ptr;
964 TreePtrT output = composite::doCSGCopy<composite::CSG_DIFFERENCE>(
965 Adapter::tree(a), Adapter::tree(b));
993 template<
typename TreeT,
typename OpT = composite::CopyOp<TreeT> >
997 composite::doCompActiveLeafVoxels<TreeT, OpT>(srcTree, dstTree, op);
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: openvdb/Types.h:429
CombineArgs & setResult(const AValueType &val)
Set the output value.
Definition: openvdb/Types.h:478
const AValueType & a() const
Get the A input value.
Definition: openvdb/Types.h:468
const BValueType & b() const
Get the B input value.
Definition: openvdb/Types.h:470
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition: Grid.h:415
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:577
SharedPtr< Grid > Ptr
Definition: Grid.h:579
Tag dispatch class that distinguishes constructors that steal.
Definition: openvdb/Types.h:546
Definition: openvdb/Exceptions.h:65
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:249
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:26
const Int32 * data() const
Definition: Coord.h:140
Definition: NodeManager.h:858
void foreachTopDown(const NodeOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to all the nodes in the tree.
Definition: NodeManager.h:932
Definition: ValueAccessor.h:183
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
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:127
Index32 Index
Definition: openvdb/Types.h:32
Definition: openvdb/Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition: openvdb/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:1078
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:101
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:153