OpenVDB 3.2.0

Composite.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2016 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 //
36
37 #ifndef OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED
38 #define OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED
39
40 #include <openvdb/Platform.h>
41 #include <openvdb/Exceptions.h>
42 #include <openvdb/Types.h>
43 #include <openvdb/Grid.h>
44 #include <openvdb/math/Math.h> // for isExactlyEqual()
45 #include "ValueTransformer.h" // for transformValues()
46 #include "Prune.h"// for prune
47 #include "SignedFloodFill.h" // for signedFloodFill()
48 #include <boost/utility/enable_if.hpp>
49
50 #include <tbb/blocked_range.h>
51 #include <tbb/parallel_for.h>
52 #include <tbb/parallel_reduce.h>
53 #include <tbb/task_group.h>
54 #include <tbb/task_scheduler_init.h>
55
56
57 namespace openvdb {
58 OPENVDB_USE_VERSION_NAMESPACE
59 namespace OPENVDB_VERSION_NAME {
60 namespace tools {
61
65 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
66 inline void csgUnion(GridOrTreeT& a, GridOrTreeT& b, bool prune = true);
70 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
71 inline void csgIntersection(GridOrTreeT& a, GridOrTreeT& b, bool prune = true);
75 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
76 inline void csgDifference(GridOrTreeT& a, GridOrTreeT& b, bool prune = true);
77
81 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
82 inline typename GridOrTreeT::Ptr csgUnionCopy(const GridOrTreeT& a, const GridOrTreeT& b);
86 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
87 inline typename GridOrTreeT::Ptr csgIntersectionCopy(const GridOrTreeT& a, const GridOrTreeT& b);
91 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
92 inline typename GridOrTreeT::Ptr csgDifferenceCopy(const GridOrTreeT& a, const GridOrTreeT& b);
93
96 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
97 inline void compMax(GridOrTreeT& a, GridOrTreeT& b);
100 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
101 inline void compMin(GridOrTreeT& a, GridOrTreeT& b);
104 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
105 inline void compSum(GridOrTreeT& a, GridOrTreeT& b);
108 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
109 inline void compMul(GridOrTreeT& a, GridOrTreeT& b);
112 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
113 inline void compDiv(GridOrTreeT& a, GridOrTreeT& b);
114
116 template<typename GridOrTreeT> OPENVDB_STATIC_SPECIALIZATION
117 inline void compReplace(GridOrTreeT& a, const GridOrTreeT& b);
118
119
121
122
123 namespace composite {
124
125 // composite::min() and composite::max() for non-vector types compare with operator<().
126 template<typename T> inline
127 const typename boost::disable_if_c<VecTraits<T>::IsVec, T>::type& // = T if T is not a vector type
128 min(const T& a, const T& b) { return std::min(a, b); }
129
130 template<typename T> inline
131 const typename boost::disable_if_c<VecTraits<T>::IsVec, T>::type&
132 max(const T& a, const T& b) { return std::max(a, b); }
133
134
135 // composite::min() and composite::max() for OpenVDB vector types compare by magnitude.
136 template<typename T> inline
137 const typename boost::enable_if_c<VecTraits<T>::IsVec, T>::type& // = T if T is a vector type
138 min(const T& a, const T& b)
139 {
140 const typename T::ValueType aMag = a.lengthSqr(), bMag = b.lengthSqr();
141 return (aMag < bMag ? a : (bMag < aMag ? b : std::min(a, b)));
142 }
143
144 template<typename T> inline
145 const typename boost::enable_if_c<VecTraits<T>::IsVec, T>::type&
146 max(const T& a, const T& b)
147 {
148 const typename T::ValueType aMag = a.lengthSqr(), bMag = b.lengthSqr();
149 return (aMag < bMag ? b : (bMag < aMag ? a : std::max(a, b)));
150 }
151
152
153 template<typename T> inline
154 typename boost::disable_if<boost::is_integral<T>, T>::type // = T if T is not an integer type
155 divide(const T& a, const T& b) { return a / b; }
156
157 template<typename T> inline
158 typename boost::enable_if<boost::is_integral<T>, T>::type // = T if T is an integer type
159 divide(const T& a, const T& b)
160 {
161 const T zero(0);
162 if (b != zero) return a / b;
163 if (a == zero) return 0;
164 return (a > 0 ? std::numeric_limits<T>::max() : -std::numeric_limits<T>::max());
165 }
166
167 // If b is true, return a / 1 = a.
168 // If b is false and a is true, return 1 / 0 = inf = MAX_BOOL = 1 = a.
169 // If b is false and a is false, return 0 / 0 = NaN = 0 = a.
170 inline bool divide(bool a, bool /*b*/) { return a; }
171
172
173 enum CSGOperation { CSG_UNION, CSG_INTERSECTION, CSG_DIFFERENCE };
174
175 template<typename TreeType, CSGOperation Operation>
176 struct BuildPrimarySegment
177 {
178 typedef typename TreeType::ValueType ValueType;
179 typedef typename TreeType::Ptr TreePtrType;
180 typedef typename TreeType::LeafNodeType LeafNodeType;
181 typedef typename LeafNodeType::NodeMaskType NodeMaskType;
182 typedef typename TreeType::RootNodeType RootNodeType;
183 typedef typename RootNodeType::NodeChainType NodeChainType;
184 typedef typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type InternalNodeType;
185
186 BuildPrimarySegment(const TreeType& lhs, const TreeType& rhs)
187 : mSegment(new TreeType(lhs.background()))
188 , mLhsTree(&lhs)
189 , mRhsTree(&rhs)
190 {
191 }
192
193 void operator()() const
194 {
195 std::vector<const LeafNodeType*> leafNodes;
196
197 {
198 std::vector<const InternalNodeType*> internalNodes;
199 mLhsTree->getNodes(internalNodes);
200
201 ProcessInternalNodes op(internalNodes, *mRhsTree, *mSegment, leafNodes);
202 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
203 }
204
205 ProcessLeafNodes op(leafNodes, *mRhsTree, *mSegment);
206 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
207 }
208
209 TreePtrType& segment() { return mSegment; }
210
211 private:
212
213 struct ProcessInternalNodes {
214
215 ProcessInternalNodes(std::vector<const InternalNodeType*>& lhsNodes, const TreeType& rhsTree,
216 TreeType& outputTree, std::vector<const LeafNodeType*>& outputLeafNodes)
217 : mLhsNodes(lhsNodes.empty() ? NULL : &lhsNodes.front())
218 , mRhsTree(&rhsTree)
219 , mLocalTree(mRhsTree->background())
220 , mOutputTree(&outputTree)
221 , mLocalLeafNodes()
222 , mOutputLeafNodes(&outputLeafNodes)
223 {
224 }
225
226 ProcessInternalNodes(ProcessInternalNodes& other, tbb::split)
227 : mLhsNodes(other.mLhsNodes)
228 , mRhsTree(other.mRhsTree)
229 , mLocalTree(mRhsTree->background())
230 , mOutputTree(&mLocalTree)
231 , mLocalLeafNodes()
232 , mOutputLeafNodes(&mLocalLeafNodes)
233 {
234 }
235
236 void join(ProcessInternalNodes& other)
237 {
238 mOutputTree->merge(*other.mOutputTree);
239 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
240 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
241 }
242
243 void operator()(const tbb::blocked_range<size_t>& range)
244 {
245 tree::ValueAccessor<const TreeType> rhsAcc(*mRhsTree);
246 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
247
248 std::vector<const LeafNodeType*> tmpLeafNodes;
249
250 for (size_t n = range.begin(), N = range.end(); n < N; ++n) {
251
252 const InternalNodeType& lhsNode = *mLhsNodes[n];
253 const Coord& ijk = lhsNode.origin();
254 const InternalNodeType * rhsNode = rhsAcc.template probeConstNode<InternalNodeType>(ijk);
255
256 if (rhsNode) {
257 lhsNode.getNodes(*mOutputLeafNodes);
258 } else {
259 if (Operation == CSG_INTERSECTION) {
260 if (rhsAcc.getValue(ijk) < ValueType(0.0)) {
261 tmpLeafNodes.clear();
262 lhsNode.getNodes(tmpLeafNodes);
263 for (size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
264 outputAcc.addLeaf(new LeafNodeType(*tmpLeafNodes[i]));
265 }
266 }
267 } else { // Union & Difference
268 if (!(rhsAcc.getValue(ijk) < ValueType(0.0))) {
269 tmpLeafNodes.clear();
270 lhsNode.getNodes(tmpLeafNodes);
271 for (size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
272 outputAcc.addLeaf(new LeafNodeType(*tmpLeafNodes[i]));
273 }
274 }
275 }
276 }
277 } // end range loop
278 }
279
280 InternalNodeType const * const * const mLhsNodes;
281 TreeType const * const mRhsTree;
282 TreeType mLocalTree;
283 TreeType * const mOutputTree;
284
285 std::vector<const LeafNodeType*> mLocalLeafNodes;
286 std::vector<const LeafNodeType*> * const mOutputLeafNodes;
287 }; // struct ProcessInternalNodes
288
289 struct ProcessLeafNodes {
290
291 ProcessLeafNodes(std::vector<const LeafNodeType*>& lhsNodes, const TreeType& rhsTree, TreeType& output)
292 : mLhsNodes(lhsNodes.empty() ? NULL : &lhsNodes.front())
293 , mRhsTree(&rhsTree)
294 , mLocalTree(mRhsTree->background())
295 , mOutputTree(&output)
296 {
297 }
298
299 ProcessLeafNodes(ProcessLeafNodes& other, tbb::split)
300 : mLhsNodes(other.mLhsNodes)
301 , mRhsTree(other.mRhsTree)
302 , mLocalTree(mRhsTree->background())
303 , mOutputTree(&mLocalTree)
304 {
305 }
306
307 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
308
309 void operator()(const tbb::blocked_range<size_t>& range)
310 {
311 tree::ValueAccessor<const TreeType> rhsAcc(*mRhsTree);
312 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
313
314 for (size_t n = range.begin(), N = range.end(); n < N; ++n) {
315
316 const LeafNodeType& lhsNode = *mLhsNodes[n];
317 const Coord& ijk = lhsNode.origin();
318
319 const LeafNodeType* rhsNodePt = rhsAcc.probeConstLeaf(ijk);
320
321 if (rhsNodePt) { // combine overlapping nodes
322
323 LeafNodeType* outputNode = outputAcc.touchLeaf(ijk);
324 ValueType * outputData = outputNode->buffer().data();
325 NodeMaskType& outputMask = outputNode->getValueMask();
326
327 const ValueType * lhsData = lhsNode.buffer().data();
328 const NodeMaskType& lhsMask = lhsNode.getValueMask();
329
330 const ValueType * rhsData = rhsNodePt->buffer().data();
331 const NodeMaskType& rhsMask = rhsNodePt->getValueMask();
332
333 if (Operation == CSG_INTERSECTION) {
334 for (Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
335 const bool fromRhs = lhsData[pos] < rhsData[pos];
336 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
337 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
338 }
339 } else if (Operation == CSG_DIFFERENCE){
340 for (Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
341 const ValueType rhsVal = math::negative(rhsData[pos]);
342 const bool fromRhs = lhsData[pos] < rhsVal;
343 outputData[pos] = fromRhs ? rhsVal : lhsData[pos];
344 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
345 }
346 } else { // Union
347 for (Index pos = 0; pos < LeafNodeType::SIZE; ++pos) {
348 const bool fromRhs = lhsData[pos] > rhsData[pos];
349 outputData[pos] = fromRhs ? rhsData[pos] : lhsData[pos];
350 outputMask.set(pos, fromRhs ? rhsMask.isOn(pos) : lhsMask.isOn(pos));
351 }
352 }
353
354 } else {
355 if (Operation == CSG_INTERSECTION) {
356 if (rhsAcc.getValue(ijk) < ValueType(0.0)) {
357 outputAcc.addLeaf(new LeafNodeType(lhsNode));
358 }
359 } else { // Union & Difference
360 if (!(rhsAcc.getValue(ijk) < ValueType(0.0))) {
361 outputAcc.addLeaf(new LeafNodeType(lhsNode));
362 }
363 }
364 }
365 } // end range loop
366 }
367
368 LeafNodeType const * const * const mLhsNodes;
369 TreeType const * const mRhsTree;
370 TreeType mLocalTree;
371 TreeType * const mOutputTree;
372 }; // struct ProcessLeafNodes
373
374 TreePtrType mSegment;
375 TreeType const * const mLhsTree;
376 TreeType const * const mRhsTree;
377 }; // struct BuildPrimarySegment
378
379
380 template<typename TreeType, CSGOperation Operation>
381 struct BuildSecondarySegment
382 {
383 typedef typename TreeType::ValueType ValueType;
384 typedef typename TreeType::Ptr TreePtrType;
385 typedef typename TreeType::LeafNodeType LeafNodeType;
386 typedef typename LeafNodeType::NodeMaskType NodeMaskType;
387 typedef typename TreeType::RootNodeType RootNodeType;
388 typedef typename RootNodeType::NodeChainType NodeChainType;
389 typedef typename boost::mpl::at<NodeChainType, boost::mpl::int_<1> >::type InternalNodeType;
390
391 BuildSecondarySegment(const TreeType& lhs, const TreeType& rhs)
392 : mSegment(new TreeType(lhs.background()))
393 , mLhsTree(&lhs)
394 , mRhsTree(&rhs)
395 {
396 }
397
398 void operator()() const
399 {
400 std::vector<const LeafNodeType*> leafNodes;
401
402 {
403 std::vector<const InternalNodeType*> internalNodes;
404 mRhsTree->getNodes(internalNodes);
405
406 ProcessInternalNodes op(internalNodes, *mLhsTree, *mSegment, leafNodes);
407 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, internalNodes.size()), op);
408 }
409
410 ProcessLeafNodes op(leafNodes, *mLhsTree, *mSegment);
411 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, leafNodes.size()), op);
412 }
413
414 TreePtrType& segment() { return mSegment; }
415
416 private:
417
418 struct ProcessInternalNodes {
419
420 ProcessInternalNodes(std::vector<const InternalNodeType*>& rhsNodes, const TreeType& lhsTree,
421 TreeType& outputTree, std::vector<const LeafNodeType*>& outputLeafNodes)
422 : mRhsNodes(rhsNodes.empty() ? NULL : &rhsNodes.front())
423 , mLhsTree(&lhsTree)
424 , mLocalTree(mLhsTree->background())
425 , mOutputTree(&outputTree)
426 , mLocalLeafNodes()
427 , mOutputLeafNodes(&outputLeafNodes)
428 {
429 }
430
431 ProcessInternalNodes(ProcessInternalNodes& other, tbb::split)
432 : mRhsNodes(other.mRhsNodes)
433 , mLhsTree(other.mLhsTree)
434 , mLocalTree(mLhsTree->background())
435 , mOutputTree(&mLocalTree)
436 , mLocalLeafNodes()
437 , mOutputLeafNodes(&mLocalLeafNodes)
438 {
439 }
440
441 void join(ProcessInternalNodes& other)
442 {
443 mOutputTree->merge(*other.mOutputTree);
444 mOutputLeafNodes->insert(mOutputLeafNodes->end(),
445 other.mOutputLeafNodes->begin(), other.mOutputLeafNodes->end());
446 }
447
448 void operator()(const tbb::blocked_range<size_t>& range)
449 {
450 tree::ValueAccessor<const TreeType> lhsAcc(*mLhsTree);
451 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
452
453 std::vector<const LeafNodeType*> tmpLeafNodes;
454
455 for (size_t n = range.begin(), N = range.end(); n < N; ++n) {
456
457 const InternalNodeType& rhsNode = *mRhsNodes[n];
458 const Coord& ijk = rhsNode.origin();
459 const InternalNodeType * lhsNode = lhsAcc.template probeConstNode<InternalNodeType>(ijk);
460
461 if (lhsNode) {
462 rhsNode.getNodes(*mOutputLeafNodes);
463 } else {
464 if (Operation == CSG_INTERSECTION) {
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]));
470 }
471 }
472 } else if (Operation == CSG_DIFFERENCE) {
473 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
474 tmpLeafNodes.clear();
475 rhsNode.getNodes(tmpLeafNodes);
476 for (size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
477 LeafNodeType* outputNode = new LeafNodeType(*tmpLeafNodes[i]);
478 outputNode->negate();
479 outputAcc.addLeaf(outputNode);
480 }
481 }
482 } else { // Union
483 if (!(lhsAcc.getValue(ijk) < ValueType(0.0))) {
484 tmpLeafNodes.clear();
485 rhsNode.getNodes(tmpLeafNodes);
486 for (size_t i = 0, I = tmpLeafNodes.size(); i < I; ++i) {
487 outputAcc.addLeaf(new LeafNodeType(*tmpLeafNodes[i]));
488 }
489 }
490 }
491 }
492 } // end range loop
493 }
494
495 InternalNodeType const * const * const mRhsNodes;
496 TreeType const * const mLhsTree;
497 TreeType mLocalTree;
498 TreeType * const mOutputTree;
499
500 std::vector<const LeafNodeType*> mLocalLeafNodes;
501 std::vector<const LeafNodeType*> * const mOutputLeafNodes;
502 }; // struct ProcessInternalNodes
503
504 struct ProcessLeafNodes {
505
506 ProcessLeafNodes(std::vector<const LeafNodeType*>& rhsNodes, const TreeType& lhsTree, TreeType& output)
507 : mRhsNodes(rhsNodes.empty() ? NULL : &rhsNodes.front())
508 , mLhsTree(&lhsTree)
509 , mLocalTree(mLhsTree->background())
510 , mOutputTree(&output)
511 {
512 }
513
514 ProcessLeafNodes(ProcessLeafNodes& rhs, tbb::split)
515 : mRhsNodes(rhs.mRhsNodes)
516 , mLhsTree(rhs.mLhsTree)
517 , mLocalTree(mLhsTree->background())
518 , mOutputTree(&mLocalTree)
519 {
520 }
521
522 void join(ProcessLeafNodes& rhs) { mOutputTree->merge(*rhs.mOutputTree); }
523
524 void operator()(const tbb::blocked_range<size_t>& range)
525 {
526 tree::ValueAccessor<const TreeType> lhsAcc(*mLhsTree);
527 tree::ValueAccessor<TreeType> outputAcc(*mOutputTree);
528
529 for (size_t n = range.begin(), N = range.end(); n < N; ++n) {
530
531 const LeafNodeType& rhsNode = *mRhsNodes[n];
532 const Coord& ijk = rhsNode.origin();
533
534 const LeafNodeType* lhsNode = lhsAcc.probeConstLeaf(ijk);
535
536 if (!lhsNode) {
537 if (Operation == CSG_INTERSECTION) {
538 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
539 outputAcc.addLeaf(new LeafNodeType(rhsNode));
540 }
541 } else if (Operation == CSG_DIFFERENCE) {
542 if (lhsAcc.getValue(ijk) < ValueType(0.0)) {
543 LeafNodeType* outputNode = new LeafNodeType(rhsNode);
544 outputNode->negate();
545 outputAcc.addLeaf(outputNode);
546 }
547 } else { // Union
548 if (!(lhsAcc.getValue(ijk) < ValueType(0.0))) {
549 outputAcc.addLeaf(new LeafNodeType(rhsNode));
550 }
551 }
552 }
553 } // end range loop
554 }
555
556 LeafNodeType const * const * const mRhsNodes;
557 TreeType const * const mLhsTree;
558 TreeType mLocalTree;
559 TreeType * const mOutputTree;
560 }; // struct ProcessLeafNodes
561
562 TreePtrType mSegment;
563 TreeType const * const mLhsTree;
564 TreeType const * const mRhsTree;
565 }; // struct BuildSecondarySegment
566
567
568 template<CSGOperation Operation, typename TreeType>
569 inline typename TreeType::Ptr
570 doCSGCopy(const TreeType& lhs, const TreeType& rhs)
571 {
572 BuildPrimarySegment<TreeType, Operation> primary(lhs, rhs);
573 BuildSecondarySegment<TreeType, Operation> secondary(lhs, rhs);
574
575 // Exploiting nested parallelism
576 tbb::task_group tasks;
577 tasks.run(primary);
578 tasks.run(secondary);
579 tasks.wait();
580
581 primary.segment()->merge(*secondary.segment());
582
583 // The leafnode (level = 0) sign is set in the segment construction.
584 tools::signedFloodFill(*primary.segment(), /*threaded=*/true, /*grainSize=*/1, /*minLevel=*/1);
585
586 return primary.segment();
587 }
588
589
591
592
593 template<typename TreeType>
594 struct GridOrTreeConstructor
595 {
596 typedef typename TreeType::Ptr TreeTypePtr;
597 static TreeTypePtr construct(const TreeType&, TreeTypePtr& tree) { return tree; }
598 };
599
600
601 template<typename TreeType>
602 struct GridOrTreeConstructor<Grid<TreeType> >
603 {
604 typedef Grid<TreeType> GridType;
605 typedef typename Grid<TreeType>::Ptr GridTypePtr;
606 typedef typename TreeType::Ptr TreeTypePtr;
607
608 static GridTypePtr construct(const GridType& grid, TreeTypePtr& tree) {
609 GridTypePtr maskGrid(GridType::create(tree));
610 maskGrid->setTransform(grid.transform().copy());
611 maskGrid->insertMeta(grid);
612 return maskGrid;
613 }
614 };
615
616
618
619
620 } // namespace composite
621
622
623 template<typename GridOrTreeT>
624 OPENVDB_STATIC_SPECIALIZATION inline void
625 compMax(GridOrTreeT& aTree, GridOrTreeT& bTree)
626 {
627 typedef TreeAdapter<GridOrTreeT> Adapter;
628 typedef typename Adapter::TreeType TreeT;
629 typedef typename TreeT::ValueType ValueT;
630 struct Local {
631 static inline void op(CombineArgs<ValueT>& args) {
632 args.setResult(composite::max(args.a(), args.b()));
633 }
634 };
635 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op, /*prune=*/false);
636 }
637
638
639 template<typename GridOrTreeT>
640 OPENVDB_STATIC_SPECIALIZATION inline void
641 compMin(GridOrTreeT& aTree, GridOrTreeT& bTree)
642 {
643 typedef TreeAdapter<GridOrTreeT> Adapter;
644 typedef typename Adapter::TreeType TreeT;
645 typedef typename TreeT::ValueType ValueT;
646 struct Local {
647 static inline void op(CombineArgs<ValueT>& args) {
648 args.setResult(composite::min(args.a(), args.b()));
649 }
650 };
651 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op, /*prune=*/false);
652 }
653
654
655 template<typename GridOrTreeT>
656 OPENVDB_STATIC_SPECIALIZATION inline void
657 compSum(GridOrTreeT& aTree, GridOrTreeT& bTree)
658 {
659 typedef TreeAdapter<GridOrTreeT> Adapter;
660 typedef typename Adapter::TreeType TreeT;
661 struct Local {
662 static inline void op(CombineArgs<typename TreeT::ValueType>& args) {
663 args.setResult(args.a() + args.b());
664 }
665 };
666 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op, /*prune=*/false);
667 }
668
669
670 template<typename GridOrTreeT>
671 OPENVDB_STATIC_SPECIALIZATION inline void
672 compMul(GridOrTreeT& aTree, GridOrTreeT& bTree)
673 {
674 typedef TreeAdapter<GridOrTreeT> Adapter;
675 typedef typename Adapter::TreeType TreeT;
676 struct Local {
677 static inline void op(CombineArgs<typename TreeT::ValueType>& args) {
678 args.setResult(args.a() * args.b());
679 }
680 };
681 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op, /*prune=*/false);
682 }
683
684
685 template<typename GridOrTreeT>
686 OPENVDB_STATIC_SPECIALIZATION inline void
687 compDiv(GridOrTreeT& aTree, GridOrTreeT& bTree)
688 {
689 typedef TreeAdapter<GridOrTreeT> Adapter;
690 typedef typename Adapter::TreeType TreeT;
691 struct Local {
692 static inline void op(CombineArgs<typename TreeT::ValueType>& args) {
693 args.setResult(composite::divide(args.a(), args.b()));
694 }
695 };
696 Adapter::tree(aTree).combineExtended(Adapter::tree(bTree), Local::op, /*prune=*/false);
697 }
698
699
701
702
703 template<typename TreeT>
704 struct CompReplaceOp
705 {
706 TreeT* const aTree;
707
708 CompReplaceOp(TreeT& _aTree): aTree(&_aTree) {}
709
711 void operator()(const typename TreeT::ValueOnCIter& iter) const
712 {
713 CoordBBox bbox;
714 iter.getBoundingBox(bbox);
715 aTree->fill(bbox, *iter);
716 }
717
718 void operator()(const typename TreeT::LeafCIter& leafIter) const
719 {
720 tree::ValueAccessor<TreeT> acc(*aTree);
721 for (typename TreeT::LeafCIter::LeafNodeT::ValueOnCIter iter =
722 leafIter->cbeginValueOn(); iter; ++iter)
723 {
724 acc.setValue(iter.getCoord(), *iter);
725 }
726 }
727 };
728
729
730 template<typename GridOrTreeT>
731 OPENVDB_STATIC_SPECIALIZATION inline void
732 compReplace(GridOrTreeT& aTree, const GridOrTreeT& bTree)
733 {
734 typedef TreeAdapter<GridOrTreeT> Adapter;
735 typedef typename Adapter::TreeType TreeT;
736 typedef typename TreeT::ValueOnCIter ValueOnCIterT;
737
738 // Copy active states (but not values) from B to A.
739 Adapter::tree(aTree).topologyUnion(Adapter::tree(bTree));
740
741 CompReplaceOp<TreeT> op(Adapter::tree(aTree));
742
743 // Copy all active tile values from B to A.
744 ValueOnCIterT iter = bTree.cbeginValueOn();
745 iter.setMaxDepth(iter.getLeafDepth() - 1); // don't descend into leaf nodes
746 foreach(iter, op, /*threaded=*/false);
747
748 // Copy all active voxel values from B to A.
749 foreach(Adapter::tree(bTree).cbeginLeaf(), op);
750 }
751
752
754
755
758 template<typename TreeType>
759 class CsgVisitorBase
760 {
761 public:
762 typedef TreeType TreeT;
763 typedef typename TreeT::ValueType ValueT;
764 typedef typename TreeT::LeafNodeType::ChildAllIter ChildIterT;
765
766 enum { STOP = 3 };
767
768 CsgVisitorBase(const TreeT& aTree, const TreeT& bTree):
769 mAOutside(aTree.background()),
770 mAInside(math::negative(mAOutside)),
771 mBOutside(bTree.background()),
772 mBInside(math::negative(mBOutside))
773 {
774 const ValueT zero = zeroVal<ValueT>();
775 if (!(mAOutside > zero)) {
776 OPENVDB_THROW(ValueError,
777 "expected grid A outside value > 0, got " << mAOutside);
778 }
779 if (!(mAInside < zero)) {
780 OPENVDB_THROW(ValueError,
781 "expected grid A inside value < 0, got " << mAInside);
782 }
783 if (!(mBOutside > zero)) {
784 OPENVDB_THROW(ValueError,
785 "expected grid B outside value > 0, got " << mBOutside);
786 }
787 if (!(mBInside < zero)) {
788 OPENVDB_THROW(ValueError,
789 "expected grid B outside value < 0, got " << mBOutside);
790 }
791 }
792
793 protected:
794 ValueT mAOutside, mAInside, mBOutside, mBInside;
795 };
796
797
799
800
801 template<typename TreeType>
802 struct CsgUnionVisitor: public CsgVisitorBase<TreeType>
803 {
804 typedef TreeType TreeT;
805 typedef typename TreeT::ValueType ValueT;
806 typedef typename TreeT::LeafNodeType::ChildAllIter ChildIterT;
807
808 enum { STOP = CsgVisitorBase<TreeT>::STOP };
809
810 CsgUnionVisitor(const TreeT& a, const TreeT& b): CsgVisitorBase<TreeT>(a, b) {}
811
813 template<typename AIterT, typename BIterT>
814 inline int operator()(AIterT&, BIterT&) { return 0; }
815
817 template<typename IterT>
818 inline int operator()(IterT& aIter, IterT& bIter)
819 {
820 ValueT aValue = zeroVal<ValueT>();
821 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
822 if (!aChild && aValue < zeroVal<ValueT>()) {
823 // A is an inside tile. Leave it alone and stop traversing this branch.
824 return STOP;
825 }
826
827 ValueT bValue = zeroVal<ValueT>();
828 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
829 if (!bChild && bValue < zeroVal<ValueT>()) {
830 // B is an inside tile. Make A an inside tile and stop traversing this branch.
831 aIter.setValue(this->mAInside);
832 aIter.setValueOn(bIter.isValueOn());
833 delete aChild;
834 return STOP;
835 }
836
837 if (!aChild && aValue > zeroVal<ValueT>()) {
838 // A is an outside tile. If B has a child, transfer it to A,
839 // otherwise leave A alone.
840 if (bChild) {
841 bIter.setValue(this->mBOutside);
842 bIter.setValueOff();
843 bChild->resetBackground(this->mBOutside, this->mAOutside);
844 aIter.setChild(bChild); // transfer child
845 delete aChild;
846 }
847 return STOP;
848 }
849
850 // If A has a child and B is an outside tile, stop traversing this branch.
851 // Continue traversal only if A and B both have children.
852 return (aChild && bChild) ? 0 : STOP;
853 }
854
856 inline int operator()(ChildIterT& aIter, ChildIterT& bIter)
857 {
858 ValueT aValue, bValue;
859 aIter.probeValue(aValue);
860 bIter.probeValue(bValue);
861 if (aValue > bValue) { // a = min(a, b)
862 aIter.setValue(bValue);
863 aIter.setValueOn(bIter.isValueOn());
864 }
865 return 0;
866 }
867 };
868
869
870
872
873
874 template<typename TreeType>
875 struct CsgIntersectVisitor: public CsgVisitorBase<TreeType>
876 {
877 typedef TreeType TreeT;
878 typedef typename TreeT::ValueType ValueT;
879 typedef typename TreeT::LeafNodeType::ChildAllIter ChildIterT;
880
881 enum { STOP = CsgVisitorBase<TreeT>::STOP };
882
883 CsgIntersectVisitor(const TreeT& a, const TreeT& b): CsgVisitorBase<TreeT>(a, b) {}
884
886 template<typename AIterT, typename BIterT>
887 inline int operator()(AIterT&, BIterT&) { return 0; }
888
890 template<typename IterT>
891 inline int operator()(IterT& aIter, IterT& bIter)
892 {
893 ValueT aValue = zeroVal<ValueT>();
894 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
895 if (!aChild && !(aValue < zeroVal<ValueT>())) {
896 // A is an outside tile. Leave it alone and stop traversing this branch.
897 return STOP;
898 }
899
900 ValueT bValue = zeroVal<ValueT>();
901 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
902 if (!bChild && !(bValue < zeroVal<ValueT>())) {
903 // B is an outside tile. Make A an outside tile and stop traversing this branch.
904 aIter.setValue(this->mAOutside);
905 aIter.setValueOn(bIter.isValueOn());
906 delete aChild;
907 return STOP;
908 }
909
910 if (!aChild && aValue < zeroVal<ValueT>()) {
911 // A is an inside tile. If B has a child, transfer it to A,
912 // otherwise leave A alone.
913 if (bChild) {
914 bIter.setValue(this->mBOutside);
915 bIter.setValueOff();
916 bChild->resetBackground(this->mBOutside, this->mAOutside);
917 aIter.setChild(bChild); // transfer child
918 delete aChild;
919 }
920 return STOP;
921 }
922
923 // If A has a child and B is an outside tile, stop traversing this branch.
924 // Continue traversal only if A and B both have children.
925 return (aChild && bChild) ? 0 : STOP;
926 }
927
929 inline int operator()(ChildIterT& aIter, ChildIterT& bIter)
930 {
931 ValueT aValue, bValue;
932 aIter.probeValue(aValue);
933 bIter.probeValue(bValue);
934 if (aValue < bValue) { // a = max(a, b)
935 aIter.setValue(bValue);
936 aIter.setValueOn(bIter.isValueOn());
937 }
938 return 0;
939 }
940 };
941
942
944
945
946 template<typename TreeType>
947 struct CsgDiffVisitor: public CsgVisitorBase<TreeType>
948 {
949 typedef TreeType TreeT;
950 typedef typename TreeT::ValueType ValueT;
951 typedef typename TreeT::LeafNodeType::ChildAllIter ChildIterT;
952
953 enum { STOP = CsgVisitorBase<TreeT>::STOP };
954
955 CsgDiffVisitor(const TreeT& a, const TreeT& b): CsgVisitorBase<TreeT>(a, b) {}
956
958 template<typename AIterT, typename BIterT>
959 inline int operator()(AIterT&, BIterT&) { return 0; }
960
962 template<typename IterT>
963 inline int operator()(IterT& aIter, IterT& bIter)
964 {
965 ValueT aValue = zeroVal<ValueT>();
966 typename IterT::ChildNodeType* aChild = aIter.probeChild(aValue);
967 if (!aChild && !(aValue < zeroVal<ValueT>())) {
968 // A is an outside tile. Leave it alone and stop traversing this branch.
969 return STOP;
970 }
971
972 ValueT bValue = zeroVal<ValueT>();
973 typename IterT::ChildNodeType* bChild = bIter.probeChild(bValue);
974 if (!bChild && bValue < zeroVal<ValueT>()) {
975 // B is an inside tile. Make A an inside tile and stop traversing this branch.
976 aIter.setValue(this->mAOutside);
977 aIter.setValueOn(bIter.isValueOn());
978 delete aChild;
979 return STOP;
980 }
981
982 if (!aChild && aValue < zeroVal<ValueT>()) {
983 // A is an inside tile. If B has a child, transfer it to A,
984 // otherwise leave A alone.
985 if (bChild) {
986 bIter.setValue(this->mBOutside);
987 bIter.setValueOff();
988 bChild->resetBackground(this->mBOutside, this->mAOutside);
989 aIter.setChild(bChild); // transfer child
990 bChild->negate();
991 delete aChild;
992 }
993 return STOP;
994 }
995
996 // If A has a child and B is an outside tile, stop traversing this branch.
997 // Continue traversal only if A and B both have children.
998 return (aChild && bChild) ? 0 : STOP;
999 }
1000
1002 inline int operator()(ChildIterT& aIter, ChildIterT& bIter)
1003 {
1004 ValueT aValue, bValue;
1005 aIter.probeValue(aValue);
1006 bIter.probeValue(bValue);
1007 bValue = math::negative(bValue);
1008 if (aValue < bValue) { // a = max(a, -b)
1009 aIter.setValue(bValue);
1010 aIter.setValueOn(bIter.isValueOn());
1011 }
1012 return 0;
1013 }
1014 };
1015
1016
1018
1019
1020 template<typename GridOrTreeT>
1021 OPENVDB_STATIC_SPECIALIZATION inline void
1022 csgUnion(GridOrTreeT& a, GridOrTreeT& b, bool prune)
1023 {
1024 typedef TreeAdapter<GridOrTreeT> Adapter;
1025 typedef typename Adapter::TreeType TreeT;
1026 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1027 CsgUnionVisitor<TreeT> visitor(aTree, bTree);
1028 aTree.visit2(bTree, visitor);
1029 if (prune) tools::pruneLevelSet(aTree);
1030 }
1031
1032 template<typename GridOrTreeT>
1033 OPENVDB_STATIC_SPECIALIZATION inline void
1034 csgIntersection(GridOrTreeT& a, GridOrTreeT& b, bool prune)
1035 {
1036 typedef TreeAdapter<GridOrTreeT> Adapter;
1037 typedef typename Adapter::TreeType TreeT;
1038 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1039 CsgIntersectVisitor<TreeT> visitor(aTree, bTree);
1040 aTree.visit2(bTree, visitor);
1041 if (prune) tools::pruneLevelSet(aTree);
1042 }
1043
1044 template<typename GridOrTreeT>
1045 OPENVDB_STATIC_SPECIALIZATION inline void
1046 csgDifference(GridOrTreeT& a, GridOrTreeT& b, bool prune)
1047 {
1048 typedef TreeAdapter<GridOrTreeT> Adapter;
1049 typedef typename Adapter::TreeType TreeT;
1050 TreeT &aTree = Adapter::tree(a), &bTree = Adapter::tree(b);
1051 CsgDiffVisitor<TreeT> visitor(aTree, bTree);
1052 aTree.visit2(bTree, visitor);
1053 if (prune) tools::pruneLevelSet(aTree);
1054 }
1055
1056
1057 template<typename GridOrTreeT>
1058 OPENVDB_STATIC_SPECIALIZATION inline typename GridOrTreeT::Ptr
1059 csgUnionCopy(const GridOrTreeT& a, const GridOrTreeT& b)
1060 {
1061 typedef TreeAdapter<GridOrTreeT> Adapter;
1062 typedef typename Adapter::TreeType::Ptr TreePtrT;
1063
1064 TreePtrT output = composite::doCSGCopy<composite::CSG_UNION>(
1065 Adapter::tree(a), Adapter::tree(b));
1066
1067 return composite::GridOrTreeConstructor<GridOrTreeT>::construct(a, output);
1068 }
1069
1070
1071 template<typename GridOrTreeT>
1072 OPENVDB_STATIC_SPECIALIZATION inline typename GridOrTreeT::Ptr
1073 csgIntersectionCopy(const GridOrTreeT& a, const GridOrTreeT& b)
1074 {
1075 typedef TreeAdapter<GridOrTreeT> Adapter;
1076 typedef typename Adapter::TreeType::Ptr TreePtrT;
1077
1078 TreePtrT output = composite::doCSGCopy<composite::CSG_INTERSECTION>(
1079 Adapter::tree(a), Adapter::tree(b));
1080
1081 return composite::GridOrTreeConstructor<GridOrTreeT>::construct(a, output);
1082 }
1083
1084
1085 template<typename GridOrTreeT>
1086 OPENVDB_STATIC_SPECIALIZATION inline typename GridOrTreeT::Ptr
1087 csgDifferenceCopy(const GridOrTreeT& a, const GridOrTreeT& b)
1088 {
1089 typedef TreeAdapter<GridOrTreeT> Adapter;
1090 typedef typename Adapter::TreeType::Ptr TreePtrT;
1091
1092 TreePtrT output = composite::doCSGCopy<composite::CSG_DIFFERENCE>(
1093 Adapter::tree(a), Adapter::tree(b));
1094
1095 return composite::GridOrTreeConstructor<GridOrTreeT>::construct(a, output);
1096 }
1097
1098
1099 } // namespace tools
1100 } // namespace OPENVDB_VERSION_NAME
1101 } // namespace openvdb
1102
1103 #endif // OPENVDB_TOOLS_COMPOSITE_HAS_BEEN_INCLUDED
1104
1105 // Copyright (c) 2012-2016 DreamWorks Animation LLC
1106 // All rights reserved. This software is distributed under the
1107 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
openvdb::v3_2_0::tree::ValueAccessor::addLeaf
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process. If the leaf node already exists, replace it.
Definition: ValueAccessor.h:374
openvdb::v3_2_0::tools::CsgDiffVisitor
Definition: Composite.h:947
openvdb::v3_2_0::tools::composite::GridOrTreeConstructor
Definition: Composite.h:594
openvdb::v3_2_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:294
openvdb::v3_2_0::tools::CsgDiffVisitor::operator()
int operator()(ChildIterT &aIter, ChildIterT &bIter)
Process leaf node values.
Definition: Composite.h:1002
openvdb::v3_2_0::tools::csgDifference
OPENVDB_STATIC_SPECIALIZATION 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:1046
Types.h
openvdb::v3_2_0::tools::csgIntersection
OPENVDB_STATIC_SPECIALIZATION 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:1034
openvdb::v3_2_0::math::Transform::copy
Ptr copy() const
Definition: Transform.h:77
openvdb::v3_2_0::tools::composite::BuildPrimarySegment::segment
TreePtrType & segment()
Definition: Composite.h:209
openvdb::v3_2_0::tools::CsgIntersectVisitor::TreeT
TreeType TreeT
Definition: Composite.h:877
openvdb::v3_2_0::CombineArgs::setResult
CombineArgs & setResult(const AValueType &val)
Set the output value.
Definition: Types.h:362
openvdb::v3_2_0::tools::composite::BuildSecondarySegment::NodeMaskType
LeafNodeType::NodeMaskType NodeMaskType
Definition: Composite.h:386
openvdb::v3_2_0::tools::CsgIntersectVisitor::CsgIntersectVisitor
CsgIntersectVisitor(const TreeT &a, const TreeT &b)
Definition: Composite.h:883
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
ValueTransformer.h
openvdb::v3_2_0::tools::CompReplaceOp::operator()
void operator()(const typename TreeT::ValueOnCIter &iter) const
Definition: Composite.h:711
openvdb::v3_2_0::tools::composite::BuildPrimarySegment::TreePtrType
TreeType::Ptr TreePtrType
Definition: Composite.h:179
openvdb::v3_2_0::tools::CsgDiffVisitor::operator()
int operator()(IterT &aIter, IterT &bIter)
Process root and internal nodes.
Definition: Composite.h:963
openvdb::v3_2_0::tools::csgUnion
OPENVDB_STATIC_SPECIALIZATION 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:1022
openvdb::v3_2_0::tools::composite::CSG_INTERSECTION
Definition: Composite.h:173
openvdb::v3_2_0::tools::CsgUnionVisitor::ValueT
TreeT::ValueType ValueT
Definition: Composite.h:805
openvdb::v3_2_0::tools::CsgUnionVisitor
Definition: Composite.h:802
openvdb::v3_2_0::tools::CompReplaceOp::aTree
TreeT *const aTree
Definition: Composite.h:706
openvdb::v3_2_0::tools::CompReplaceOp::CompReplaceOp
CompReplaceOp(TreeT &_aTree)
Definition: Composite.h:708
openvdb::v3_2_0::tools::compMax
OPENVDB_STATIC_SPECIALIZATION 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:625
openvdb::v3_2_0::tools::composite::BuildSecondarySegment::TreePtrType
TreeType::Ptr TreePtrType
Definition: Composite.h:384
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
openvdb::v3_2_0::tools::CsgDiffVisitor::operator()
int operator()(AIterT &, BIterT &)
Don&#39;t process nodes that are at different tree levels.
Definition: Composite.h:959
openvdb::v3_2_0::tools::composite::divide
bool divide(bool a, bool)
Definition: Composite.h:170
openvdb::v3_2_0::tools::CsgUnionVisitor::operator()
int operator()(AIterT &, BIterT &)
Don&#39;t process nodes that are at different tree levels.
Definition: Composite.h:814
openvdb::v3_2_0::tools::CsgVisitorBase::CsgVisitorBase
CsgVisitorBase(const TreeT &aTree, const TreeT &bTree)
Definition: Composite.h:768
openvdb::v3_2_0::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:47
openvdb::v3_2_0::tools::composite::BuildSecondarySegment::NodeChainType
RootNodeType::NodeChainType NodeChainType
Definition: Composite.h:388
openvdb::v3_2_0::tools::CsgIntersectVisitor::operator()
int operator()(IterT &aIter, IterT &bIter)
Process root and internal nodes.
Definition: Composite.h:891
openvdb::v3_2_0::tools::CsgUnionVisitor::operator()
int operator()(ChildIterT &aIter, ChildIterT &bIter)
Process leaf node values.
Definition: Composite.h:856
openvdb::v3_2_0::tools::composite::BuildPrimarySegment::LeafNodeType
TreeType::LeafNodeType LeafNodeType
Definition: Composite.h:180
openvdb::v3_2_0::tools::compSum
OPENVDB_STATIC_SPECIALIZATION 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:657
openvdb::v3_2_0::tools::compMul
OPENVDB_STATIC_SPECIALIZATION 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:672
openvdb::v3_2_0::tools::CsgUnionVisitor::ChildIterT
TreeT::LeafNodeType::ChildAllIter ChildIterT
Definition: Composite.h:806
openvdb::v3_2_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:429
openvdb::v3_2_0::tools::composite::BuildPrimarySegment::NodeChainType
RootNodeType::NodeChainType NodeChainType
Definition: Composite.h:183
openvdb::v3_2_0::tools::composite::BuildSecondarySegment
Definition: Composite.h:381
openvdb::v3_2_0::tools::CsgVisitorBase::TreeT
TreeType TreeT
Definition: Composite.h:762
openvdb::v3_2_0::tools::composite::BuildSecondarySegment::InternalNodeType
boost::mpl::at< NodeChainType, boost::mpl::int_< 1 > >::type InternalNodeType
Definition: Composite.h:389
openvdb::v3_2_0::tools::composite::GridOrTreeConstructor::construct
static TreeTypePtr construct(const TreeType &, TreeTypePtr &tree)
Definition: Composite.h:597
openvdb::v3_2_0::tools::csgDifferenceCopy
OPENVDB_STATIC_SPECIALIZATION 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:1087
openvdb::v3_2_0::tools::CompReplaceOp::operator()
void operator()(const typename TreeT::LeafCIter &leafIter) const
Definition: Composite.h:718
openvdb::v3_2_0::Grid::Ptr
boost::shared_ptr< Grid > Ptr
Definition: Grid.h:485
openvdb::v3_2_0::tree::ValueAccessor< const TreeType >
openvdb::v3_2_0::tools::CsgDiffVisitor::ChildIterT
TreeT::LeafNodeType::ChildAllIter ChildIterT
Definition: Composite.h:951
openvdb::v3_2_0::GridBase::transform
math::Transform & transform()
Return a reference to this grid&#39;s transform, which might be shared with other grids.
Definition: Grid.h:335
Prune.h
Defined various multi-threaded utility functions for trees.
openvdb::v3_2_0::tools::csgUnionCopy
OPENVDB_STATIC_SPECIALIZATION 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:1059
openvdb::v3_2_0::tools::compReplace
OPENVDB_STATIC_SPECIALIZATION void compReplace(GridOrTreeT &a, const GridOrTreeT &b)
Copy the active voxels of B into A.
Definition: Composite.h:732
openvdb::v3_2_0::CombineArgs::a
const AValueType & a() const
Get the A input value.
Definition: Types.h:352
openvdb::v3_2_0::tools::compMin
OPENVDB_STATIC_SPECIALIZATION 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:641
openvdb::v3_2_0::Index
Index32 Index
Definition: Types.h:58
openvdb::v3_2_0::tools::composite::GridOrTreeConstructor::TreeTypePtr
TreeType::Ptr TreeTypePtr
Definition: Composite.h:596
openvdb::v3_2_0::tools::CsgIntersectVisitor::operator()
int operator()(ChildIterT &aIter, ChildIterT &bIter)
Process leaf node values.
Definition: Composite.h:929
openvdb::v3_2_0::tools::CompReplaceOp
Definition: Composite.h:704
Exceptions.h
openvdb::v3_2_0::tools::CsgDiffVisitor::TreeT
TreeType TreeT
Definition: Composite.h:949
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
Definition: version.h:43
openvdb::v3_2_0::CombineArgs::b
const BValueType & b() const
Get the B input value.
Definition: Types.h:354
openvdb::v3_2_0::tree::ValueAccessor::getValue
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: ValueAccessor.h:256
openvdb::v3_2_0::tools::CsgUnionVisitor::operator()
int operator()(IterT &aIter, IterT &bIter)
Process root and internal nodes.
Definition: Composite.h:818
openvdb::v3_2_0::tools::composite::GridOrTreeConstructor< Grid< TreeType > >::GridTypePtr
Grid< TreeType >::Ptr GridTypePtr
Definition: Composite.h:605
SignedFloodFill.h
Propagates the sign of distance values from the active voxels in the narrow band to the inactive valu...
openvdb::v3_2_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:898
openvdb::v3_2_0::tools::composite::GridOrTreeConstructor< Grid< TreeType > >::TreeTypePtr
TreeType::Ptr TreeTypePtr
Definition: Composite.h:606
openvdb::v3_2_0::tools::CsgVisitorBase::mBOutside
ValueT mBOutside
Definition: Composite.h:794
openvdb
Definition: Exceptions.h:39
openvdb::v3_2_0::tools::composite::min
const boost::enable_if_c< VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:138
openvdb::v3_2_0::tools::composite::GridOrTreeConstructor< Grid< TreeType > >::GridType
Grid< TreeType > GridType
Definition: Composite.h:604
openvdb::v3_2_0::tools::CsgDiffVisitor::ValueT
TreeT::ValueType ValueT
Definition: Composite.h:950
openvdb::v3_2_0::tools::CsgUnionVisitor::TreeT
TreeType TreeT
Definition: Composite.h:804
openvdb::v3_2_0::tools::compDiv
OPENVDB_STATIC_SPECIALIZATION 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:687
openvdb::v3_2_0::tools::CsgDiffVisitor::CsgDiffVisitor
CsgDiffVisitor(const TreeT &a, const TreeT &b)
Definition: Composite.h:955
openvdb::v3_2_0::tools::CsgVisitorBase::ChildIterT
TreeT::LeafNodeType::ChildAllIter ChildIterT
Definition: Composite.h:764
openvdb::v3_2_0::tools::CsgVisitorBase::ValueT
TreeT::ValueType ValueT
Definition: Composite.h:763
openvdb::v3_2_0::tools::composite::max
const boost::enable_if_c< VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:146
openvdb::v3_2_0::tree::ValueAccessor::clear
virtual void clear()
Remove all nodes from this cache, then reinsert the root node.
Definition: ValueAccessor.h:438
openvdb::v3_2_0::tools::composite::BuildSecondarySegment::BuildSecondarySegment
BuildSecondarySegment(const TreeType &lhs, const TreeType &rhs)
Definition: Composite.h:391
openvdb::v3_2_0::tree::ValueAccessor::touchLeaf
LeafNodeT * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one, but preserve the values and active states of all voxels.
Definition: ValueAccessor.h:393
openvdb::v3_2_0::tools::CsgUnionVisitor::CsgUnionVisitor
CsgUnionVisitor(const TreeT &a, const TreeT &b)
Definition: Composite.h:810
openvdb::v3_2_0::tools::composite::BuildPrimarySegment::RootNodeType
TreeType::RootNodeType RootNodeType
Definition: Composite.h:182
openvdb::v3_2_0::tools::CsgIntersectVisitor::operator()
int operator()(AIterT &, BIterT &)
Don&#39;t process nodes that are at different tree levels.
Definition: Composite.h:887
openvdb::v3_2_0::tools::CsgIntersectVisitor::ChildIterT
TreeT::LeafNodeType::ChildAllIter ChildIterT
Definition: Composite.h:879
openvdb::v3_2_0::math::CoordBBox
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:259
OPENVDB_STATIC_SPECIALIZATION
#define OPENVDB_STATIC_SPECIALIZATION
Macro for determining if there are sufficient C++0x/C++11 features.
Definition: Platform.h:91
openvdb::v3_2_0::tools::composite::BuildSecondarySegment::ValueType
TreeType::ValueType ValueType
Definition: Composite.h:383
openvdb::v3_2_0::tools::composite::BuildPrimarySegment::operator()
void operator()() const
Definition: Composite.h:193
Grid.h
openvdb::v3_2_0::ValueError
Definition: Exceptions.h:88
openvdb::v3_2_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:374
openvdb::v3_2_0::tools::composite::doCSGCopy
TreeType::Ptr doCSGCopy(const TreeType &lhs, const TreeType &rhs)
Definition: Composite.h:570
openvdb::v3_2_0::tools::CsgVisitorBase
Definition: Composite.h:759
openvdb::v3_2_0::tools::csgIntersectionCopy
OPENVDB_STATIC_SPECIALIZATION 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:1073
openvdb::v3_2_0::tools::composite::BuildSecondarySegment::operator()
void operator()() const
Definition: Composite.h:398
openvdb::v3_2_0::tools::composite::BuildPrimarySegment::NodeMaskType
LeafNodeType::NodeMaskType NodeMaskType
Definition: Composite.h:181
openvdb::v3_2_0::tools::composite::BuildPrimarySegment::ValueType
TreeType::ValueType ValueType
Definition: Composite.h:178
openvdb::v3_2_0::math::negative
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:116
openvdb::v3_2_0::tools::composite::CSGOperation
CSGOperation
Definition: Composite.h:173
openvdb::v3_2_0::tools::CsgIntersectVisitor::ValueT
TreeT::ValueType ValueT
Definition: Composite.h:878
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
openvdb::v3_2_0::tools::composite::BuildPrimarySegment
Definition: Composite.h:176
openvdb::v3_2_0::tools::composite::BuildPrimarySegment::InternalNodeType
boost::mpl::at< NodeChainType, boost::mpl::int_< 1 > >::type InternalNodeType
Definition: Composite.h:184
openvdb::v3_2_0::tools::CsgIntersectVisitor
Definition: Composite.h:875
openvdb::v3_2_0::tools::composite::BuildSecondarySegment::RootNodeType
TreeType::RootNodeType RootNodeType
Definition: Composite.h:387
openvdb::v3_2_0::tools::composite::BuildPrimarySegment::BuildPrimarySegment
BuildPrimarySegment(const TreeType &lhs, const TreeType &rhs)
Definition: Composite.h:186
openvdb::v3_2_0::tree::ValueAccessor::probeConstLeaf
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z), or NULL if no such node exists...
Definition: ValueAccessor.h:429
openvdb::v3_2_0::tools::composite::BuildSecondarySegment::segment
TreePtrType & segment()
Definition: Composite.h:414
openvdb::v3_2_0::tools::composite::CSG_UNION
Definition: Composite.h:173
openvdb::v3_2_0::CombineArgs
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:312
openvdb::v3_2_0::Grid
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:54
openvdb::v3_2_0::tools::composite::GridOrTreeConstructor< Grid< TreeType > >::construct
static GridTypePtr construct(const GridType &grid, TreeTypePtr &tree)
Definition: Composite.h:608
openvdb::v3_2_0::tools::composite::CSG_DIFFERENCE
Definition: Composite.h:173
openvdb::v3_2_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:287
openvdb::v3_2_0::tools::composite::BuildSecondarySegment::LeafNodeType
TreeType::LeafNodeType LeafNodeType
Definition: Composite.h:385
Platform.h