OpenVDB 7.0.0

Composite.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 //
9
10 #ifndef OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED
11 #define OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED
12
13 #include <openvdb/Platform.h>
14 #include <openvdb/Exceptions.h>
15 #include <openvdb/Types.h>
16 #include <openvdb/Grid.h>
17 #include <openvdb/math/Math.h> // for isExactlyEqual()
18 #include "ValueTransformer.h" // for transformValues()
19 #include "Prune.h"// for prune
20 #include "SignedFloodFill.h" // for signedFloodFill()
21
22 #include <tbb/blocked_range.h>
23 #include <tbb/parallel_for.h>
24 #include <tbb/parallel_reduce.h>
25 #include <tbb/task_group.h>
26 #include <tbb/task_scheduler_init.h>
27
28 #include <type_traits>
29 #include <functional>
30
31 namespace openvdb {
32 OPENVDB_USE_VERSION_NAMESPACE
33 namespace OPENVDB_VERSION_NAME {
34 namespace tools {
35
39 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
40 inline void csgUnion(GridOrTreeT& a, GridOrTreeT& b, bool prune = true);
44 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
45 inline void csgIntersection(GridOrTreeT& a, GridOrTreeT& b, bool prune = true);
49 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
50 inline void csgDifference(GridOrTreeT& a, GridOrTreeT& b, bool prune = true);
51
55 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
56 inline typename GridOrTreeT::Ptr csgUnionCopy(const GridOrTreeT& a, const GridOrTreeT& b);
60 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
61 inline typename GridOrTreeT::Ptr csgIntersectionCopy(const GridOrTreeT& a, const GridOrTreeT& b);
65 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
66 inline typename GridOrTreeT::Ptr csgDifferenceCopy(const GridOrTreeT& a, const GridOrTreeT& b);
67
70 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
71 inline void compMax(GridOrTreeT& a, GridOrTreeT& b);
74 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
75 inline void compMin(GridOrTreeT& a, GridOrTreeT& b);
78 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
79 inline void compSum(GridOrTreeT& a, GridOrTreeT& b);
82 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
83 inline void compMul(GridOrTreeT& a, GridOrTreeT& b);
86 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
87 inline void compDiv(GridOrTreeT& a, GridOrTreeT& b);
88
90 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
91 inline void compReplace(GridOrTreeT& a, const GridOrTreeT& b);
92
93
95
96
97 namespace composite {
98
99 // composite::min() and composite::max() for non-vector types compare with operator<().
100 template<typename T> inline
101 const typename std::enable_if<!VecTraits<T>::IsVec, T>::type& // = T if T is not a vector type
102 min(const T& a, const T& b) { return std::min(a, b); }
103
104 template<typename T> inline
105 const typename std::enable_if<!VecTraits<T>::IsVec, T>::type&
106 max(const T& a, const T& b) { return std::max(a, b); }
107
108
109 // composite::min() and composite::max() for OpenVDB vector types compare by magnitude.
110 template<typename T> inline
111 const typename std::enable_if<VecTraits<T>::IsVec, T>::type& // = T if T is a vector type
112 min(const T& a, const T& b)
113 {
114 const typename T::ValueType aMag = a.lengthSqr(), bMag = b.lengthSqr();
115 return (aMag < bMag ? a : (bMag < aMag ? b : std::min(a, b)));
116 }
117
118 template<typename T> inline
119 const typename std::enable_if<VecTraits<T>::IsVec, T>::type&
120 max(const T& a, const T& b)
121 {
122 const typename T::ValueType aMag = a.lengthSqr(), bMag = b.lengthSqr();
123 return (aMag < bMag ? b : (bMag < aMag ? a : std::max(a, b)));
124 }
125
126
127 template<typename T> inline
128 typename std::enable_if<!std::is_integral<T>::value, T>::type // = T if T is not an integer type
129 divide(const T& a, const T& b) { return a / b; }
130
131 template<typename T> inline
132 typename std::enable_if<std::is_integral<T>::value, T>::type // = T if T is an integer type
133 divide(const T& a, const T& b)
134 {
135 const T zero(0);
136 if (b != zero) return a / b;
137 if (a == zero) return 0;
138 return (a > 0 ? std::numeric_limits<T>::max() : -std::numeric_limits<T>::max());
139 }
140
141 // If b is true, return a / 1 = a.
142 // If b is false and a is true, return 1 / 0 = inf = MAX_BOOL = 1 = a.
143 // If b is false and a is false, return 0 / 0 = NaN = 0 = a.
144 inline bool divide(bool a, bool /*b*/) { return a; }
145
146
147 enum CSGOperation { CSG_UNION, CSG_INTERSECTION, CSG_DIFFERENCE };
148
149 template<typename TreeType, CSGOperation Operation>
150 struct BuildPrimarySegment
151 {
152 using ValueType = typename TreeType::ValueType;
153 using TreePtrType = typename TreeType::Ptr;
154 using LeafNodeType = typename TreeType::LeafNodeType;
155 using NodeMaskType = typename LeafNodeType::NodeMaskType;
156 using RootNodeType = typename TreeType::RootNodeType;
157 using NodeChainType = typename RootNodeType::NodeChainType;
158 using InternalNodeType = typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type;
159
160 BuildPrimarySegment(const TreeType& lhs, const TreeType& rhs)
161 : mSegment(new TreeType(lhs.background()))
162 , mLhsTree(&lhs)
163 , mRhsTree(&rhs)
164 {
165 }
166
167 void operator()() const
168 {
169 std::vector<const LeafNodeType*> leafNodes;
170
171 {
172 std::vector<const InternalNodeType*> internalNodes;
173 mLhsTree->getNodes(internalNodes);
174
175 ProcessInternalNodes op(internalNodes, *mRhsTree, *mSegment, leafNodes);
176 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
177 }
178
179 ProcessLeafNodes op(leafNodes, *mRhsTree, *mSegment);
180 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
181 }
182
183 TreePtrType& segment() { return mSegment; }
184
185 private:
186
187 struct ProcessInternalNodes {
188
189 ProcessInternalNodes(std::vector<const InternalNodeType*>& lhsNodes,
190 const TreeType& rhsTree, TreeType& outputTree,
191 std::vector<const LeafNodeType*>& outputLeafNodes)
192 : mLhsNodes(lhsNodes.empty() ? nullptr : &lhsNodes.front())
193 , mRhsTree(&rhsTree)
194 , mLocalTree(mRhsTree->background())
195 , mOutputTree(&outputTree)
196 , mLocalLeafNodes()
197 , mOutputLeafNodes(&outputLeafNodes)
198 {
199 }
200
201 ProcessInternalNodes(ProcessInternalNodes& other, tbb::split)
202 : mLhsNodes(other.mLhsNodes)
203 , mRhsTree(other.mRhsTree)
204 , mLocalTree(mRhsTree->background())
205 , mOutputTree(&mLocalTree)
206 , mLocalLeafNodes()
207 , mOutputLeafNodes(&mLocalLeafNodes)
208 {
209 }
210
211 void join(ProcessInternalNodes& other)
212 {
213 mOutputTree->merge(*other.mOutputTree);
214 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
215 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
216 }
217
218 void operator()(const tbb::blocked_range<size_t>& range)
219 {
220 tree::ValueAccessor<const TreeType> rhsAcc(*mRhsTree);
221 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
222
223 std::vector<const LeafNodeType*> tmpLeafNodes;
224
225 for (size_t n = range.begin(), N = range.end(); n < N; ++n) {
226
227 const InternalNodeType& lhsNode = *mLhsNodes[n];
228 const Coord& ijk = lhsNode.origin();
229 const InternalNodeType * rhsNode =
230 rhsAcc.template probeConstNode<InternalNodeType>(ijk);
231
232 if (rhsNode) {
233 lhsNode.getNodes(*mOutputLeafNodes);
234 } else {
235 if (Operation == CSG_INTERSECTION) {
236 if (rhsAcc.getValue(ijk) < ValueType(0.0)) {
237 tmpLeafNodes.clear();
238 lhsNode.getNodes(tmpLeafNodes);
239 for (size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
240 outputAcc.addLeaf(new LeafNodeType(*tmpLeafNodes[i]));
241 }
242 }
243 } else { // Union & Difference
244 if (!(rhsAcc.getValue(ijk) < ValueType(0.0))) {
245 tmpLeafNodes.clear();
246 lhsNode.getNodes(tmpLeafNodes);
247 for (size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
248 outputAcc.addLeaf(new LeafNodeType(*tmpLeafNodes[i]));
249 }
250 }
251 }
252 }
253 } // end range loop
254 }
255
256 InternalNodeType const * const * const mLhsNodes;
257 TreeType const * const mRhsTree;
258 TreeType mLocalTree;
259 TreeType * const mOutputTree;
260
261 std::vector<const LeafNodeType*> mLocalLeafNodes;
262 std::vector<const LeafNodeType*> * const mOutputLeafNodes;
263 }; // struct ProcessInternalNodes
264
265 struct ProcessLeafNodes {
266
267 ProcessLeafNodes(std::vector<const LeafNodeType*>& lhsNodes,
268 const TreeType& rhsTree, TreeType& output)
269 : mLhsNodes(lhsNodes.empty() ? nullptr : &lhsNodes.front())
270 , mRhsTree(&rhsTree)
271 , mLocalTree(mRhsTree->background())
272 , mOutputTree(&output)
273 {
274 }
275
276 ProcessLeafNodes(ProcessLeafNodes& other, tbb::split)
277 : mLhsNodes(other.mLhsNodes)
278 , mRhsTree(other.mRhsTree)
279 , mLocalTree(mRhsTree->background())
280 , mOutputTree(&mLocalTree)
281 {
282 }
283
284 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
285
286 void operator()(const tbb::blocked_range<size_t>& range)
287 {
288 tree::ValueAccessor<const TreeType> rhsAcc(*mRhsTree);
289 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
290
291 for (size_t n = range.begin(), N = range.end(); n < N; ++n) {
292
293 const LeafNodeType& lhsNode = *mLhsNodes[n];
294 const Coord& ijk = lhsNode.origin();
295
296 const LeafNodeType* rhsNodePt = rhsAcc.probeConstLeaf(ijk);
297
298 if (rhsNodePt) { // combine overlapping nodes
299
300 LeafNodeType* outputNode = outputAcc.touchLeaf(ijk);
301 ValueType * outputData = outputNode->buffer().data();
302 NodeMaskType& outputMask = outputNode->getValueMask();
303
304 const ValueType * lhsData = lhsNode.buffer().data();
305 const NodeMaskType& lhsMask = lhsNode.getValueMask();
306
307 const ValueType * rhsData = rhsNodePt->buffer().data();
308 const NodeMaskType& rhsMask = rhsNodePt->getValueMask();
309
310 if (Operation == CSG_INTERSECTION) {
311 for (Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
312 const bool fromRhs = lhsData[pos] < rhsData[pos];
313 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
314 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
315 }
316 } else if (Operation == CSG_DIFFERENCE){
317 for (Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
318 const ValueType rhsVal = math::negative(rhsData[pos]);
319 const bool fromRhs = lhsData[pos] < rhsVal;
320 outputData[pos] = fromRhs ? rhsVal : lhsData[pos];
321 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
322 }
323 } else { // Union
324 for (Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
325 const bool fromRhs = lhsData[pos] > rhsData[pos];
326 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
327 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
328 }
329 }
330
331 } else {
332 if (Operation == CSG_INTERSECTION) {
333 if (rhsAcc.getValue(ijk) < ValueType(0.0)) {
334 outputAcc.addLeaf(new LeafNodeType(lhsNode));
335 }
336 } else { // Union & Difference
337 if (!(rhsAcc.getValue(ijk) < ValueType(0.0))) {
338 outputAcc.addLeaf(new LeafNodeType(lhsNode));
339 }
340 }
341 }
342 } // end range loop
343 }
344
345 LeafNodeType const * const * const mLhsNodes;
346 TreeType const * const mRhsTree;
347 TreeType mLocalTree;
348 TreeType * const mOutputTree;
349 }; // struct ProcessLeafNodes
350
351 TreePtrType mSegment;
352 TreeType const * const mLhsTree;
353 TreeType const * const mRhsTree;
354 }; // struct BuildPrimarySegment
355
356
357 template<typename TreeType, CSGOperation Operation>
358 struct BuildSecondarySegment
359 {
360 using ValueType = typename TreeType::ValueType;
361 using TreePtrType = typename TreeType::Ptr;
362 using LeafNodeType = typename TreeType::LeafNodeType;
363 using NodeMaskType = typename LeafNodeType::NodeMaskType;
364 using RootNodeType = typename TreeType::RootNodeType;
365 using NodeChainType = typename RootNodeType::NodeChainType;
366 using InternalNodeType = typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type;
367
368 BuildSecondarySegment(const TreeType& lhs, const TreeType& rhs)
369 : mSegment(new TreeType(lhs.background()))
370 , mLhsTree(&lhs)
371 , mRhsTree(&rhs)
372 {
373 }
374
375 void operator()() const
376 {
377 std::vector<const LeafNodeType*> leafNodes;
378
379 {
380 std::vector<const InternalNodeType*> internalNodes;
381 mRhsTree->getNodes(internalNodes);
382
383 ProcessInternalNodes op(internalNodes, *mLhsTree, *mSegment, leafNodes);
384 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
385 }
386
387 ProcessLeafNodes op(leafNodes, *mLhsTree, *mSegment);
388 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
389 }
390
391 TreePtrType& segment() { return mSegment; }
392
393 private:
394
395 struct ProcessInternalNodes {
396
397 ProcessInternalNodes(std::vector<const InternalNodeType*>& rhsNodes,
398 const TreeType& lhsTree, TreeType& outputTree,
399 std::vector<const LeafNodeType*>& outputLeafNodes)
400 : mRhsNodes(rhsNodes.empty() ? nullptr : &rhsNodes.front())
401 , mLhsTree(&lhsTree)
402 , mLocalTree(mLhsTree->background())
403 , mOutputTree(&outputTree)
404 , mLocalLeafNodes()
405 , mOutputLeafNodes(&outputLeafNodes)
406 {
407 }
408
409 ProcessInternalNodes(ProcessInternalNodes& other, tbb::split)
410 : mRhsNodes(other.mRhsNodes)
411 , mLhsTree(other.mLhsTree)
412 , mLocalTree(mLhsTree->background())
413 , mOutputTree(&mLocalTree)
414 , mLocalLeafNodes()
415 , mOutputLeafNodes(&mLocalLeafNodes)
416 {
417 }
418
419 void join(ProcessInternalNodes& other)
420 {
421 mOutputTree->merge(*other.mOutputTree);
422 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
423 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
424 }
425
426 void operator()(const tbb::blocked_range<size_t>& range)
427 {
428 tree::ValueAccessor<const TreeType> lhsAcc(*mLhsTree);
429 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
430
431 std::vector<const LeafNodeType*> tmpLeafNodes;
432
433 for (size_t n = range.begin(), N = range.end(); n < N; ++n) {
434
435 const InternalNodeType& rhsNode = *mRhsNodes[n];
436 const Coord& ijk = rhsNode.origin();
437 const InternalNodeType * lhsNode =
438 lhsAcc.template probeConstNode<InternalNodeType>(ijk);
439
440 if (lhsNode) {
441 rhsNode.getNodes(*mOutputLeafNodes);
442 } else {
443 if (Operation == CSG_INTERSECTION) {
444 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
445 tmpLeafNodes.clear();
446 rhsNode.getNodes(tmpLeafNodes);
447 for (size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
448 outputAcc.addLeaf(new LeafNodeType(*tmpLeafNodes[i]));
449 }
450 }
451 } else if (Operation == CSG_DIFFERENCE) {
452 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
453 tmpLeafNodes.clear();
454 rhsNode.getNodes(tmpLeafNodes);
455 for (size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
456 LeafNodeType* outputNode = new LeafNodeType(*tmpLeafNodes[i]);
457 outputNode->negate();
458 outputAcc.addLeaf(outputNode);
459 }
460 }
461 } else { // Union
462 if (!(lhsAcc.getValue(ijk) < ValueType(0.0))) {
463 tmpLeafNodes.clear();
464 rhsNode.getNodes(tmpLeafNodes);
465 for (size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
466 outputAcc.addLeaf(new LeafNodeType(*tmpLeafNodes[i]));
467 }
468 }
469 }
470 }
471 } // end range loop
472 }
473
474 InternalNodeType const * const * const mRhsNodes;
475 TreeType const * const mLhsTree;
476 TreeType mLocalTree;
477 TreeType * const mOutputTree;
478
479 std::vector<const LeafNodeType*> mLocalLeafNodes;
480 std::vector<const LeafNodeType*> * const mOutputLeafNodes;
481 }; // struct ProcessInternalNodes
482
483 struct ProcessLeafNodes {
484
485 ProcessLeafNodes(std::vector<const LeafNodeType*>& rhsNodes,
486 const TreeType& lhsTree, TreeType& output)
487 : mRhsNodes(rhsNodes.empty() ? nullptr : &rhsNodes.front())
488 , mLhsTree(&lhsTree)
489 , mLocalTree(mLhsTree->background())
490 , mOutputTree(&output)
491 {
492 }
493
494 ProcessLeafNodes(ProcessLeafNodes& rhs, tbb::split)
495 : mRhsNodes(rhs.mRhsNodes)
496 , mLhsTree(rhs.mLhsTree)
497 , mLocalTree(mLhsTree->background())
498 , mOutputTree(&mLocalTree)
499 {
500 }
501
502 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
503
504 void operator()(const tbb::blocked_range<size_t>& range)
505 {
506 tree::ValueAccessor<const TreeType> lhsAcc(*mLhsTree);
507 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
508
509 for (size_t n = range.begin(), N = range.end(); n < N; ++n) {
510
511 const LeafNodeType& rhsNode = *mRhsNodes[n];
512 const Coord& ijk = rhsNode.origin();
513
514 const LeafNodeType* lhsNode = lhsAcc.probeConstLeaf(ijk);
515
516 if (!lhsNode) {
517 if (Operation == CSG_INTERSECTION) {
518 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
519 outputAcc.addLeaf(new LeafNodeType(rhsNode));
520 }
521 } else if (Operation == CSG_DIFFERENCE) {
522 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
523 LeafNodeType* outputNode = new LeafNodeType(rhsNode);
524 outputNode->negate();
525 outputAcc.addLeaf(outputNode);
526 }
527 } else { // Union
528 if (!(lhsAcc.getValue(ijk) < ValueType(0.0))) {
529 outputAcc.addLeaf(new LeafNodeType(rhsNode));
530 }
531 }
532 }
533 } // end range loop
534 }
535
536 LeafNodeType const * const * const mRhsNodes;
537 TreeType const * const mLhsTree;
538 TreeType mLocalTree;
539 TreeType * const mOutputTree;
540 }; // struct ProcessLeafNodes
541
542 TreePtrType mSegment;
543 TreeType const * const mLhsTree;
544 TreeType const * const mRhsTree;
545 }; // struct BuildSecondarySegment
546
547
548 template<CSGOperation Operation, typename TreeType>
549 inline typename TreeType::Ptr
550 doCSGCopy(const TreeType& lhs, const TreeType& rhs)
551 {
552 BuildPrimarySegment<TreeType, Operation> primary(lhs, rhs);
553 BuildSecondarySegment<TreeType, Operation> secondary(lhs, rhs);
554
555 // Exploiting nested parallelism
556 tbb::task_group tasks;
557 tasks.run(primary);
558 tasks.run(secondary);
559 tasks.wait();
560
561 primary.segment()->merge(*secondary.segment());
562
563 // The leafnode (level = 0) sign is set in the segment construction.
564 tools::signedFloodFill(*primary.segment(), /*threaded=*/true, /*grainSize=*/1, /*minLevel=*/1);
565
566 return primary.segment();
567 }
568
569
571
572
573 template<typename TreeType>
574 struct GridOrTreeConstructor
575 {
576 using TreeTypePtr = typename TreeType::Ptr;
577 static TreeTypePtr construct(const TreeType&, TreeTypePtr& tree) { return tree; }
578 };
579
580
581 template<typename TreeType>
582 struct GridOrTreeConstructor<Grid<TreeType> >
583 {
584 using GridType = Grid<TreeType>;
585 using GridTypePtr = typename Grid<TreeType>::Ptr;
586 using TreeTypePtr = typename TreeType::Ptr;
587
588 static GridTypePtr construct(const GridType& grid, TreeTypePtr& tree) {
589 GridTypePtr maskGrid(GridType::create(tree));
590 maskGrid->setTransform(grid.transform().copy());
591 maskGrid->insertMeta(grid);
592 return maskGrid;
593 }
594 };
595
596
598
601 template <typename LeafT>
602 using LeafPairList = std::vector<std::pair<LeafT*, LeafT*>>;
604
610 template <typename TreeT>
611 inline void transferLeafNodes(TreeT &srcTree, TreeT &dstTree,
612 LeafPairList<typename TreeT::LeafNodeType> &overlapping)
613 {
614 using LeafT = typename TreeT::LeafNodeType;
615 tree::ValueAccessor<TreeT> acc(dstTree);//destination
616 std::vector<LeafT*> srcLeafNodes;
617 srcLeafNodes.reserve(srcTree.leafCount());
618 srcTree.stealNodes(srcLeafNodes);
619 srcTree.clear();
620 for (LeafT *srcLeaf : srcLeafNodes) {
621 LeafT *dstLeaf = acc.probeLeaf(srcLeaf->origin());
622 if (dstLeaf) {
623 overlapping.emplace_back(dstLeaf, srcLeaf);//dst, src
624 } else {
625 acc.addLeaf(srcLeaf);
626 }
627 }
628 }
630
633 template <typename TreeT, typename OpT>
634 inline
635 typename std::enable_if<
636 !std::is_same<typename TreeT::ValueType, bool>::value &&
637 !std::is_same<typename TreeT::BuildType, ValueMask>::value &&
638 std::is_same<typename TreeT::LeafNodeType::Buffer::ValueType,
639 typename TreeT::LeafNodeType::Buffer::StorageType>::value>::type
640 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT op)
641 {
642 using LeafT = typename TreeT::LeafNodeType;
643 LeafPairList<LeafT> overlapping;//dst, src
644 transferLeafNodes(srcTree, dstTree, overlapping);
645
646 using RangeT = tbb::blocked_range<size_t>;
647 tbb::parallel_for(RangeT(0, overlapping.size()), [op, &overlapping](const RangeT& r) {
648 for (auto i = r.begin(); i != r.end(); ++i) {
649 LeafT *dstLeaf = overlapping[i].first, *srcLeaf = overlapping[i].second;
650 dstLeaf->getValueMask() |= srcLeaf->getValueMask();
651 auto *ptr = dstLeaf->buffer().data();
652 for (auto v = srcLeaf->cbeginValueOn(); v; ++v) op(ptr[v.pos()], *v);
653 delete srcLeaf;
654 }
655 });
656 }
658
661 template <typename TreeT, typename OpT>
662 inline
663 typename std::enable_if<
664 std::is_same<typename TreeT::BuildType, ValueMask>::value &&
665 std::is_same<typename TreeT::ValueType, bool>::value>::type
666 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT)
667 {
668 using LeafT = typename TreeT::LeafNodeType;
669 LeafPairList<LeafT> overlapping;//dst, src
670 transferLeafNodes(srcTree, dstTree, overlapping);
671
672 using RangeT = tbb::blocked_range<size_t>;
673 tbb::parallel_for(RangeT(0, overlapping.size()), [&overlapping](const RangeT& r) {
674 for (auto i = r.begin(); i != r.end(); ++i) {
675 overlapping[i].first->getValueMask() |= overlapping[i].second->getValueMask();
676 delete overlapping[i].second;
677 }
678 });
679 }
680
683 template <typename TreeT, typename OpT>
684 inline
685 typename std::enable_if<
686 std::is_same<typename TreeT::ValueType, bool>::value &&
687 !std::is_same<typename TreeT::BuildType, ValueMask>::value>::type
688 doCompActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT op)
689 {
690 using LeafT = typename TreeT::LeafNodeType;
691 LeafPairList<LeafT> overlapping;//dst, src
692 transferLeafNodes(srcTree, dstTree, overlapping);
693
694 using RangeT = tbb::blocked_range<size_t>;
695 using WordT = typename LeafT::Buffer::WordType;
696 tbb::parallel_for(RangeT(0, overlapping.size()), [op, &overlapping](const RangeT& r) {
697 for (auto i = r.begin(); i != r.end(); ++i) {
698 LeafT *dstLeaf = overlapping[i].first, *srcLeaf = overlapping[i].second;
699 WordT *w1 = dstLeaf->buffer().data();
700 const WordT *w2 = srcLeaf->buffer().data();
701 const WordT *w3 = &(srcLeaf->getValueMask().template getWord<WordT>(0));
702 for (Index32 n = LeafT::Buffer::WORD_COUNT; n--; ++w1) {
703 WordT tmp = *w1, state = *w3++;
704 op (tmp, *w2++);
705 *w1 = (state & tmp) | (~state & *w1);//inactive values are unchanged
706 }
707 dstLeaf->getValueMask() |= srcLeaf->getValueMask();
708 delete srcLeaf;
709 }
710 });
711 }
713
716 template <typename TreeT>
717 struct CopyOp
718 {
719 using ValueT = typename TreeT::ValueType;
720 CopyOp() = default;
721 void operator()(ValueT& dst, const ValueT& src) const { dst = src; }
722 };
724
725 } // namespace composite
726
727
728 template<typename GridOrTreeT>
729 OPENVDB_STATIC_SPECIALIZATION inline void
730 compMax(GridOrTreeT& aTree, GridOrTreeT& bTree)
731 {
732 using Adapter = TreeAdapter<GridOrTreeT>;
733 using TreeT = typename Adapter::TreeType;
734 using ValueT = typename TreeT::ValueType;
735 struct Local {
736 static inline void op(CombineArgs<ValueT>& args) {
737 args.setResult(composite::max(args.a(), args.b()));
738 }
739 };
740 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op, /*prune=*/false);
741 }
742
743
744 template<typename GridOrTreeT>
745 OPENVDB_STATIC_SPECIALIZATION inline void
746 compMin(GridOrTreeT& aTree, GridOrTreeT& bTree)
747 {
748 using Adapter = TreeAdapter<GridOrTreeT>;
749 using TreeT = typename Adapter::TreeType;
750 using ValueT = typename TreeT::ValueType;
751 struct Local {
752 static inline void op(CombineArgs<ValueT>& args) {
753 args.setResult(composite::min(args.a(), args.b()));
754 }
755 };
756 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op, /*prune=*/false);
757 }
758
759
760 template<typename GridOrTreeT>
761 OPENVDB_STATIC_SPECIALIZATION inline void
762 compSum(GridOrTreeT& aTree, GridOrTreeT& bTree)
763 {
764 using Adapter = TreeAdapter<GridOrTreeT>;
765 using TreeT = typename Adapter::TreeType;
766 struct Local {
767 static inline void op(CombineArgs<typename TreeT::ValueType>& args) {
768 args.setResult(args.a() + args.b());
769 }
770 };
771 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op, /*prune=*/false);
772 }
773
774
775 template<typename GridOrTreeT>
776 OPENVDB_STATIC_SPECIALIZATION inline void
777 compMul(GridOrTreeT& aTree, GridOrTreeT& bTree)
778 {
779 using Adapter = TreeAdapter<GridOrTreeT>;
780 using TreeT = typename Adapter::TreeType;
781 struct Local {
782 static inline void op(CombineArgs<typename TreeT::ValueType>& args) {
783 args.setResult(args.a() * args.b());
784 }
785 };
786 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op, /*prune=*/false);
787 }
788
789
790 template<typename GridOrTreeT>
791 OPENVDB_STATIC_SPECIALIZATION inline void
792 compDiv(GridOrTreeT& aTree, GridOrTreeT& bTree)
793 {
794 using Adapter = TreeAdapter<GridOrTreeT>;
795 using TreeT = typename Adapter::TreeType;
796 struct Local {
797 static inline void op(CombineArgs<typename TreeT::ValueType>& args) {
798 args.setResult(composite::divide(args.a(), args.b()));
799 }
800 };
801 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op, /*prune=*/false);
802 }
803
804
806
807
808 template<typename TreeT>
809 struct CompReplaceOp
810 {
811 TreeT* const aTree;
812
813 CompReplaceOp(TreeT& _aTree): aTree(&_aTree) {}
814
816 void operator()(const typename TreeT::ValueOnCIter& iter) const
817 {
818 CoordBBox bbox;
819 iter.getBoundingBox(bbox);
820 aTree->fill(bbox, *iter);
821 }
822
823 void operator()(const typename TreeT::LeafCIter& leafIter) const
824 {
825 tree::ValueAccessor<TreeT> acc(*aTree);
826 for (typename TreeT::LeafCIter::LeafNodeT::ValueOnCIter iter =
827 leafIter->cbeginValueOn(); iter; ++iter)
828 {
829 acc.setValue(iter.getCoord(), *iter);
830 }
831 }
832 };
833
834
835 template<typename GridOrTreeT>
836 OPENVDB_STATIC_SPECIALIZATION inline void
837 compReplace(GridOrTreeT& aTree, const GridOrTreeT& bTree)
838 {
839 using Adapter = TreeAdapter<GridOrTreeT>;
840 using TreeT = typename Adapter::TreeType;
841 using ValueOnCIterT = typename TreeT::ValueOnCIter;
842
843 // Copy active states (but not values) from B to A.
844 Adapter::tree(aTree).topologyUnion(Adapter::tree(bTree));
845
846 CompReplaceOp<TreeT> op(Adapter::tree(aTree));
847
848 // Copy all active tile values from B to A.
849 ValueOnCIterT iter = bTree.cbeginValueOn();
850 iter.setMaxDepth(iter.getLeafDepth() - 1); // don't descend into leaf nodes
851 foreach(iter, op, /*threaded=*/false);
852
853 // Copy all active voxel values from B to A.
854 foreach(Adapter::tree(bTree).cbeginLeaf(), op);
855 }
856
857
859
860
863 template<typename TreeType>
864 class CsgVisitorBase
865 {
866 public:
867 using TreeT = TreeType;
868 using ValueT = typename TreeT::ValueType;
869 using ChildIterT = typename TreeT::LeafNodeType::ChildAllIter;
870
871 enum { STOP = 3 };
872
873 CsgVisitorBase(const TreeT& aTree, const TreeT& bTree):
874 mAOutside(aTree.background()),
875 mAInside(math::negative(mAOutside)),
876 mBOutside(bTree.background()),
877 mBInside(math::negative(mBOutside))
878 {
879 const ValueT zero = zeroVal<ValueT>();
880 if (!(mAOutside > zero)) {
881 OPENVDB_THROW(ValueError,
882 "expected grid A outside value > 0, got " << mAOutside);
883 }
884 if (!(mAInside < zero)) {
885 OPENVDB_THROW(ValueError,
886 "expected grid A inside value < 0, got " << mAInside);
887 }
888 if (!(mBOutside > zero)) {
889 OPENVDB_THROW(ValueError,
890 "expected grid B outside value > 0, got " << mBOutside);
891 }
892 if (!(mBInside < zero)) {
893 OPENVDB_THROW(ValueError,
894 "expected grid B outside value < 0, got " << mBOutside);
895 }
896 }
897
898 protected:
899 ValueT mAOutside, mAInside, mBOutside, mBInside;
900 };
901
902
904
905
906 template<typename TreeType>
907 struct CsgUnionVisitor: public CsgVisitorBase<TreeType>
908 {
909 using TreeT = TreeType;
910 using ValueT = typename TreeT::ValueType;
911 using ChildIterT = typename TreeT::LeafNodeType::ChildAllIter;
912
913 enum { STOP = CsgVisitorBase<TreeT>::STOP };
914
915 CsgUnionVisitor(const TreeT& a, const TreeT& b): CsgVisitorBase<TreeT>(a, b) {}
916
918 template<typename AIterT, typename BIterT>
919 inline int operator()(AIterT&, BIterT&) { return 0; }
920
922 template<typename IterT>
923 inline int operator()(IterT& aIter, IterT& bIter)
924 {
925 ValueT aValue = zeroVal<ValueT>();
926 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
927 if (!aChild && aValue < zeroVal<ValueT>()) {
928 // A is an inside tile. Leave it alone and stop traversing this branch.
929 return STOP;
930 }
931
932 ValueT bValue = zeroVal<ValueT>();
933 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
934 if (!bChild && bValue < zeroVal<ValueT>()) {
935 // B is an inside tile. Make A an inside tile and stop traversing this branch.
936 aIter.setValue(this->mAInside);
937 aIter.setValueOn(bIter.isValueOn());
938 delete aChild;
939 return STOP;
940 }
941
942 if (!aChild && aValue > zeroVal<ValueT>()) {
943 // A is an outside tile. If B has a child, transfer it to A,
944 // otherwise leave A alone.
945 if (bChild) {
946 bIter.setValue(this->mBOutside);
947 bIter.setValueOff();
948 bChild->resetBackground(this->mBOutside, this->mAOutside);
949 aIter.setChild(bChild); // transfer child
950 delete aChild;
951 }
952 return STOP;
953 }
954
955 // If A has a child and B is an outside tile, stop traversing this branch.
956 // Continue traversal only if A and B both have children.
957 return (aChild && bChild) ? 0 : STOP;
958 }
959
961 inline int operator()(ChildIterT& aIter, ChildIterT& bIter)
962 {
963 ValueT aValue, bValue;
964 aIter.probeValue(aValue);
965 bIter.probeValue(bValue);
966 if (aValue > bValue) { // a = min(a, b)
967 aIter.setValue(bValue);
968 aIter.setValueOn(bIter.isValueOn());
969 }
970 return 0;
971 }
972 };
973
974
975
977
978
979 template<typename TreeType>
980 struct CsgIntersectVisitor: public CsgVisitorBase<TreeType>
981 {
982 using TreeT = TreeType;
983 using ValueT = typename TreeT::ValueType;
984 using ChildIterT = typename TreeT::LeafNodeType::ChildAllIter;
985
986 enum { STOP = CsgVisitorBase<TreeT>::STOP };
987
988 CsgIntersectVisitor(const TreeT& a, const TreeT& b): CsgVisitorBase<TreeT>(a, b) {}
989
991 template<typename AIterT, typename BIterT>
992 inline int operator()(AIterT&, BIterT&) { return 0; }
993
995 template<typename IterT>
996 inline int operator()(IterT& aIter, IterT& bIter)
997 {
998 ValueT aValue = zeroVal<ValueT>();
999 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
1000 if (!aChild && !(aValue < zeroVal<ValueT>())) {
1001 // A is an outside tile. Leave it alone and stop traversing this branch.
1002 return STOP;
1003 }
1004
1005 ValueT bValue = zeroVal<ValueT>();
1006 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
1007 if (!bChild && !(bValue < zeroVal<ValueT>())) {
1008 // B is an outside tile. Make A an outside tile and stop traversing this branch.
1009 aIter.setValue(this->mAOutside);
1010 aIter.setValueOn(bIter.isValueOn());
1011 delete aChild;
1012 return STOP;
1013 }
1014
1015 if (!aChild && aValue < zeroVal<ValueT>()) {
1016 // A is an inside tile. If B has a child, transfer it to A,
1017 // otherwise leave A alone.
1018 if (bChild) {
1019 bIter.setValue(this->mBOutside);
1020 bIter.setValueOff();
1021 bChild->resetBackground(this->mBOutside, this->mAOutside);
1022 aIter.setChild(bChild); // transfer child
1023 delete aChild;
1024 }
1025 return STOP;
1026 }
1027
1028 // If A has a child and B is an outside tile, stop traversing this branch.
1029 // Continue traversal only if A and B both have children.
1030 return (aChild && bChild) ? 0 : STOP;
1031 }
1032
1034 inline int operator()(ChildIterT& aIter, ChildIterT& bIter)
1035 {
1036 ValueT aValue, bValue;
1037 aIter.probeValue(aValue);
1038 bIter.probeValue(bValue);
1039 if (aValue < bValue) { // a = max(a, b)
1040 aIter.setValue(bValue);
1041 aIter.setValueOn(bIter.isValueOn());
1042 }
1043 return 0;
1044 }
1045 };
1046
1047
1049
1050
1051 template<typename TreeType>
1052 struct CsgDiffVisitor: public CsgVisitorBase<TreeType>
1053 {
1054 using TreeT = TreeType;
1055 using ValueT = typename TreeT::ValueType;
1056 using ChildIterT = typename TreeT::LeafNodeType::ChildAllIter;
1057
1058 enum { STOP = CsgVisitorBase<TreeT>::STOP };
1059
1060 CsgDiffVisitor(const TreeT& a, const TreeT& b): CsgVisitorBase<TreeT>(a, b) {}
1061
1063 template<typename AIterT, typename BIterT>
1064 inline int operator()(AIterT&, BIterT&) { return 0; }
1065
1067 template<typename IterT>
1068 inline int operator()(IterT& aIter, IterT& bIter)
1069 {
1070 ValueT aValue = zeroVal<ValueT>();
1071 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
1072 if (!aChild && !(aValue < zeroVal<ValueT>())) {
1073 // A is an outside tile. Leave it alone and stop traversing this branch.
1074 return STOP;
1075 }
1076
1077 ValueT bValue = zeroVal<ValueT>();
1078 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
1079 if (!bChild && bValue < zeroVal<ValueT>()) {
1080 // B is an inside tile. Make A an inside tile and stop traversing this branch.
1081 aIter.setValue(this->mAOutside);
1082 aIter.setValueOn(bIter.isValueOn());
1083 delete aChild;
1084 return STOP;
1085 }
1086
1087 if (!aChild && aValue < zeroVal<ValueT>()) {
1088 // A is an inside tile. If B has a child, transfer it to A,
1089 // otherwise leave A alone.
1090 if (bChild) {
1091 bIter.setValue(this->mBOutside);
1092 bIter.setValueOff();
1093 bChild->resetBackground(this->mBOutside, this->mAOutside);
1094 aIter.setChild(bChild); // transfer child
1095 bChild->negate();
1096 delete aChild;
1097 }
1098 return STOP;
1099 }
1100
1101 // If A has a child and B is an outside tile, stop traversing this branch.
1102 // Continue traversal only if A and B both have children.
1103 return (aChild && bChild) ? 0 : STOP;
1104 }
1105
1107 inline int operator()(ChildIterT& aIter, ChildIterT& bIter)
1108 {
1109 ValueT aValue, bValue;
1110 aIter.probeValue(aValue);
1111 bIter.probeValue(bValue);
1112 bValue = math::negative(bValue);
1113 if (aValue < bValue) { // a = max(a, -b)
1114 aIter.setValue(bValue);
1115 aIter.setValueOn(bIter.isValueOn());
1116 }
1117 return 0;
1118 }
1119 };
1120
1121
1123
1124
1125 template<typename GridOrTreeT>
1126 OPENVDB_STATIC_SPECIALIZATION inline void
1127 csgUnion(GridOrTreeT& a, GridOrTreeT& b, bool prune)
1128 {
1129 using Adapter = TreeAdapter<GridOrTreeT>;
1130 using TreeT = typename Adapter::TreeType;
1131 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1132 CsgUnionVisitor<TreeT> visitor(aTree, bTree);
1133 aTree.visit2(bTree, visitor);
1134 if (prune) tools::pruneLevelSet(aTree);
1135 }
1136
1137 template<typename GridOrTreeT>
1138 OPENVDB_STATIC_SPECIALIZATION inline void
1139 csgIntersection(GridOrTreeT& a, GridOrTreeT& b, bool prune)
1140 {
1141 using Adapter = TreeAdapter<GridOrTreeT>;
1142 using TreeT = typename Adapter::TreeType;
1143 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1144 CsgIntersectVisitor<TreeT> visitor(aTree, bTree);
1145 aTree.visit2(bTree, visitor);
1146 if (prune) tools::pruneLevelSet(aTree);
1147 }
1148
1149 template<typename GridOrTreeT>
1150 OPENVDB_STATIC_SPECIALIZATION inline void
1151 csgDifference(GridOrTreeT& a, GridOrTreeT& b, bool prune)
1152 {
1153 using Adapter = TreeAdapter<GridOrTreeT>;
1154 using TreeT = typename Adapter::TreeType;
1155 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1156 CsgDiffVisitor<TreeT> visitor(aTree, bTree);
1157 aTree.visit2(bTree, visitor);
1158 if (prune) tools::pruneLevelSet(aTree);
1159 }
1160
1161
1162 template<typename GridOrTreeT>
1163 OPENVDB_STATIC_SPECIALIZATION inline typename GridOrTreeT::Ptr
1164 csgUnionCopy(const GridOrTreeT& a, const GridOrTreeT& b)
1165 {
1166 using Adapter = TreeAdapter<GridOrTreeT>;
1167 using TreePtrT = typename Adapter::TreeType::Ptr;
1168
1169 TreePtrT output = composite::doCSGCopy<composite::CSG_UNION>(
1170 Adapter::tree(a), Adapter::tree(b));
1171
1172 return composite::GridOrTreeConstructor<GridOrTreeT>::construct(a, output);
1173 }
1174
1175
1176 template<typename GridOrTreeT>
1177 OPENVDB_STATIC_SPECIALIZATION inline typename GridOrTreeT::Ptr
1178 csgIntersectionCopy(const GridOrTreeT& a, const GridOrTreeT& b)
1179 {
1180 using Adapter = TreeAdapter<GridOrTreeT>;
1181 using TreePtrT = typename Adapter::TreeType::Ptr;
1182
1183 TreePtrT output = composite::doCSGCopy<composite::CSG_INTERSECTION>(
1184 Adapter::tree(a), Adapter::tree(b));
1185
1186 return composite::GridOrTreeConstructor<GridOrTreeT>::construct(a, output);
1187 }
1188
1189
1190 template<typename GridOrTreeT>
1191 OPENVDB_STATIC_SPECIALIZATION inline typename GridOrTreeT::Ptr
1192 csgDifferenceCopy(const GridOrTreeT& a, const GridOrTreeT& b)
1193 {
1194 using Adapter = TreeAdapter<GridOrTreeT>;
1195 using TreePtrT = typename Adapter::TreeType::Ptr;
1196
1197 TreePtrT output = composite::doCSGCopy<composite::CSG_DIFFERENCE>(
1198 Adapter::tree(a), Adapter::tree(b));
1199
1200 return composite::GridOrTreeConstructor<GridOrTreeT>::construct(a, output);
1201 }
1202
1204
1226 template<typename TreeT, typename OpT = composite::CopyOp<TreeT> >
1227 inline void
1228 compActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT op = composite::CopyOp<TreeT>())
1229 {
1230 composite::doCompActiveLeafVoxels<TreeT, OpT>(srcTree, dstTree, op);
1231 }
1232
1233
1234 } // namespace tools
1235 } // namespace OPENVDB_VERSION_NAME
1236 } // namespace openvdb
1237
1238 #endif // OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED
openvdb::v7_0::tools::composite::GridOrTreeConstructor< Grid< TreeType > >::TreeTypePtr
typename TreeType::Ptr TreeTypePtr
Definition: Composite.h:586
openvdb::v7_0::tools::composite::BuildPrimarySegment::ValueType
typename TreeType::ValueType ValueType
Definition: Composite.h:152
openvdb::v7_0::tools::composite::CSG_DIFFERENCE
Definition: Composite.h:147
openvdb::v7_0::tools::CsgVisitorBase::mBOutside
ValueT mBOutside
Definition: Composite.h:899
openvdb::v7_0::tools::CsgIntersectVisitor
Definition: Composite.h:980
openvdb::v7_0::tools::composite::min
const std::enable_if< VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:112
openvdb::v7_0::tools::composite::GridOrTreeConstructor::construct
static TreeTypePtr construct(const TreeType &, TreeTypePtr &tree)
Definition: Composite.h:577
openvdb::v7_0::tools::csgUnionCopy
GridOrTreeT::Ptr csgUnionCopy(const GridOrTreeT &a, const GridOrTreeT &b)
Threaded CSG union operation that produces a new grid or tree from immutable inputs.
Definition: Composite.h:1164
openvdb::v7_0::tools::composite::BuildPrimarySegment::operator()
void operator()() const
Definition: Composite.h:167
OPENVDB_STATIC_SPECIALIZATION
#define OPENVDB_STATIC_SPECIALIZATION
Definition: Platform.h:62
openvdb::v7_0::tools::composite::BuildPrimarySegment::NodeChainType
typename RootNodeType::NodeChainType NodeChainType
Definition: Composite.h:157
openvdb::v7_0::tools::composite::BuildSecondarySegment::TreePtrType
typename TreeType::Ptr TreePtrType
Definition: Composite.h:361
openvdb::v7_0::tools::CompReplaceOp
Definition: Composite.h:809
openvdb::v7_0::tools::csgIntersectionCopy
GridOrTreeT::Ptr csgIntersectionCopy(const GridOrTreeT &a, const GridOrTreeT &b)
Threaded CSG intersection operation that produces a new grid or tree from immutable inputs.
Definition: Composite.h:1178
Types.h
openvdb::v7_0::tools::CsgVisitorBase::ChildIterT
typename TreeT::LeafNodeType::ChildAllIter ChildIterT
Definition: Composite.h:869
openvdb::v7_0::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:25
openvdb::v7_0::tools::composite::GridOrTreeConstructor< Grid< TreeType > >::construct
static GridTypePtr construct(const GridType &grid, TreeTypePtr &tree)
Definition: Composite.h:588
openvdb::v7_0::tools::composite::BuildPrimarySegment::BuildPrimarySegment
BuildPrimarySegment(const TreeType &lhs, const TreeType &rhs)
Definition: Composite.h:160
openvdb::v7_0::tools::CsgDiffVisitor::CsgDiffVisitor
CsgDiffVisitor(const TreeT &a, const TreeT &b)
Definition: Composite.h:1060
openvdb::v7_0::tools::compDiv
void compDiv(GridOrTreeT &a, GridOrTreeT &b)
Given grids A and B, compute a / b per voxel (using sparse traversal). Store the result in the A grid...
Definition: Composite.h:792
openvdb::v7_0::tree::ValueAccessor< const TreeType >
openvdb::v7_0::Grid::Ptr
SharedPtr< Grid > Ptr
Definition: Grid.h:574
openvdb::v7_0::tools::composite::max
const std::enable_if< VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:120
openvdb::v7_0::tools::CsgIntersectVisitor::operator()
int operator()(ChildIterT &aIter, ChildIterT &bIter)
Process leaf node values.
Definition: Composite.h:1034
openvdb::v7_0::tools::composite::BuildSecondarySegment::NodeChainType
typename RootNodeType::NodeChainType NodeChainType
Definition: Composite.h:365
openvdb::v7_0::tools::compMul
void compMul(GridOrTreeT &a, GridOrTreeT &b)
Given grids A and B, compute a * b per voxel (using sparse traversal). Store the result in the A grid...
Definition: Composite.h:777
openvdb::v7_0::tools::csgUnion
void csgUnion(GridOrTreeT &a, GridOrTreeT &b, bool prune=true)
Given two level set grids, replace the A grid with the union of A and B.
Definition: Composite.h:1127
openvdb::v7_0::tree::ValueAccessor::setValue
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:261
openvdb::v7_0::tools::csgIntersection
void csgIntersection(GridOrTreeT &a, GridOrTreeT &b, bool prune=true)
Given two level set grids, replace the A grid with the intersection of A and B.
Definition: Composite.h:1139
openvdb::v7_0::tools::composite::BuildSecondarySegment::ValueType
typename TreeType::ValueType ValueType
Definition: Composite.h:360
openvdb::v7_0::tools::CsgUnionVisitor::operator()
int operator()(AIterT &, BIterT &)
Don't process nodes that are at different tree levels.
Definition: Composite.h:919
openvdb::v7_0::tools::composite::BuildPrimarySegment::RootNodeType
typename TreeType::RootNodeType RootNodeType
Definition: Composite.h:156
openvdb::v7_0::tools::composite::BuildPrimarySegment::segment
TreePtrType & segment()
Definition: Composite.h:183
openvdb::v7_0::GridBase::transform
math::Transform & transform()
Return a reference to this grid's transform, which might be shared with other grids.
Definition: Grid.h:410
openvdb::v7_0::tools::CompReplaceOp::aTree
TreeT *const aTree
Definition: Composite.h:811
openvdb::v7_0::tools::composite::CSGOperation
CSGOperation
Definition: Composite.h:147
openvdb::v7_0::math::negative
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:81
openvdb::v7_0::tools::composite::BuildSecondarySegment::operator()
void operator()() const
Definition: Composite.h:375
openvdb::v7_0::tools::compMin
void compMin(GridOrTreeT &a, GridOrTreeT &b)
Given grids A and B, compute min(a, b) per voxel (using sparse traversal). Store the result in the A ...
Definition: Composite.h:746
Platform.h
Grid.h
openvdb::v7_0::CombineArgs::a
const AValueType & a() const
Get the A input value.
Definition: Types.h:607
openvdb::v7_0::tools::CsgIntersectVisitor::CsgIntersectVisitor
CsgIntersectVisitor(const TreeT &a, const TreeT &b)
Definition: Composite.h:988
openvdb::v7_0::math::CoordBBox
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:248
openvdb::v7_0::Grid
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:28
openvdb::v7_0::tools::composite::CSG_UNION
Definition: Composite.h:147
openvdb::v7_0::tools::composite::BuildPrimarySegment::NodeMaskType
typename LeafNodeType::NodeMaskType NodeMaskType
Definition: Composite.h:155
openvdb::v7_0::tools::CompReplaceOp::CompReplaceOp
CompReplaceOp(TreeT &_aTree)
Definition: Composite.h:813
openvdb::v7_0::tools::composite::BuildSecondarySegment::NodeMaskType
typename LeafNodeType::NodeMaskType NodeMaskType
Definition: Composite.h:363
openvdb::v7_0::tools::compReplace
void compReplace(GridOrTreeT &a, const GridOrTreeT &b)
Copy the active voxels of B into A.
Definition: Composite.h:837
openvdb::v7_0::tools::compActiveLeafVoxels
void compActiveLeafVoxels(TreeT &srcTree, TreeT &dstTree, OpT op=composite::CopyOp< TreeT >())
Composite the active values in leaf nodes, i.e. active voxels, of a source tree into a destination tr...
Definition: Composite.h:1228
openvdb::v7_0::tools::csgDifferenceCopy
GridOrTreeT::Ptr csgDifferenceCopy(const GridOrTreeT &a, const GridOrTreeT &b)
Threaded CSG difference operation that produces a new grid or tree from immutable inputs.
Definition: Composite.h:1192
openvdb::v7_0::tools::CsgDiffVisitor::operator()
int operator()(ChildIterT &aIter, ChildIterT &bIter)
Process leaf node values.
Definition: Composite.h:1107
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
openvdb::v7_0::tools::composite::BuildSecondarySegment::InternalNodeType
typename boost::mpl::at< NodeChainType, boost::mpl::int_< 1 > >::type InternalNodeType
Definition: Composite.h:366
openvdb::v7_0::tools::CsgVisitorBase::TreeT
TreeType TreeT
Definition: Composite.h:867
openvdb::v7_0::tools::pruneLevelSet
void pruneLevelSet(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing nodes whose values are all inactive with inactive ...
Definition: Prune.h:389
Prune.h
Defined various multi-threaded utility functions for trees.
openvdb::v7_0::tools::composite::BuildSecondarySegment
Definition: Composite.h:358
openvdb::v7_0::tools::composite::divide
bool divide(bool a, bool)
Definition: Composite.h:144
openvdb::v7_0::tools::composite::BuildSecondarySegment::segment
TreePtrType & segment()
Definition: Composite.h:391
ValueTransformer.h
openvdb::v7_0::tools::compMax
void compMax(GridOrTreeT &a, GridOrTreeT &b)
Given grids A and B, compute max(a, b) per voxel (using sparse traversal). Store the result in the A ...
Definition: Composite.h:730
openvdb::v7_0::CombineArgs::b
const BValueType & b() const
Get the B input value.
Definition: Types.h:609
openvdb::v7_0::tools::CompReplaceOp::operator()
void operator()(const typename TreeT::LeafCIter &leafIter) const
Definition: Composite.h:823
openvdb::v7_0::tools::csgDifference
void csgDifference(GridOrTreeT &a, GridOrTreeT &b, bool prune=true)
Given two level set grids, replace the A grid with the difference A / B.
Definition: Composite.h:1151
openvdb::v7_0::tools::composite::BuildPrimarySegment
Definition: Composite.h:150
openvdb::v7_0::CombineArgs
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:567
openvdb::v7_0::tools::CsgUnionVisitor::operator()
int operator()(IterT &aIter, IterT &bIter)
Process root and internal nodes.
Definition: Composite.h:923
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:154
openvdb::v7_0::tools::CsgIntersectVisitor::operator()
int operator()(AIterT &, BIterT &)
Don't process nodes that are at different tree levels.
Definition: Composite.h:992
openvdb::v7_0::tools::CsgUnionVisitor::CsgUnionVisitor
CsgUnionVisitor(const TreeT &a, const TreeT &b)
Definition: Composite.h:915
openvdb::v7_0::TreeAdapter
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:1065
openvdb::v7_0::tools::CsgIntersectVisitor::operator()
int operator()(IterT &aIter, IterT &bIter)
Process root and internal nodes.
Definition: Composite.h:996
openvdb::v7_0::tools::composite::doCSGCopy
TreeType::Ptr doCSGCopy(const TreeType &lhs, const TreeType &rhs)
Definition: Composite.h:550
openvdb::v7_0::tools::CsgUnionVisitor::operator()
int operator()(ChildIterT &aIter, ChildIterT &bIter)
Process leaf node values.
Definition: Composite.h:961
openvdb::v7_0::CombineArgs::setResult
CombineArgs & setResult(const AValueType &val)
Set the output value.
Definition: Types.h:617
openvdb::v7_0::tools::compSum
void compSum(GridOrTreeT &a, GridOrTreeT &b)
Given grids A and B, compute a + b per voxel (using sparse traversal). Store the result in the A grid...
Definition: Composite.h:762
openvdb::v7_0::tools::prune
void prune(TreeT &tree, typename TreeT::ValueType tolerance=zeroVal< typename TreeT::ValueType >(), bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing with tiles any nodes whose values are all the same...
Definition: Prune.h:334
openvdb::v7_0::tools::composite::GridOrTreeConstructor::TreeTypePtr
typename TreeType::Ptr TreeTypePtr
Definition: Composite.h:576
SignedFloodFill.h
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
openvdb::v7_0::tools::composite::GridOrTreeConstructor< Grid< TreeType > >::GridTypePtr
typename Grid< TreeType >::Ptr GridTypePtr
Definition: Composite.h:585
openvdb::v7_0::Index
Index32 Index
Definition: Types.h:31
openvdb::v7_0::tools::CsgDiffVisitor::operator()
int operator()(AIterT &, BIterT &)
Don't process nodes that are at different tree levels.
Definition: Composite.h:1064
openvdb::v7_0::tools::composite::BuildSecondarySegment::LeafNodeType
typename TreeType::LeafNodeType LeafNodeType
Definition: Composite.h:362
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:102
openvdb::v7_0::tools::CsgVisitorBase
Definition: Composite.h:864
openvdb::v7_0::math::Transform::copy
Ptr copy() const
Definition: Transform.h:50
openvdb::v7_0::tools::composite::BuildPrimarySegment::InternalNodeType
typename boost::mpl::at< NodeChainType, boost::mpl::int_< 1 > >::type InternalNodeType
Definition: Composite.h:158
openvdb::v7_0::tools::composite::BuildSecondarySegment::RootNodeType
typename TreeType::RootNodeType RootNodeType
Definition: Composite.h:364
openvdb::v7_0::tools::CsgVisitorBase::ValueT
typename TreeT::ValueType ValueT
Definition: Composite.h:868
openvdb::v7_0::tools::CsgDiffVisitor
Definition: Composite.h:1052
openvdb::v7_0::Index32
uint32_t Index32
Definition: Types.h:29
openvdb::v7_0::tools::composite::CSG_INTERSECTION
Definition: Composite.h:147
openvdb::v7_0::ValueError
Definition: Exceptions.h:65
openvdb::v7_0::tools::CsgDiffVisitor::operator()
int operator()(IterT &aIter, IterT &bIter)
Process root and internal nodes.
Definition: Composite.h:1068
openvdb
Definition: Exceptions.h:13
openvdb::v7_0::tools::composite::GridOrTreeConstructor
Definition: Composite.h:574
openvdb::v7_0::tools::CsgVisitorBase::CsgVisitorBase
CsgVisitorBase(const TreeT &aTree, const TreeT &bTree)
Definition: Composite.h:873
openvdb::v7_0::tools::composite::BuildPrimarySegment::TreePtrType
typename TreeType::Ptr TreePtrType
Definition: Composite.h:153
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:82
openvdb::v7_0::tools::signedFloodFill
void signedFloodFill(TreeOrLeafManagerT &tree, bool threaded=true, size_t grainSize=1, Index minLevel=0)
Set the values of all inactive voxels and tiles of a narrow-band level set from the signs of the acti...
Definition: SignedFloodFill.h:266
Exceptions.h
openvdb::v7_0::tools::composite::BuildPrimarySegment::LeafNodeType
typename TreeType::LeafNodeType LeafNodeType
Definition: Composite.h:154
openvdb::v7_0::math::Coord::data
const Int32 * data() const
Definition: Coord.h:140
openvdb::v7_0::tools::CompReplaceOp::operator()
void operator()(const typename TreeT::ValueOnCIter &iter) const
Definition: Composite.h:816
openvdb::v7_0::tools::composite::BuildSecondarySegment::BuildSecondarySegment
BuildSecondarySegment(const TreeType &lhs, const TreeType &rhs)
Definition: Composite.h:368
openvdb::v7_0::tools::CsgUnionVisitor
Definition: Composite.h:907