OpenVDB 3.2.0

InternalNode.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 //
34
35 #ifndef OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
36 #define OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
37
38 #include <boost/shared_array.hpp>
39 #include <boost/static_assert.hpp>
40 #include <boost/mpl/if.hpp>
41 #include <boost/type_traits/is_const.hpp>
42 #include <boost/type_traits/is_pointer.hpp>
43 #include <boost/type_traits/remove_pointer.hpp>
44 #include <tbb/parallel_for.h>
45 #include <openvdb/Platform.h>
46 #include <openvdb/util/NodeMasks.h>
47 #include <openvdb/io/Compression.h> // for io::readData(), etc.
48 #include <openvdb/math/Math.h> // for Abs(), isExactlyEqual()
49 #include <openvdb/version.h>
50 #include <openvdb/Types.h>
51 #include "Iterator.h"
52 #include "NodeUnion.h"
53
54
55 namespace openvdb {
56 OPENVDB_USE_VERSION_NAMESPACE
57 namespace OPENVDB_VERSION_NAME {
58 namespace tree {
59
60 template<typename, Index, typename> struct SameInternalConfig; // forward declaration
61
62
63 template<typename _ChildNodeType, Index Log2Dim>
64 class InternalNode
65 {
66 public:
67 typedef _ChildNodeType ChildNodeType;
68 typedef typename ChildNodeType::LeafNodeType LeafNodeType;
69 typedef typename ChildNodeType::ValueType ValueType;
70 typedef typename ChildNodeType::BuildType BuildType;
71 typedef NodeUnion<ValueType, ChildNodeType> UnionType;
72 typedef util::NodeMask<Log2Dim> NodeMaskType;
73
74 static const Index
75 LOG2DIM = Log2Dim,// Log2 of tile count in one dimension
76 TOTAL = Log2Dim + ChildNodeType::TOTAL,// Log2 of voxel count in one dimension
77 DIM = 1 << TOTAL,// Total voxel count in one dimension
78 NUM_VALUES = 1 << (3 * Log2Dim),// Total voxels count represented by this node
79 LEVEL = 1 + ChildNodeType::LEVEL; // level 0 = leaf
80 static const Index64
81 NUM_VOXELS = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node
82
85 template<typename OtherValueType>
86 struct ValueConverter {
87 typedef InternalNode<typename ChildNodeType::template ValueConverter<
88 OtherValueType>::Type, Log2Dim> Type;
89 };
90
94 template<typename OtherNodeType>
95 struct SameConfiguration {
96 static const bool value =
97 SameInternalConfig<ChildNodeType, Log2Dim, OtherNodeType>::value;
98 };
99
100
103 InternalNode() {}
104
107 explicit InternalNode(const ValueType& offValue);
108
113 InternalNode(const Coord& origin, const ValueType& fillValue, bool active = false);
114
115 #ifndef OPENVDB_2_ABI_COMPATIBLE
116 InternalNode(PartialCreate, const Coord&, const ValueType& fillValue, bool active = false);
117 #endif
118
122 InternalNode(const InternalNode&);
123
127 template<typename OtherChildNodeType>
128 explicit InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other);
129
133 template<typename OtherChildNodeType>
134 InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other,
135 const ValueType& background, TopologyCopy);
136
140 template<typename OtherChildNodeType>
141 InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other,
142 const ValueType& offValue, const ValueType& onValue, TopologyCopy);
143
144 virtual ~InternalNode();
145
146 protected:
147 typedef typename NodeMaskType::OnIterator MaskOnIterator;
148 typedef typename NodeMaskType::OffIterator MaskOffIterator;
149 typedef typename NodeMaskType::DenseIterator MaskDenseIterator;
150
151 // Type tags to disambiguate template instantiations
152 struct ValueOn {}; struct ValueOff {}; struct ValueAll {};
153 struct ChildOn {}; struct ChildOff {}; struct ChildAll {};
154
155 // The following class templates implement the iterator interfaces specified in Iterator.h
156 // by providing getItem(), setItem() and/or modifyItem() methods.
157
158 // Sparse iterator that visits child nodes of an InternNode
159 template<typename NodeT, typename ChildT, typename MaskIterT, typename TagT>
160 struct ChildIter: public SparseIteratorBase<
161 MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>
162 {
163 ChildIter() {}
164 ChildIter(const MaskIterT& iter, NodeT* parent): SparseIteratorBase<
165 MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>(iter, parent) {}
166
167 ChildT& getItem(Index pos) const
168 {
169 assert(this->parent().isChildMaskOn(pos));
170 return *(this->parent().getChildNode(pos));
171 }
172
173 // Note: setItem() can't be called on const iterators.
174 void setItem(Index pos, const ChildT& c) const { this->parent().resetChildNode(pos, &c); }
175
176 // Note: modifyItem() isn't implemented, since it's not useful for child node pointers.
177 };// ChildIter
178
179 // Sparse iterator that visits tile values of an InternNode
180 template<typename NodeT, typename ValueT, typename MaskIterT, typename TagT>
181 struct ValueIter: public SparseIteratorBase<
182 MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>
183 {
184 ValueIter() {}
185 ValueIter(const MaskIterT& iter, NodeT* parent): SparseIteratorBase<
186 MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>(iter, parent) {}
187
188 const ValueT& getItem(Index pos) const { return this->parent().mNodes[pos].getValue(); }
189
190 // Note: setItem() can't be called on const iterators.
191 void setItem(Index pos, const ValueT& v) const { this->parent().mNodes[pos].setValue(v); }
192
193 // Note: modifyItem() can't be called on const iterators.
194 template<typename ModifyOp>
195 void modifyItem(Index pos, const ModifyOp& op) const
196 {
197 op(this->parent().mNodes[pos].getValue());
198 }
199 };// ValueIter
200
201 // Dense iterator that visits both tiles and child nodes of an InternNode
202 template<typename NodeT, typename ChildT, typename ValueT, typename TagT>
203 struct DenseIter: public DenseIteratorBase<
204 MaskDenseIterator, DenseIter<NodeT, ChildT, ValueT, TagT>, NodeT, ChildT, ValueT>
205 {
206 typedef DenseIteratorBase<MaskDenseIterator, DenseIter, NodeT, ChildT, ValueT> BaseT;
207 typedef typename BaseT::NonConstValueType NonConstValueT;
208
209 DenseIter() {}
210 DenseIter(const MaskDenseIterator& iter, NodeT* parent):
211 DenseIteratorBase<MaskDenseIterator, DenseIter, NodeT, ChildT, ValueT>(iter, parent) {}
212
213 bool getItem(Index pos, ChildT*& child, NonConstValueT& value) const
214 {
215 if (this->parent().isChildMaskOn(pos)) {
216 child = this->parent().getChildNode(pos);
217 return true;
218 }
219 child = NULL;
220 value = this->parent().mNodes[pos].getValue();
221 return false;
222 }
223
224 // Note: setItem() can't be called on const iterators.
225 void setItem(Index pos, ChildT* child) const
226 {
227 this->parent().resetChildNode(pos, child);
228 }
229
230 // Note: unsetItem() can't be called on const iterators.
231 void unsetItem(Index pos, const ValueT& value) const
232 {
233 this->parent().unsetChildNode(pos, value);
234 }
235 };// DenseIter
236
237 public:
238 // Iterators (see Iterator.h for usage)
239 typedef ChildIter<InternalNode, ChildNodeType, MaskOnIterator, ChildOn> ChildOnIter;
240 typedef ChildIter<const InternalNode,const ChildNodeType,MaskOnIterator,ChildOn> ChildOnCIter;
241 typedef ValueIter<InternalNode, const ValueType, MaskOffIterator, ChildOff> ChildOffIter;
242 typedef ValueIter<const InternalNode,const ValueType,MaskOffIterator,ChildOff> ChildOffCIter;
243 typedef DenseIter<InternalNode, ChildNodeType, ValueType, ChildAll> ChildAllIter;
244 typedef DenseIter<const InternalNode,const ChildNodeType, ValueType, ChildAll> ChildAllCIter;
245
246 typedef ValueIter<InternalNode, const ValueType, MaskOnIterator, ValueOn> ValueOnIter;
247 typedef ValueIter<const InternalNode,const ValueType,MaskOnIterator,ValueOn> ValueOnCIter;
248 typedef ValueIter<InternalNode, const ValueType, MaskOffIterator, ValueOff> ValueOffIter;
249 typedef ValueIter<const InternalNode,const ValueType,MaskOffIterator,ValueOff> ValueOffCIter;
250 typedef ValueIter<InternalNode, const ValueType, MaskOffIterator, ValueAll> ValueAllIter;
251 typedef ValueIter<const InternalNode,const ValueType,MaskOffIterator,ValueAll> ValueAllCIter;
252
253 ChildOnCIter cbeginChildOn() const { return ChildOnCIter(mChildMask.beginOn(), this); }
254 ChildOffCIter cbeginChildOff() const { return ChildOffCIter(mChildMask.beginOff(), this); }
255 ChildAllCIter cbeginChildAll() const { return ChildAllCIter(mChildMask.beginDense(), this); }
256 ChildOnCIter beginChildOn() const { return cbeginChildOn(); }
257 ChildOffCIter beginChildOff() const { return cbeginChildOff(); }
258 ChildAllCIter beginChildAll() const { return cbeginChildAll(); }
259 ChildOnIter beginChildOn() { return ChildOnIter(mChildMask.beginOn(), this); }
260 ChildOffIter beginChildOff() { return ChildOffIter(mChildMask.beginOff(), this); }
261 ChildAllIter beginChildAll() { return ChildAllIter(mChildMask.beginDense(), this); }
262
263 ValueOnCIter cbeginValueOn() const { return ValueOnCIter(mValueMask.beginOn(), this); }
265 ValueOffCIter cbeginValueOff() const { return ValueOffCIter(mValueMask.beginOff(), this); }
266 ValueAllCIter cbeginValueAll() const { return ValueAllCIter(mChildMask.beginOff(), this); }
267 ValueOnCIter beginValueOn() const { return cbeginValueOn(); }
269 ValueOffCIter beginValueOff() const { return cbeginValueOff(); }
270 ValueAllCIter beginValueAll() const { return cbeginValueAll(); }
271 ValueOnIter beginValueOn() { return ValueOnIter(mValueMask.beginOn(), this); }
273 ValueOffIter beginValueOff() { return ValueOffIter(mValueMask.beginOff(), this); }
274 ValueAllIter beginValueAll() { return ValueAllIter(mChildMask.beginOff(), this); }
275
276
279 static Index dim() { return DIM; }
282 static Index getLevel() { return LEVEL; }
285 static void getNodeLog2Dims(std::vector<Index>& dims);
289 static Index getChildDim() { return ChildNodeType::DIM; }
290
292 static Index coordToOffset(const Coord& xyz);
295 static void offsetToLocalCoord(Index n, Coord& xyz);
297 Coord offsetToGlobalCoord(Index n) const;
298
300 const Coord& origin() const { return mOrigin; }
302 void setOrigin(const Coord& origin) { mOrigin = origin; }
303
304 Index32 leafCount() const;
305 Index32 nonLeafCount() const;
306 Index64 onVoxelCount() const;
307 Index64 offVoxelCount() const;
308 Index64 onLeafVoxelCount() const;
309 Index64 offLeafVoxelCount() const;
310 Index64 onTileCount() const;
311
313 Index64 memUsage() const;
314
319 void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const;
320
323 CoordBBox getNodeBoundingBox() const { return CoordBBox::createCube(mOrigin, DIM); }
324
326 bool isEmpty() const { return mChildMask.isOff(); }
327
333 bool isConstant(ValueType& firstValue, bool& state,
334 const ValueType& tolerance = zeroVal<ValueType>()) const;
335
350 bool isConstant(ValueType& minValue, ValueType& maxValue,
351 bool& state, const ValueType& tolerance = zeroVal<ValueType>()) const;
352
354 bool isInactive() const { return this->isChildMaskOff() && this->isValueMaskOff(); }
355
357 bool isValueOn(const Coord& xyz) const;
359 bool isValueOn(Index offset) const { return mValueMask.isOn(offset); }
360
362 bool hasActiveTiles() const;
363
364 const ValueType& getValue(const Coord& xyz) const;
365 bool probeValue(const Coord& xyz, ValueType& value) const;
366
369 Index getValueLevel(const Coord& xyz) const;
370
373 const ValueType& getFirstValue() const;
376 const ValueType& getLastValue() const;
377
379 void setActiveState(const Coord& xyz, bool on);
381 void setValueOnly(const Coord& xyz, const ValueType& value);
383 void setValueOn(const Coord& xyz);
385 void setValueOn(const Coord& xyz, const ValueType& value);
387 void setValueOff(const Coord& xyz);
389 void setValueOff(const Coord& xyz, const ValueType& value);
390
393 template<typename ModifyOp>
394 void modifyValue(const Coord& xyz, const ModifyOp& op);
396 template<typename ModifyOp>
397 void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op);
398
403 template<typename AccessorT>
404 const ValueType& getValueAndCache(const Coord& xyz, AccessorT&) const;
405
410 template<typename AccessorT>
411 bool isValueOnAndCache(const Coord& xyz, AccessorT&) const;
412
417 template<typename AccessorT>
418 void setValueAndCache(const Coord& xyz, const ValueType& value, AccessorT&);
419
424 template<typename AccessorT>
425 void setValueOnlyAndCache(const Coord& xyz, const ValueType& value, AccessorT&);
426
432 template<typename ModifyOp, typename AccessorT>
433 void modifyValueAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&);
434
439 template<typename ModifyOp, typename AccessorT>
440 void modifyValueAndActiveStateAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&);
441
446 template<typename AccessorT>
447 void setValueOffAndCache(const Coord& xyz, const ValueType& value, AccessorT&);
448
453 template<typename AccessorT>
454 void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT&);
455
461 template<typename AccessorT>
462 bool probeValueAndCache(const Coord& xyz, ValueType& value, AccessorT&) const;
463
470 template<typename AccessorT>
471 Index getValueLevelAndCache(const Coord& xyz, AccessorT&) const;
472
474 void setValuesOn();
475
476 //
477 // I/O
478 //
479 void writeTopology(std::ostream&, bool toHalf = false) const;
480 void readTopology(std::istream&, bool fromHalf = false);
481 void writeBuffers(std::ostream&, bool toHalf = false) const;
482 void readBuffers(std::istream&, bool fromHalf = false);
483 void readBuffers(std::istream&, const CoordBBox&, bool fromHalf = false);
484
485
486 //
487 // Aux methods
488 //
489
498 void fill(const CoordBBox& bbox, const ValueType& value, bool active = true);
499
502 void negate();
503
506 void voxelizeActiveTiles(bool threaded = true);
507
515 template<typename DenseT>
516 void copyToDense(const CoordBBox& bbox, DenseT& dense) const;
517
520 template<MergePolicy Policy>
521 void merge(InternalNode& other, const ValueType& background, const ValueType& otherBackground);
522
525 template<MergePolicy Policy> void merge(const ValueType& tileValue, bool tileActive);
526
539 template<typename OtherChildNodeType>
540 void topologyUnion(const InternalNode<OtherChildNodeType, Log2Dim>& other);
541
555 template<typename OtherChildNodeType>
556 void topologyIntersection(const InternalNode<OtherChildNodeType, Log2Dim>& other,
557 const ValueType& background);
558
570 template<typename OtherChildNodeType>
571 void topologyDifference(const InternalNode<OtherChildNodeType, Log2Dim>& other,
572 const ValueType& background);
573
574 template<typename CombineOp>
575 void combine(InternalNode& other, CombineOp&);
576 template<typename CombineOp>
577 void combine(const ValueType& value, bool valueIsActive, CombineOp&);
578
579 template<typename CombineOp, typename OtherNodeType /*= InternalNode*/>
580 void combine2(const InternalNode& other0, const OtherNodeType& other1, CombineOp&);
581 template<typename CombineOp, typename OtherNodeType /*= InternalNode*/>
582 void combine2(const ValueType& value, const OtherNodeType& other, bool valIsActive, CombineOp&);
583 template<typename CombineOp, typename OtherValueType>
584 void combine2(const InternalNode& other, const OtherValueType&, bool valIsActive, CombineOp&);
585
591 template<typename BBoxOp> void visitActiveBBox(BBoxOp&) const;
592
593 template<typename VisitorOp> void visit(VisitorOp&);
594 template<typename VisitorOp> void visit(VisitorOp&) const;
595
596 template<typename OtherNodeType, typename VisitorOp>
597 void visit2Node(OtherNodeType& other, VisitorOp&);
598 template<typename OtherNodeType, typename VisitorOp>
599 void visit2Node(OtherNodeType& other, VisitorOp&) const;
600 template<typename IterT, typename VisitorOp>
601 void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false);
602 template<typename IterT, typename VisitorOp>
603 void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false) const;
604
606 void clip(const CoordBBox&, const ValueType& background);
607
611 void prune(const ValueType& tolerance = zeroVal<ValueType>());
612
615 void addLeaf(LeafNodeType* leaf);
616
619 template<typename AccessorT>
620 void addLeafAndCache(LeafNodeType* leaf, AccessorT&);
621
630 template<typename NodeT>
631 NodeT* stealNode(const Coord& xyz, const ValueType& value, bool state);
632
635 void addTile(Index level, const Coord& xyz, const ValueType& value, bool state);
636
638 void addTile(Index offset, const ValueType& value, bool state);
639
642 template<typename AccessorT>
643 void addTileAndCache(Index level, const Coord& xyz, const ValueType&, bool state, AccessorT&);
644
646 template<typename NodeType> NodeType* probeNode(const Coord& xyz);
649 template<typename NodeType> const NodeType* probeConstNode(const Coord& xyz) const;
651
653 template<typename NodeType, typename AccessorT>
656 NodeType* probeNodeAndCache(const Coord& xyz, AccessorT&);
657 template<typename NodeType, typename AccessorT>
658 const NodeType* probeConstNodeAndCache(const Coord& xyz, AccessorT&) const;
660
662 LeafNodeType* probeLeaf(const Coord& xyz);
665 const LeafNodeType* probeConstLeaf(const Coord& xyz) const;
666 const LeafNodeType* probeLeaf(const Coord& xyz) const;
668
670 template<typename AccessorT>
673 LeafNodeType* probeLeafAndCache(const Coord& xyz, AccessorT& acc);
674 template<typename AccessorT>
675 const LeafNodeType* probeConstLeafAndCache(const Coord& xyz, AccessorT& acc) const;
676 template<typename AccessorT>
677 const LeafNodeType* probeLeafAndCache(const Coord& xyz, AccessorT& acc) const;
679
686 LeafNodeType* touchLeaf(const Coord& xyz);
687
690 template<typename AccessorT>
691 LeafNodeType* touchLeafAndCache(const Coord& xyz, AccessorT&);
692
694 template<typename ArrayT>
717 void getNodes(ArrayT& array);
718 template<typename ArrayT>
719 void getNodes(ArrayT& array) const;
721
745 template<typename ArrayT>
746 void stealNodes(ArrayT& array, const ValueType& value, bool state);
747
750 void resetBackground(const ValueType& oldBackground, const ValueType& newBackground);
751
754 template<typename OtherChildNodeType, Index OtherLog2Dim>
755 bool hasSameTopology(const InternalNode<OtherChildNodeType, OtherLog2Dim>* other) const;
756
757 protected:
759 friend class IteratorBase<MaskOnIterator, InternalNode>;
762 friend class IteratorBase<MaskOffIterator, InternalNode>;
763 friend class IteratorBase<MaskDenseIterator, InternalNode>;
765
768 template<typename, Index> friend class InternalNode;
769
770 // Mask accessors
771 public:
772 bool isValueMaskOn(Index n) const { return mValueMask.isOn(n); }
773 bool isValueMaskOn() const { return mValueMask.isOn(); }
774 bool isValueMaskOff(Index n) const { return mValueMask.isOff(n); }
775 bool isValueMaskOff() const { return mValueMask.isOff(); }
776 bool isChildMaskOn(Index n) const { return mChildMask.isOn(n); }
777 bool isChildMaskOff(Index n) const { return mChildMask.isOff(n); }
778 bool isChildMaskOff() const { return mChildMask.isOff(); }
779 const NodeMaskType& getValueMask() const { return mValueMask; }
780 const NodeMaskType& getChildMask() const { return mChildMask; }
781 NodeMaskType getValueOffMask() const
782 {
783 NodeMaskType mask = mValueMask;
784 mask |= mChildMask;
785 mask.toggle();
786 return mask;
787 }
788 const UnionType* getTable() const { return mNodes; }
789 protected:
791 void setValueMask(Index n, bool on) { mValueMask.set(n, mChildMask.isOn(n) ? false : on); }
795
796 void makeChildNodeEmpty(Index n, const ValueType& value);
797 void setChildNode( Index i, ChildNodeType* child);//assumes a tile
798 void resetChildNode(Index i, ChildNodeType* child);//checks for an existing child
799 ChildNodeType* unsetChildNode(Index i, const ValueType& value);
800
801 template<typename NodeT, typename VisitorOp, typename ChildAllIterT>
802 static inline void doVisit(NodeT&, VisitorOp&);
803
804 template<typename NodeT, typename OtherNodeT, typename VisitorOp,
805 typename ChildAllIterT, typename OtherChildAllIterT>
806 static inline void doVisit2Node(NodeT&, OtherNodeT&, VisitorOp&);
807
808 template<typename NodeT, typename VisitorOp,
809 typename ChildAllIterT, typename OtherChildAllIterT>
810 static inline void doVisit2(NodeT&, OtherChildAllIterT&, VisitorOp&, bool otherIsLHS);
811
816 ChildNodeType* getChildNode(Index n);
817 const ChildNodeType* getChildNode(Index n) const;
819
822 struct VoxelizeActiveTiles;
823 template<typename OtherInternalNode> struct DeepCopy;
824 template<typename OtherInternalNode> struct TopologyCopy1;
825 template<typename OtherInternalNode> struct TopologyCopy2;
826 template<typename OtherInternalNode> struct TopologyUnion;
827 template<typename OtherInternalNode> struct TopologyDifference;
828 template<typename OtherInternalNode> struct TopologyIntersection;
830
831 UnionType mNodes[NUM_VALUES];
832 NodeMaskType mChildMask, mValueMask;
834 Coord mOrigin;
835 }; // class InternalNode
836
837
839
840
842 template<typename ChildT1, Index Dim1, typename NodeT2>
845 struct SameInternalConfig {
846 static const bool value = false;
847 };
848
849 template<typename ChildT1, Index Dim1, typename ChildT2>
850 struct SameInternalConfig<ChildT1, Dim1, InternalNode<ChildT2, Dim1> > {
851 static const bool value = ChildT1::template SameConfiguration<ChildT2>::value;
852 };
854
855
857
858
859 template<typename ChildT, Index Log2Dim>
860 inline
861 InternalNode<ChildT, Log2Dim>::InternalNode(const ValueType& background)
862 {
863 for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(background);
864 }
865
866
867 template<typename ChildT, Index Log2Dim>
868 inline
869 InternalNode<ChildT, Log2Dim>::InternalNode(const Coord& origin, const ValueType& val, bool active):
870 mOrigin(origin[0] & ~(DIM - 1), // zero out the low-order bits
871 origin[1] & ~(DIM - 1),
872 origin[2] & ~(DIM - 1))
873 {
874 if (active) mValueMask.setOn();
875 for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(val);
876 }
877
878
879 #ifndef OPENVDB_2_ABI_COMPATIBLE
880 // For InternalNodes, the PartialCreate constructor is identical to its
881 // non-PartialCreate counterpart.
882 template<typename ChildT, Index Log2Dim>
883 inline
884 InternalNode<ChildT, Log2Dim>::InternalNode(PartialCreate,
885 const Coord& origin, const ValueType& val, bool active)
886 : mOrigin(origin[0] & ~(DIM-1), origin[1] & ~(DIM-1), origin[2] & ~(DIM-1))
887 {
888 if (active) mValueMask.setOn();
889 for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(val);
890 }
891 #endif
892
893 template<typename ChildT, Index Log2Dim>
894 template<typename OtherInternalNode>
895 struct InternalNode<ChildT, Log2Dim>::DeepCopy
896 {
897 DeepCopy(const OtherInternalNode* source, InternalNode* target) : s(source), t(target) {
898 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this);
899 //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//serial
900 }
901 void operator()(const tbb::blocked_range<Index> &r) const {
902 for (Index i = r.begin(), end=r.end(); i!=end; ++i) {
903 if (s->mChildMask.isOff(i)) {
904 t->mNodes[i].setValue(ValueType(s->mNodes[i].getValue()));
905 } else {
906 t->mNodes[i].setChild(new ChildNodeType(*(s->mNodes[i].getChild())));
907 }
908 }
909 }
910 const OtherInternalNode* s;
911 InternalNode* t;
912 };// DeepCopy
913
914 template<typename ChildT, Index Log2Dim>
915 inline
916 InternalNode<ChildT, Log2Dim>::InternalNode(const InternalNode& other):
917 mChildMask(other.mChildMask),
918 mValueMask(other.mValueMask),
919 mOrigin(other.mOrigin)
920 {
921 DeepCopy<InternalNode<ChildT, Log2Dim> > tmp(&other, this);
922 }
923
924
925 // Copy-construct from a node with the same configuration but a different ValueType.
926 template<typename ChildT, Index Log2Dim>
927 template<typename OtherChildNodeType>
928 inline
929 InternalNode<ChildT, Log2Dim>::InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other)
930 : mChildMask(other.mChildMask)
931 , mValueMask(other.mValueMask)
932 , mOrigin(other.mOrigin)
933 {
934 DeepCopy<InternalNode<OtherChildNodeType, Log2Dim> > tmp(&other, this);
935 }
936
937 template<typename ChildT, Index Log2Dim>
938 template<typename OtherInternalNode>
939 struct InternalNode<ChildT, Log2Dim>::TopologyCopy1
940 {
941 TopologyCopy1(const OtherInternalNode* source, InternalNode* target,
942 const ValueType& background) : s(source), t(target), b(background) {
943 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this);
944 //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//serial
945 }
946 void operator()(const tbb::blocked_range<Index> &r) const {
947 for (Index i = r.begin(), end=r.end(); i!=end; ++i) {
948 if (s->isChildMaskOn(i)) {
949 t->mNodes[i].setChild(new ChildNodeType(*(s->mNodes[i].getChild()),
950 b, TopologyCopy()));
951 } else {
952 t->mNodes[i].setValue(b);
953 }
954 }
955 }
956 const OtherInternalNode* s;
957 InternalNode* t;
958 const ValueType &b;
959 };// TopologyCopy1
960
961 template<typename ChildT, Index Log2Dim>
962 template<typename OtherChildNodeType>
963 inline
964 InternalNode<ChildT, Log2Dim>::InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other,
965 const ValueType& background, TopologyCopy):
966 mChildMask(other.mChildMask),
967 mValueMask(other.mValueMask),
968 mOrigin(other.mOrigin)
969 {
970 TopologyCopy1<InternalNode<OtherChildNodeType, Log2Dim> > tmp(&other, this, background);
971 }
972
973 template<typename ChildT, Index Log2Dim>
974 template<typename OtherInternalNode>
975 struct InternalNode<ChildT, Log2Dim>::TopologyCopy2
976 {
977 TopologyCopy2(const OtherInternalNode* source, InternalNode* target,
978 const ValueType& offValue, const ValueType& onValue)
979 : s(source), t(target), offV(offValue), onV(onValue) {
980 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this);
981 }
982 void operator()(const tbb::blocked_range<Index> &r) const {
983 for (Index i = r.begin(), end=r.end(); i!=end; ++i) {
984 if (s->isChildMaskOn(i)) {
985 t->mNodes[i].setChild(new ChildNodeType(*(s->mNodes[i].getChild()),
986 offV, onV, TopologyCopy()));
987 } else {
988 t->mNodes[i].setValue(s->isValueMaskOn(i) ? onV : offV);
989 }
990 }
991 }
992 const OtherInternalNode* s;
993 InternalNode* t;
994 const ValueType &offV, &onV;
995 };// TopologyCopy2
996
997 template<typename ChildT, Index Log2Dim>
998 template<typename OtherChildNodeType>
999 inline
1000 InternalNode<ChildT, Log2Dim>::InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other,
1001 const ValueType& offValue,
1002 const ValueType& onValue, TopologyCopy):
1003 mChildMask(other.mChildMask),
1004 mValueMask(other.mValueMask),
1005 mOrigin(other.mOrigin)
1006 {
1007 TopologyCopy2<InternalNode<OtherChildNodeType, Log2Dim> > tmp(&other, this, offValue, onValue);
1008 }
1009
1010
1011 template<typename ChildT, Index Log2Dim>
1012 inline
1013 InternalNode<ChildT, Log2Dim>::~InternalNode()
1014 {
1015 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1016 delete mNodes[iter.pos()].getChild();
1017 }
1018 }
1019
1020
1022
1023
1024 template<typename ChildT, Index Log2Dim>
1025 inline Index32
1026 InternalNode<ChildT, Log2Dim>::leafCount() const
1027 {
1028 if (ChildNodeType::getLevel() == 0) return mChildMask.countOn();
1029 Index32 sum = 0;
1030 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1031 sum += iter->leafCount();
1032 }
1033 return sum;
1034 }
1035
1036
1037 template<typename ChildT, Index Log2Dim>
1038 inline Index32
1039 InternalNode<ChildT, Log2Dim>::nonLeafCount() const
1040 {
1041 Index32 sum = 1;
1042 if (ChildNodeType::getLevel() == 0) return sum;
1043 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1044 sum += iter->nonLeafCount();
1045 }
1046 return sum;
1047 }
1048
1049
1050 template<typename ChildT, Index Log2Dim>
1051 inline Index64
1052 InternalNode<ChildT, Log2Dim>::onVoxelCount() const
1053 {
1054 Index64 sum = ChildT::NUM_VOXELS * mValueMask.countOn();
1055 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1056 sum += iter->onVoxelCount();
1057 }
1058 return sum;
1059 }
1060
1061
1062 template<typename ChildT, Index Log2Dim>
1063 inline Index64
1064 InternalNode<ChildT, Log2Dim>::offVoxelCount() const
1065 {
1066 Index64 sum = ChildT::NUM_VOXELS * (NUM_VALUES-mValueMask.countOn()-mChildMask.countOn());
1067 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1068 sum += iter->offVoxelCount();
1069 }
1070 return sum;
1071 }
1072
1073
1074 template<typename ChildT, Index Log2Dim>
1075 inline Index64
1076 InternalNode<ChildT, Log2Dim>::onLeafVoxelCount() const
1077 {
1078 Index64 sum = 0;
1079 for (ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1080 sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount();
1081 }
1082 return sum;
1083 }
1084
1085
1086 template<typename ChildT, Index Log2Dim>
1087 inline Index64
1088 InternalNode<ChildT, Log2Dim>::offLeafVoxelCount() const
1089 {
1090 Index64 sum = 0;
1091 for (ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1092 sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount();
1093 }
1094 return sum;
1095 }
1096
1097 template<typename ChildT, Index Log2Dim>
1098 inline Index64
1099 InternalNode<ChildT, Log2Dim>::onTileCount() const
1100 {
1101 Index64 sum = mValueMask.countOn();
1102 for (ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) {
1103 sum += iter->onTileCount();
1104 }
1105 return sum;
1106 }
1107
1108 template<typename ChildT, Index Log2Dim>
1109 inline Index64
1110 InternalNode<ChildT, Log2Dim>::memUsage() const
1111 {
1112 Index64 sum = NUM_VALUES * sizeof(UnionType) + mChildMask.memUsage()
1113 + mValueMask.memUsage() + sizeof(mOrigin);
1114 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1115 sum += iter->memUsage();
1116 }
1117 return sum;
1118 }
1119
1120
1121 template<typename ChildT, Index Log2Dim>
1122 inline void
1123 InternalNode<ChildT, Log2Dim>::evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels) const
1124 {
1125 if (bbox.isInside(this->getNodeBoundingBox())) return;
1126
1127 for (ValueOnCIter i = this->cbeginValueOn(); i; ++i) {
1128 bbox.expand(i.getCoord(), ChildT::DIM);
1129 }
1130 for (ChildOnCIter i = this->cbeginChildOn(); i; ++i) {
1131 i->evalActiveBoundingBox(bbox, visitVoxels);
1132 }
1133 }
1134
1135
1137
1138
1139 template<typename ChildT, Index Log2Dim>
1140 inline void
1141 InternalNode<ChildT, Log2Dim>::prune(const ValueType& tolerance)
1142 {
1143 bool state = false;
1144 ValueType value = zeroVal<ValueType>();
1145 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1146 const Index i = iter.pos();
1147 ChildT* child = mNodes[i].getChild();
1148 child->prune(tolerance);
1149 if (child->isConstant(value, state, tolerance)) {
1150 delete child;
1151 mChildMask.setOff(i);
1152 mValueMask.set(i, state);
1153 mNodes[i].setValue(value);
1154 }
1155 }
1156 }
1157
1158
1160
1161
1162 template<typename ChildT, Index Log2Dim>
1163 template<typename NodeT>
1164 inline NodeT*
1165 InternalNode<ChildT, Log2Dim>::stealNode(const Coord& xyz, const ValueType& value, bool state)
1166 {
1167 if ((NodeT::LEVEL == ChildT::LEVEL && !(boost::is_same<NodeT, ChildT>::value)) ||
1168 NodeT::LEVEL > ChildT::LEVEL) return NULL;
1169 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
1170 const Index n = this->coordToOffset(xyz);
1171 if (mChildMask.isOff(n)) return NULL;
1172 ChildT* child = mNodes[n].getChild();
1173 if (boost::is_same<NodeT, ChildT>::value) {
1174 mChildMask.setOff(n);
1175 mValueMask.set(n, state);
1176 mNodes[n].setValue(value);
1177 }
1178 return (boost::is_same<NodeT, ChildT>::value)
1179 ? reinterpret_cast<NodeT*>(child)
1180 : child->template stealNode<NodeT>(xyz, value, state);
1181 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
1182 }
1183
1184
1186
1187
1188 template<typename ChildT, Index Log2Dim>
1189 template<typename NodeT>
1190 inline NodeT*
1191 InternalNode<ChildT, Log2Dim>::probeNode(const Coord& xyz)
1192 {
1193 if ((NodeT::LEVEL == ChildT::LEVEL && !(boost::is_same<NodeT, ChildT>::value)) ||
1194 NodeT::LEVEL > ChildT::LEVEL) return NULL;
1195 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
1196 const Index n = this->coordToOffset(xyz);
1197 if (mChildMask.isOff(n)) return NULL;
1198 ChildT* child = mNodes[n].getChild();
1199 return (boost::is_same<NodeT, ChildT>::value)
1200 ? reinterpret_cast<NodeT*>(child)
1201 : child->template probeNode<NodeT>(xyz);
1202 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
1203 }
1204
1205
1206 template<typename ChildT, Index Log2Dim>
1207 template<typename NodeT, typename AccessorT>
1208 inline NodeT*
1209 InternalNode<ChildT, Log2Dim>::probeNodeAndCache(const Coord& xyz, AccessorT& acc)
1210 {
1211 if ((NodeT::LEVEL == ChildT::LEVEL && !(boost::is_same<NodeT, ChildT>::value)) ||
1212 NodeT::LEVEL > ChildT::LEVEL) return NULL;
1213 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
1214 const Index n = this->coordToOffset(xyz);
1215 if (mChildMask.isOff(n)) return NULL;
1216 ChildT* child = mNodes[n].getChild();
1217 acc.insert(xyz, child);
1218 return (boost::is_same<NodeT, ChildT>::value)
1219 ? reinterpret_cast<NodeT*>(child)
1220 : child->template probeNodeAndCache<NodeT>(xyz, acc);
1221 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
1222 }
1223
1224
1225 template<typename ChildT, Index Log2Dim>
1226 template<typename NodeT>
1227 inline const NodeT*
1228 InternalNode<ChildT, Log2Dim>::probeConstNode(const Coord& xyz) const
1229 {
1230 if ((NodeT::LEVEL == ChildT::LEVEL && !(boost::is_same<NodeT, ChildT>::value)) ||
1231 NodeT::LEVEL > ChildT::LEVEL) return NULL;
1232 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
1233 const Index n = this->coordToOffset(xyz);
1234 if (mChildMask.isOff(n)) return NULL;
1235 const ChildT* child = mNodes[n].getChild();
1236 return (boost::is_same<NodeT, ChildT>::value)
1237 ? reinterpret_cast<const NodeT*>(child)
1238 : child->template probeConstNode<NodeT>(xyz);
1239 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
1240 }
1241
1242
1243 template<typename ChildT, Index Log2Dim>
1244 template<typename NodeT, typename AccessorT>
1245 inline const NodeT*
1246 InternalNode<ChildT, Log2Dim>::probeConstNodeAndCache(const Coord& xyz, AccessorT& acc) const
1247 {
1248 if ((NodeT::LEVEL == ChildT::LEVEL && !(boost::is_same<NodeT, ChildT>::value)) ||
1249 NodeT::LEVEL > ChildT::LEVEL) return NULL;
1250 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
1251 const Index n = this->coordToOffset(xyz);
1252 if (mChildMask.isOff(n)) return NULL;
1253 const ChildT* child = mNodes[n].getChild();
1254 acc.insert(xyz, child);
1255 return (boost::is_same<NodeT, ChildT>::value)
1256 ? reinterpret_cast<const NodeT*>(child)
1257 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
1258 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
1259 }
1260
1261
1263
1264
1265 template<typename ChildT, Index Log2Dim>
1266 inline typename ChildT::LeafNodeType*
1267 InternalNode<ChildT, Log2Dim>::probeLeaf(const Coord& xyz)
1268 {
1269 return this->template probeNode<LeafNodeType>(xyz);
1270 }
1271
1272
1273 template<typename ChildT, Index Log2Dim>
1274 template<typename AccessorT>
1275 inline typename ChildT::LeafNodeType*
1276 InternalNode<ChildT, Log2Dim>::probeLeafAndCache(const Coord& xyz, AccessorT& acc)
1277 {
1278 return this->template probeNodeAndCache<LeafNodeType>(xyz, acc);
1279 }
1280
1281
1282 template<typename ChildT, Index Log2Dim>
1283 template<typename AccessorT>
1284 inline const typename ChildT::LeafNodeType*
1285 InternalNode<ChildT, Log2Dim>::probeLeafAndCache(const Coord& xyz, AccessorT& acc) const
1286 {
1287 return this->probeConstLeafAndCache(xyz, acc);
1288 }
1289
1290
1291 template<typename ChildT, Index Log2Dim>
1292 inline const typename ChildT::LeafNodeType*
1293 InternalNode<ChildT, Log2Dim>::probeConstLeaf(const Coord& xyz) const
1294 {
1295 return this->template probeConstNode<LeafNodeType>(xyz);
1296 }
1297
1298
1299 template<typename ChildT, Index Log2Dim>
1300 template<typename AccessorT>
1301 inline const typename ChildT::LeafNodeType*
1302 InternalNode<ChildT, Log2Dim>::probeConstLeafAndCache(const Coord& xyz, AccessorT& acc) const
1303 {
1304 return this->template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
1305 }
1306
1307
1309
1310
1311 template<typename ChildT, Index Log2Dim>
1312 inline void
1313 InternalNode<ChildT, Log2Dim>::addLeaf(LeafNodeType* leaf)
1314 {
1315 assert(leaf != NULL);
1316 const Coord& xyz = leaf->origin();
1317 const Index n = this->coordToOffset(xyz);
1318 ChildT* child = NULL;
1319 if (mChildMask.isOff(n)) {
1320 if (ChildT::LEVEL>0) {
1321 child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1322 } else {
1323 child = reinterpret_cast<ChildT*>(leaf);
1324 }
1325 this->setChildNode(n, child);
1326 } else {
1327 if (ChildT::LEVEL>0) {
1328 child = mNodes[n].getChild();
1329 } else {
1330 delete mNodes[n].getChild();
1331 child = reinterpret_cast<ChildT*>(leaf);
1332 mNodes[n].setChild(child);
1333 }
1334 }
1335 child->addLeaf(leaf);
1336 }
1337
1338
1339 template<typename ChildT, Index Log2Dim>
1340 template<typename AccessorT>
1341 inline void
1342 InternalNode<ChildT, Log2Dim>::addLeafAndCache(LeafNodeType* leaf, AccessorT& acc)
1343 {
1344 assert(leaf != NULL);
1345 const Coord& xyz = leaf->origin();
1346 const Index n = this->coordToOffset(xyz);
1347 ChildT* child = NULL;
1348 if (mChildMask.isOff(n)) {
1349 if (ChildT::LEVEL>0) {
1350 child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1351 acc.insert(xyz, child);//we only cache internal nodes
1352 } else {
1353 child = reinterpret_cast<ChildT*>(leaf);
1354 }
1355 this->setChildNode(n, child);
1356 } else {
1357 if (ChildT::LEVEL>0) {
1358 child = mNodes[n].getChild();
1359 acc.insert(xyz, child);//we only cache internal nodes
1360 } else {
1361 delete mNodes[n].getChild();
1362 child = reinterpret_cast<ChildT*>(leaf);
1363 mNodes[n].setChild(child);
1364 }
1365 }
1366 child->addLeafAndCache(leaf, acc);
1367 }
1368
1369
1371
1372
1373 template<typename ChildT, Index Log2Dim>
1374 inline void
1375 InternalNode<ChildT, Log2Dim>::addTile(Index n, const ValueType& value, bool state)
1376 {
1377 assert(n < NUM_VALUES);
1378 this->makeChildNodeEmpty(n, value);
1379 mValueMask.set(n, state);
1380 }
1381
1382
1383 template<typename ChildT, Index Log2Dim>
1384 inline void
1385 InternalNode<ChildT, Log2Dim>::addTile(Index level, const Coord& xyz,
1386 const ValueType& value, bool state)
1387 {
1388 if (LEVEL >= level) {
1389 const Index n = this->coordToOffset(xyz);
1390 if (mChildMask.isOff(n)) {// tile case
1391 if (LEVEL > level) {
1392 ChildT* child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1393 this->setChildNode(n, child);
1394 child->addTile(level, xyz, value, state);
1395 } else {
1396 mValueMask.set(n, state);
1397 mNodes[n].setValue(value);
1398 }
1399 } else {// child branch case
1400 ChildT* child = mNodes[n].getChild();
1401 if (LEVEL > level) {
1402 child->addTile(level, xyz, value, state);
1403 } else {
1404 delete child;
1405 mChildMask.setOff(n);
1406 mValueMask.set(n, state);
1407 mNodes[n].setValue(value);
1408 }
1409 }
1410 }
1411 }
1412
1413
1414 template<typename ChildT, Index Log2Dim>
1415 template<typename AccessorT>
1416 inline void
1417 InternalNode<ChildT, Log2Dim>::addTileAndCache(Index level, const Coord& xyz,
1418 const ValueType& value, bool state, AccessorT& acc)
1419 {
1420 if (LEVEL >= level) {
1421 const Index n = this->coordToOffset(xyz);
1422 if (mChildMask.isOff(n)) {// tile case
1423 if (LEVEL > level) {
1424 ChildT* child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1425 this->setChildNode(n, child);
1426 acc.insert(xyz, child);
1427 child->addTileAndCache(level, xyz, value, state, acc);
1428 } else {
1429 mValueMask.set(n, state);
1430 mNodes[n].setValue(value);
1431 }
1432 } else {// child branch case
1433 ChildT* child = mNodes[n].getChild();
1434 if (LEVEL > level) {
1435 acc.insert(xyz, child);
1436 child->addTileAndCache(level, xyz, value, state, acc);
1437 } else {
1438 delete child;
1439 mChildMask.setOff(n);
1440 mValueMask.set(n, state);
1441 mNodes[n].setValue(value);
1442 }
1443 }
1444 }
1445 }
1446
1447
1449
1450
1451 template<typename ChildT, Index Log2Dim>
1452 inline typename ChildT::LeafNodeType*
1453 InternalNode<ChildT, Log2Dim>::touchLeaf(const Coord& xyz)
1454 {
1455 const Index n = this->coordToOffset(xyz);
1456 ChildT* child = NULL;
1457 if (mChildMask.isOff(n)) {
1458 child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1459 this->setChildNode(n, child);
1460 } else {
1461 child = mNodes[n].getChild();
1462 }
1463 return child->touchLeaf(xyz);
1464 }
1465
1466
1467 template<typename ChildT, Index Log2Dim>
1468 template<typename AccessorT>
1469 inline typename ChildT::LeafNodeType*
1470 InternalNode<ChildT, Log2Dim>::touchLeafAndCache(const Coord& xyz, AccessorT& acc)
1471 {
1472 const Index n = this->coordToOffset(xyz);
1473 if (mChildMask.isOff(n)) {
1474 this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), mValueMask.isOn(n)));
1475 }
1476 acc.insert(xyz, mNodes[n].getChild());
1477 return mNodes[n].getChild()->touchLeafAndCache(xyz, acc);
1478 }
1479
1480
1482
1483
1484 template<typename ChildT, Index Log2Dim>
1485 inline bool
1486 InternalNode<ChildT, Log2Dim>::isConstant(ValueType& firstValue, bool& state,
1487 const ValueType& tolerance) const
1488 {
1489 if (!mChildMask.isOff() || !mValueMask.isConstant(state)) return false;// early termination
1490
1491 firstValue = mNodes[0].getValue();
1492 for (Index i = 1; i < NUM_VALUES; ++i) {
1493 if ( !math::isApproxEqual(mNodes[i].getValue(), firstValue, tolerance) ) return false;// early termination
1494 }
1495 return true;
1496 }
1497
1499
1500
1501 template<typename ChildT, Index Log2Dim>
1502 inline bool
1503 InternalNode<ChildT, Log2Dim>::isConstant(ValueType& minValue,
1504 ValueType& maxValue,
1505 bool& state,
1506 const ValueType& tolerance) const
1507 {
1508
1509 if (!mChildMask.isOff() || !mValueMask.isConstant(state)) return false;// early termination
1510 minValue = maxValue = mNodes[0].getValue();
1511 for (Index i = 1; i < NUM_VALUES; ++i) {
1512 const ValueType& v = mNodes[i].getValue();
1513 if (v < minValue) {
1514 if ((maxValue - v) > tolerance) return false;// early termination
1515 minValue = v;
1516 } else if (v > maxValue) {
1517 if ((v - minValue) > tolerance) return false;// early termination
1518 maxValue = v;
1519 }
1520 }
1521 return true;
1522 }
1523
1524
1526
1527
1528 template<typename ChildT, Index Log2Dim>
1529 inline bool
1530 InternalNode<ChildT, Log2Dim>::hasActiveTiles() const
1531 {
1532 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
1533 const bool anyActiveTiles = !mValueMask.isOff();
1534 if (LEVEL==1 || anyActiveTiles) return anyActiveTiles;
1535 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1536 if (iter->hasActiveTiles()) return true;
1537 }
1538 return false;
1539 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
1540 }
1541
1542
1543 template<typename ChildT, Index Log2Dim>
1544 inline bool
1545 InternalNode<ChildT, Log2Dim>::isValueOn(const Coord& xyz) const
1546 {
1547 const Index n = this->coordToOffset(xyz);
1548 if (this->isChildMaskOff(n)) return this->isValueMaskOn(n);
1549 return mNodes[n].getChild()->isValueOn(xyz);
1550 }
1551
1552 template<typename ChildT, Index Log2Dim>
1553 template<typename AccessorT>
1554 inline bool
1555 InternalNode<ChildT, Log2Dim>::isValueOnAndCache(const Coord& xyz, AccessorT& acc) const
1556 {
1557 const Index n = this->coordToOffset(xyz);
1558 if (this->isChildMaskOff(n)) return this->isValueMaskOn(n);
1559 acc.insert(xyz, mNodes[n].getChild());
1560 return mNodes[n].getChild()->isValueOnAndCache(xyz, acc);
1561 }
1562
1563
1564 template<typename ChildT, Index Log2Dim>
1565 inline const typename ChildT::ValueType&
1566 InternalNode<ChildT, Log2Dim>::getValue(const Coord& xyz) const
1567 {
1568 const Index n = this->coordToOffset(xyz);
1569 return this->isChildMaskOff(n) ? mNodes[n].getValue()
1570 : mNodes[n].getChild()->getValue(xyz);
1571 }
1572
1573 template<typename ChildT, Index Log2Dim>
1574 template<typename AccessorT>
1575 inline const typename ChildT::ValueType&
1576 InternalNode<ChildT, Log2Dim>::getValueAndCache(const Coord& xyz, AccessorT& acc) const
1577 {
1578 const Index n = this->coordToOffset(xyz);
1579 if (this->isChildMaskOn(n)) {
1580 acc.insert(xyz, mNodes[n].getChild());
1581 return mNodes[n].getChild()->getValueAndCache(xyz, acc);
1582 }
1583 return mNodes[n].getValue();
1584 }
1585
1586
1587 template<typename ChildT, Index Log2Dim>
1588 inline Index
1589 InternalNode<ChildT, Log2Dim>::getValueLevel(const Coord& xyz) const
1590 {
1591 const Index n = this->coordToOffset(xyz);
1592 return this->isChildMaskOff(n) ? LEVEL : mNodes[n].getChild()->getValueLevel(xyz);
1593 }
1594
1595 template<typename ChildT, Index Log2Dim>
1596 template<typename AccessorT>
1597 inline Index
1598 InternalNode<ChildT, Log2Dim>::getValueLevelAndCache(const Coord& xyz, AccessorT& acc) const
1599 {
1600 const Index n = this->coordToOffset(xyz);
1601 if (this->isChildMaskOn(n)) {
1602 acc.insert(xyz, mNodes[n].getChild());
1603 return mNodes[n].getChild()->getValueLevelAndCache(xyz, acc);
1604 }
1605 return LEVEL;
1606 }
1607
1608
1609 template<typename ChildT, Index Log2Dim>
1610 inline bool
1611 InternalNode<ChildT, Log2Dim>::probeValue(const Coord& xyz, ValueType& value) const
1612 {
1613 const Index n = this->coordToOffset(xyz);
1614 if (this->isChildMaskOff(n)) {
1615 value = mNodes[n].getValue();
1616 return this->isValueMaskOn(n);
1617 }
1618 return mNodes[n].getChild()->probeValue(xyz, value);
1619 }
1620
1621 template<typename ChildT, Index Log2Dim>
1622 template<typename AccessorT>
1623 inline bool
1624 InternalNode<ChildT, Log2Dim>::probeValueAndCache(const Coord& xyz,
1625 ValueType& value, AccessorT& acc) const
1626 {
1627 const Index n = this->coordToOffset(xyz);
1628 if (this->isChildMaskOn(n)) {
1629 acc.insert(xyz, mNodes[n].getChild());
1630 return mNodes[n].getChild()->probeValueAndCache(xyz, value, acc);
1631 }
1632 value = mNodes[n].getValue();
1633 return this->isValueMaskOn(n);
1634 }
1635
1636
1637 template<typename ChildT, Index Log2Dim>
1638 inline void
1639 InternalNode<ChildT, Log2Dim>::setValueOff(const Coord& xyz)
1640 {
1641 const Index n = this->coordToOffset(xyz);
1642 bool hasChild = this->isChildMaskOn(n);
1643 if (!hasChild && this->isValueMaskOn(n)) {
1644 // If the voxel belongs to a constant tile that is active,
1645 // a child subtree must be constructed.
1646 hasChild = true;
1647 this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), /*active=*/true));
1648 }
1649 if (hasChild) mNodes[n].getChild()->setValueOff(xyz);
1650 }
1651
1652
1653 template<typename ChildT, Index Log2Dim>
1654 inline void
1655 InternalNode<ChildT, Log2Dim>::setValueOn(const Coord& xyz)
1656 {
1657 const Index n = this->coordToOffset(xyz);
1658 bool hasChild = this->isChildMaskOn(n);
1659 if (!hasChild && !this->isValueMaskOn(n)) {
1660 // If the voxel belongs to a constant tile that is inactive,
1661 // a child subtree must be constructed.
1662 hasChild = true;
1663 this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), /*active=*/false));
1664 }
1665 if (hasChild) mNodes[n].getChild()->setValueOn(xyz);
1666 }
1667
1668
1669 template<typename ChildT, Index Log2Dim>
1670 inline void
1671 InternalNode<ChildT, Log2Dim>::setValueOff(const Coord& xyz, const ValueType& value)
1672 {
1673 const Index n = InternalNode::coordToOffset(xyz);
1674 bool hasChild = this->isChildMaskOn(n);
1675 if (!hasChild) {
1676 const bool active = this->isValueMaskOn(n);
1677 if (active || !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1678 // If the voxel belongs to a tile that is either active or that
1679 // has a constant value that is different from the one provided,
1680 // a child subtree must be constructed.
1681 hasChild = true;
1682 this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1683 }
1684 }
1685 if (hasChild) mNodes[n].getChild()->setValueOff(xyz, value);
1686 }
1687
1688 template<typename ChildT, Index Log2Dim>
1689 template<typename AccessorT>
1690 inline void
1691 InternalNode<ChildT, Log2Dim>::setValueOffAndCache(const Coord& xyz,
1692 const ValueType& value, AccessorT& acc)
1693 {
1694 const Index n = InternalNode::coordToOffset(xyz);
1695 bool hasChild = this->isChildMaskOn(n);
1696 if (!hasChild) {
1697 const bool active = this->isValueMaskOn(n);
1698 if (active || !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1699 // If the voxel belongs to a tile that is either active or that
1700 // has a constant value that is different from the one provided,
1701 // a child subtree must be constructed.
1702 hasChild = true;
1703 this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1704 }
1705 }
1706 if (hasChild) {
1707 ChildT* child = mNodes[n].getChild();
1708 acc.insert(xyz, child);
1709 child->setValueOffAndCache(xyz, value, acc);
1710 }
1711 }
1712
1713
1714 template<typename ChildT, Index Log2Dim>
1715 inline void
1716 InternalNode<ChildT, Log2Dim>::setValueOn(const Coord& xyz, const ValueType& value)
1717 {
1718 const Index n = this->coordToOffset(xyz);
1719 bool hasChild = this->isChildMaskOn(n);
1720 if (!hasChild) {
1721 const bool active = this->isValueMaskOn(n); // tile's active state
1722 if (!active || !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1723 // If the voxel belongs to a tile that is either inactive or that
1724 // has a constant value that is different from the one provided,
1725 // a child subtree must be constructed.
1726 hasChild = true;
1727 this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1728 }
1729 }
1730 if (hasChild) mNodes[n].getChild()->setValueOn(xyz, value);
1731 }
1732
1733 template<typename ChildT, Index Log2Dim>
1734 template<typename AccessorT>
1735 inline void
1736 InternalNode<ChildT, Log2Dim>::setValueAndCache(const Coord& xyz,
1737 const ValueType& value, AccessorT& acc)
1738 {
1739 const Index n = this->coordToOffset(xyz);
1740 bool hasChild = this->isChildMaskOn(n);
1741 if (!hasChild) {
1742 const bool active = this->isValueMaskOn(n);
1743 if (!active || !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1744 // If the voxel belongs to a tile that is either inactive or that
1745 // has a constant value that is different from the one provided,
1746 // a child subtree must be constructed.
1747 hasChild = true;
1748 this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1749 }
1750 }
1751 if (hasChild) {
1752 acc.insert(xyz, mNodes[n].getChild());
1753 mNodes[n].getChild()->setValueAndCache(xyz, value, acc);
1754 }
1755 }
1756
1757
1758 template<typename ChildT, Index Log2Dim>
1759 inline void
1760 InternalNode<ChildT, Log2Dim>::setValueOnly(const Coord& xyz, const ValueType& value)
1761 {
1762 const Index n = this->coordToOffset(xyz);
1763 bool hasChild = this->isChildMaskOn(n);
1764 if (!hasChild && !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1765 // If the voxel has a tile value that is different from the one provided,
1766 // a child subtree must be constructed.
1767 const bool active = this->isValueMaskOn(n);
1768 hasChild = true;
1769 this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1770 }
1771 if (hasChild) mNodes[n].getChild()->setValueOnly(xyz, value);
1772 }
1773
1774 template<typename ChildT, Index Log2Dim>
1775 template<typename AccessorT>
1776 inline void
1777 InternalNode<ChildT, Log2Dim>::setValueOnlyAndCache(const Coord& xyz,
1778 const ValueType& value, AccessorT& acc)
1779 {
1780 const Index n = this->coordToOffset(xyz);
1781 bool hasChild = this->isChildMaskOn(n);
1782 if (!hasChild && !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1783 // If the voxel has a tile value that is different from the one provided,
1784 // a child subtree must be constructed.
1785 const bool active = this->isValueMaskOn(n);
1786 hasChild = true;
1787 this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1788 }
1789 if (hasChild) {
1790 acc.insert(xyz, mNodes[n].getChild());
1791 mNodes[n].getChild()->setValueOnlyAndCache(xyz, value, acc);
1792 }
1793 }
1794
1795
1796 template<typename ChildT, Index Log2Dim>
1797 inline void
1798 InternalNode<ChildT, Log2Dim>::setActiveState(const Coord& xyz, bool on)
1799 {
1800 const Index n = this->coordToOffset(xyz);
1801 bool hasChild = this->isChildMaskOn(n);
1802 if (!hasChild) {
1803 if (on != this->isValueMaskOn(n)) {
1804 // If the voxel belongs to a tile with the wrong active state,
1805 // then a child subtree must be constructed.
1806 // 'on' is the voxel's new state, therefore '!on' is the tile's current state
1807 hasChild = true;
1808 this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1809 }
1810 }
1811 if (hasChild) mNodes[n].getChild()->setActiveState(xyz, on);
1812 }
1813
1814 template<typename ChildT, Index Log2Dim>
1815 template<typename AccessorT>
1816 inline void
1817 InternalNode<ChildT, Log2Dim>::setActiveStateAndCache(const Coord& xyz, bool on, AccessorT& acc)
1818 {
1819 const Index n = this->coordToOffset(xyz);
1820 bool hasChild = this->isChildMaskOn(n);
1821 if (!hasChild) {
1822 if (on != this->isValueMaskOn(n)) {
1823 // If the voxel belongs to a tile with the wrong active state,
1824 // then a child subtree must be constructed.
1825 // 'on' is the voxel's new state, therefore '!on' is the tile's current state
1826 hasChild = true;
1827 this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1828 }
1829 }
1830 if (hasChild) {
1831 ChildT* child = mNodes[n].getChild();
1832 acc.insert(xyz, child);
1833 child->setActiveStateAndCache(xyz, on, acc);
1834 }
1835 }
1836
1837
1838 template<typename ChildT, Index Log2Dim>
1839 inline void
1840 InternalNode<ChildT, Log2Dim>::setValuesOn()
1841 {
1842 mValueMask = !mChildMask;
1843 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1844 mNodes[iter.pos()].getChild()->setValuesOn();
1845 }
1846 }
1847
1848
1849 template<typename ChildT, Index Log2Dim>
1850 template<typename ModifyOp>
1851 inline void
1852 InternalNode<ChildT, Log2Dim>::modifyValue(const Coord& xyz, const ModifyOp& op)
1853 {
1854 const Index n = InternalNode::coordToOffset(xyz);
1855 bool hasChild = this->isChildMaskOn(n);
1856 if (!hasChild) {
1857 // Need to create a child if the tile is inactive,
1858 // in order to activate voxel (x, y, z).
1859 const bool active = this->isValueMaskOn(n);
1860 bool createChild = !active;
1861 if (!createChild) {
1862 // Need to create a child if applying the functor
1863 // to the tile value produces a different value.
1864 const ValueType& tileVal = mNodes[n].getValue();
1865 ValueType modifiedVal = tileVal;
1866 op(modifiedVal);
1867 createChild = !math::isExactlyEqual(tileVal, modifiedVal);
1868 }
1869 if (createChild) {
1870 hasChild = true;
1871 this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1872 }
1873 }
1874 if (hasChild) mNodes[n].getChild()->modifyValue(xyz, op);
1875 }
1876
1877 template<typename ChildT, Index Log2Dim>
1878 template<typename ModifyOp, typename AccessorT>
1879 inline void
1880 InternalNode<ChildT, Log2Dim>::modifyValueAndCache(const Coord& xyz, const ModifyOp& op,
1881 AccessorT& acc)
1882 {
1883 const Index n = InternalNode::coordToOffset(xyz);
1884 bool hasChild = this->isChildMaskOn(n);
1885 if (!hasChild) {
1886 // Need to create a child if the tile is inactive,
1887 // in order to activate voxel (x, y, z).
1888 const bool active = this->isValueMaskOn(n);
1889 bool createChild = !active;
1890 if (!createChild) {
1891 // Need to create a child if applying the functor
1892 // to the tile value produces a different value.
1893 const ValueType& tileVal = mNodes[n].getValue();
1894 ValueType modifiedVal = tileVal;
1895 op(modifiedVal);
1896 createChild = !math::isExactlyEqual(tileVal, modifiedVal);
1897 }
1898 if (createChild) {
1899 hasChild = true;
1900 this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active));
1901 }
1902 }
1903 if (hasChild) {
1904 ChildNodeType* child = mNodes[n].getChild();
1905 acc.insert(xyz, child);
1906 child->modifyValueAndCache(xyz, op, acc);
1907 }
1908 }
1909
1910
1911 template<typename ChildT, Index Log2Dim>
1912 template<typename ModifyOp>
1913 inline void
1914 InternalNode<ChildT, Log2Dim>::modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
1915 {
1916 const Index n = InternalNode::coordToOffset(xyz);
1917 bool hasChild = this->isChildMaskOn(n);
1918 if (!hasChild) {
1919 const bool tileState = this->isValueMaskOn(n);
1920 const ValueType& tileVal = mNodes[n].getValue();
1921 bool modifiedState = !tileState;
1922 ValueType modifiedVal = tileVal;
1923 op(modifiedVal, modifiedState);
1924 // Need to create a child if applying the functor to the tile
1925 // produces a different value or active state.
1926 if (modifiedState != tileState || !math::isExactlyEqual(modifiedVal, tileVal)) {
1927 hasChild = true;
1928 this->setChildNode(n, new ChildNodeType(xyz, tileVal, tileState));
1929 }
1930 }
1931 if (hasChild) mNodes[n].getChild()->modifyValueAndActiveState(xyz, op);
1932 }
1933
1934 template<typename ChildT, Index Log2Dim>
1935 template<typename ModifyOp, typename AccessorT>
1936 inline void
1937 InternalNode<ChildT, Log2Dim>::modifyValueAndActiveStateAndCache(
1938 const Coord& xyz, const ModifyOp& op, AccessorT& acc)
1939 {
1940 const Index n = InternalNode::coordToOffset(xyz);
1941 bool hasChild = this->isChildMaskOn(n);
1942 if (!hasChild) {
1943 const bool tileState = this->isValueMaskOn(n);
1944 const ValueType& tileVal = mNodes[n].getValue();
1945 bool modifiedState = !tileState;
1946 ValueType modifiedVal = tileVal;
1947 op(modifiedVal, modifiedState);
1948 // Need to create a child if applying the functor to the tile
1949 // produces a different value or active state.
1950 if (modifiedState != tileState || !math::isExactlyEqual(modifiedVal, tileVal)) {
1951 hasChild = true;
1952 this->setChildNode(n, new ChildNodeType(xyz, tileVal, tileState));
1953 }
1954 }
1955 if (hasChild) {
1956 ChildNodeType* child = mNodes[n].getChild();
1957 acc.insert(xyz, child);
1958 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
1959 }
1960 }
1961
1962
1964
1965
1966 template<typename ChildT, Index Log2Dim>
1967 inline void
1968 InternalNode<ChildT, Log2Dim>::clip(const CoordBBox& clipBBox, const ValueType& background)
1969 {
1970 CoordBBox nodeBBox = this->getNodeBoundingBox();
1971 if (!clipBBox.hasOverlap(nodeBBox)) {
1972 // This node lies completely outside the clipping region. Fill it with background tiles.
1973 this->fill(nodeBBox, background, /*active=*/false);
1974 } else if (clipBBox.isInside(nodeBBox)) {
1975 // This node lies completely inside the clipping region. Leave it intact.
1976 return;
1977 }
1978
1979 // This node isn't completely contained inside the clipping region.
1980 // Clip tiles and children, and replace any that lie outside the region
1981 // with background tiles.
1982
1983 for (Index pos = 0; pos < NUM_VALUES; ++pos) {
1984 const Coord xyz = this->offsetToGlobalCoord(pos); // tile or child origin
1985 CoordBBox tileBBox(xyz, xyz.offsetBy(ChildT::DIM - 1)); // tile or child bounds
1986 if (!clipBBox.hasOverlap(tileBBox)) {
1987 // This table entry lies completely outside the clipping region.
1988 // Replace it with a background tile.
1989 this->makeChildNodeEmpty(pos, background);
1990 mValueMask.setOff(pos);
1991 } else if (!clipBBox.isInside(tileBBox)) {
1992 // This table entry does not lie completely inside the clipping region
1993 // and must be clipped.
1994 if (this->isChildMaskOn(pos)) {
1995 mNodes[pos].getChild()->clip(clipBBox, background);
1996 } else {
1997 // Replace this tile with a background tile, then fill the clip region
1998 // with the tile's original value. (This might create a child branch.)
1999 tileBBox.intersect(clipBBox);
2000 const ValueType val = mNodes[pos].getValue();
2001 const bool on = this->isValueMaskOn(pos);
2002 mNodes[pos].setValue(background);
2003 mValueMask.setOff(pos);
2004 this->fill(tileBBox, val, on);
2005 }
2006 } else {
2007 // This table entry lies completely inside the clipping region. Leave it intact.
2008 }
2009 }
2010 }
2011
2012
2014
2015
2016 template<typename ChildT, Index Log2Dim>
2017 inline void
2018 InternalNode<ChildT, Log2Dim>::fill(const CoordBBox& bbox, const ValueType& value, bool active)
2019 {
2020 Coord xyz, tileMin, tileMax;
2021 for (int x = bbox.min().x(); x <= bbox.max().x(); x = tileMax.x() + 1) {
2022 xyz.setX(x);
2023 for (int y = bbox.min().y(); y <= bbox.max().y(); y = tileMax.y() + 1) {
2024 xyz.setY(y);
2025 for (int z = bbox.min().z(); z <= bbox.max().z(); z = tileMax.z() + 1) {
2026 xyz.setZ(z);
2027
2028 // Get the bounds of the tile that contains voxel (x, y, z).
2029 const Index n = this->coordToOffset(xyz);
2030 tileMin = this->offsetToGlobalCoord(n);
2031 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2032
2033 if (xyz != tileMin || Coord::lessThan(bbox.max(), tileMax)) {
2034 // If the box defined by (xyz, bbox.max()) doesn't completely enclose
2035 // the tile to which xyz belongs, create a child node (or retrieve
2036 // the existing one).
2037 ChildT* child = NULL;
2038 if (this->isChildMaskOff(n)) {
2039 // Replace the tile with a newly-created child that is initialized
2040 // with the tile's value and active state.
2041 child = new ChildT(xyz, mNodes[n].getValue(), this->isValueMaskOn(n));
2042 this->setChildNode(n, child);
2043 } else {
2044 child = mNodes[n].getChild();
2045 }
2046
2047 // Forward the fill request to the child.
2048 if (child) {
2049 const Coord tmp = Coord::minComponent(bbox.max(), tileMax);
2050 child->fill(CoordBBox(xyz, tmp), value, active);
2051 }
2052
2053 } else {
2054 // If the box given by (xyz, bbox.max()) completely encloses
2055 // the tile to which xyz belongs, create the tile (if it
2056 // doesn't already exist) and give it the fill value.
2057 this->makeChildNodeEmpty(n, value);
2058 mValueMask.set(n, active);
2059 }
2060 }
2061 }
2062 }
2063 }
2064
2065
2067
2068
2069 template<typename ChildT, Index Log2Dim>
2070 template<typename DenseT>
2071 inline void
2072 InternalNode<ChildT, Log2Dim>::copyToDense(const CoordBBox& bbox, DenseT& dense) const
2073 {
2074 typedef typename DenseT::ValueType DenseValueType;
2075
2076 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2077 const Coord& min = dense.bbox().min();
2078 for (Coord xyz = bbox.min(), max; xyz[0] <= bbox.max()[0]; xyz[0] = max[0] + 1) {
2079 for (xyz[1] = bbox.min()[1]; xyz[1] <= bbox.max()[1]; xyz[1] = max[1] + 1) {
2080 for (xyz[2] = bbox.min()[2]; xyz[2] <= bbox.max()[2]; xyz[2] = max[2] + 1) {
2081 const Index n = this->coordToOffset(xyz);
2082 // Get max coordinates of the child node that contains voxel xyz.
2083 max = this->offsetToGlobalCoord(n).offsetBy(ChildT::DIM-1);
2084
2085 // Get the bbox of the interection of bbox and the child node
2086 CoordBBox sub(xyz, Coord::minComponent(bbox.max(), max));
2087
2088 if (this->isChildMaskOn(n)) {//is a child
2089 mNodes[n].getChild()->copyToDense(sub, dense);
2090 } else {//a tile value
2091 const ValueType value = mNodes[n].getValue();
2092 sub.translate(-min);
2093 DenseValueType* a0 = dense.data() + zStride*sub.min()[2];
2094 for (Int32 x=sub.min()[0], ex=sub.max()[0]+1; x<ex; ++x) {
2095 DenseValueType* a1 = a0 + x*xStride;
2096 for (Int32 y=sub.min()[1], ey=sub.max()[1]+1; y<ey; ++y) {
2097 DenseValueType* a2 = a1 + y*yStride;
2098 for (Int32 z=sub.min()[2], ez=sub.max()[2]+1; z<ez; ++z, a2 += zStride) {
2099 *a2 = DenseValueType(value);
2100 }
2101 }
2102 }
2103 }
2104 }
2105 }
2106 }
2107 }
2108
2109
2111
2112
2113 template<typename ChildT, Index Log2Dim>
2114 inline void
2115 InternalNode<ChildT, Log2Dim>::writeTopology(std::ostream& os, bool toHalf) const
2116 {
2117 mChildMask.save(os);
2118 mValueMask.save(os);
2119
2120 {
2121 // Copy all of this node's values into an array.
2122 boost::shared_array<ValueType> values(new ValueType[NUM_VALUES]);
2123 const ValueType zero = zeroVal<ValueType>();
2124 for (Index i = 0; i < NUM_VALUES; ++i) {
2125 values[i] = (mChildMask.isOff(i) ? mNodes[i].getValue() : zero);
2126 }
2127 // Compress (optionally) and write out the contents of the array.
2128 io::writeCompressedValues(os, values.get(), NUM_VALUES, mValueMask, mChildMask, toHalf);
2129 }
2130 // Write out the child nodes in order.
2131 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2132 iter->writeTopology(os, toHalf);
2133 }
2134 }
2135
2136
2137 template<typename ChildT, Index Log2Dim>
2138 inline void
2139 InternalNode<ChildT, Log2Dim>::readTopology(std::istream& is, bool fromHalf)
2140 {
2141 #ifndef OPENVDB_2_ABI_COMPATIBLE
2142 const ValueType background = (!io::getGridBackgroundValuePtr(is) ? zeroVal<ValueType>()
2143 : *static_cast<const ValueType*>(io::getGridBackgroundValuePtr(is)));
2144 #endif
2145
2146 mChildMask.load(is);
2147 mValueMask.load(is);
2148
2149 if (io::getFormatVersion(is) < OPENVDB_FILE_VERSION_INTERNALNODE_COMPRESSION) {
2150 for (Index i = 0; i < NUM_VALUES; ++i) {
2151 if (this->isChildMaskOn(i)) {
2152 ChildNodeType* child =
2153 #ifdef OPENVDB_2_ABI_COMPATIBLE
2154 new ChildNodeType(offsetToGlobalCoord(i), zeroVal<ValueType>());
2155 #else
2156 new ChildNodeType(PartialCreate(), offsetToGlobalCoord(i), background);
2157 #endif
2158 mNodes[i].setChild(child);
2159 child->readTopology(is);
2160 } else {
2161 ValueType value;
2162 is.read(reinterpret_cast<char*>(&value), sizeof(ValueType));
2163 mNodes[i].setValue(value);
2164 }
2165 }
2166 } else {
2167 const bool oldVersion =
2168 (io::getFormatVersion(is) < OPENVDB_FILE_VERSION_NODE_MASK_COMPRESSION);
2169 const Index numValues = (oldVersion ? mChildMask.countOff() : NUM_VALUES);
2170 {
2171 // Read in (and uncompress, if necessary) all of this node's values
2172 // into a contiguous array.
2173 boost::shared_array<ValueType> values(new ValueType[numValues]);
2174 io::readCompressedValues(is, values.get(), numValues, mValueMask, fromHalf);
2175
2176 // Copy values from the array into this node's table.
2177 if (oldVersion) {
2178 Index n = 0;
2179 for (ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2180 mNodes[iter.pos()].setValue(values[n++]);
2181 }
2182 assert(n == numValues);
2183 } else {
2184 for (ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2185 mNodes[iter.pos()].setValue(values[iter.pos()]);
2186 }
2187 }
2188 }
2189 // Read in all child nodes and insert them into the table at their proper locations.
2190 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2191 #ifdef OPENVDB_2_ABI_COMPATIBLE
2192 ChildNodeType* child = new ChildNodeType(iter.getCoord(), zeroVal<ValueType>());
2193 #else
2194 ChildNodeType* child = new ChildNodeType(PartialCreate(), iter.getCoord(), background);
2195 #endif
2196 mNodes[iter.pos()].setChild(child);
2197 child->readTopology(is, fromHalf);
2198 }
2199 }
2200 }
2201
2202
2204
2205
2206 template<typename ChildT, Index Log2Dim>
2207 inline const typename ChildT::ValueType&
2208 InternalNode<ChildT, Log2Dim>::getFirstValue() const
2209 {
2210 return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].getValue());
2211 }
2212
2213
2214 template<typename ChildT, Index Log2Dim>
2215 inline const typename ChildT::ValueType&
2216 InternalNode<ChildT, Log2Dim>::getLastValue() const
2217 {
2218 const Index n = NUM_VALUES - 1;
2219 return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].getValue());
2220 }
2221
2222
2224
2225
2226 template<typename ChildT, Index Log2Dim>
2227 inline void
2228 InternalNode<ChildT, Log2Dim>::negate()
2229 {
2230 for (Index i = 0; i < NUM_VALUES; ++i) {
2231 if (this->isChildMaskOn(i)) {
2232 mNodes[i].getChild()->negate();
2233 } else {
2234 mNodes[i].setValue(math::negative(mNodes[i].getValue()));
2235 }
2236 }
2237
2238 }
2239
2241
2242 template<typename ChildT, Index Log2Dim>
2243 struct InternalNode<ChildT, Log2Dim>::VoxelizeActiveTiles
2244 {
2245 VoxelizeActiveTiles(InternalNode &node) : mNode(&node) {
2246 //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//single thread for debugging
2247 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this);
2248
2249 node.mChildMask |= node.mValueMask;
2250 node.mValueMask.setOff();
2251 }
2252 void operator()(const tbb::blocked_range<Index> &r) const
2253 {
2254 for (Index i = r.begin(), end=r.end(); i!=end; ++i) {
2255 if (mNode->mChildMask.isOn(i)) {// Loop over node's child nodes
2256 mNode->mNodes[i].getChild()->voxelizeActiveTiles(true);
2257 } else if (mNode->mValueMask.isOn(i)) {// Loop over node's active tiles
2258 const Coord &ijk = mNode->offsetToGlobalCoord(i);
2259 ChildNodeType *child = new ChildNodeType(ijk, mNode->mNodes[i].getValue(), true);
2260 child->voxelizeActiveTiles(true);
2261 mNode->mNodes[i].setChild(child);
2262 }
2263 }
2264 }
2265 InternalNode* mNode;
2266 };// VoxelizeActiveTiles
2267
2268 template<typename ChildT, Index Log2Dim>
2269 inline void
2270 InternalNode<ChildT, Log2Dim>::voxelizeActiveTiles(bool threaded)
2271 {
2272 if (threaded) {
2273 VoxelizeActiveTiles tmp(*this);
2274 } else {
2275 for (ValueOnIter iter = this->beginValueOn(); iter; ++iter) {
2276 this->setChildNode(iter.pos(), new ChildNodeType(iter.getCoord(), iter.getValue(), true));
2277 }
2278 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter)
2279 iter->voxelizeActiveTiles(false);
2280 }
2281 }
2282
2283
2285
2286
2287 template<typename ChildT, Index Log2Dim>
2288 template<MergePolicy Policy>
2289 inline void
2290 InternalNode<ChildT, Log2Dim>::merge(InternalNode& other,
2291 const ValueType& background, const ValueType& otherBackground)
2292 {
2293 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
2294
2295 switch (Policy) {
2296
2297 case MERGE_ACTIVE_STATES:
2298 default:
2299 {
2300 for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) {
2301 const Index n = iter.pos();
2302 if (mChildMask.isOn(n)) {
2303 // Merge this node's child with the other node's child.
2304 mNodes[n].getChild()->template merge<MERGE_ACTIVE_STATES>(*iter,
2305 background, otherBackground);
2306 } else if (mValueMask.isOff(n)) {
2307 // Replace this node's inactive tile with the other node's child
2308 // and replace the other node's child with a tile of undefined value
2309 // (which is okay since the other tree is assumed to be cannibalized
2310 // in the process of merging).
2311 ChildNodeType* child = other.mNodes[n].getChild();
2312 other.mChildMask.setOff(n);
2313 child->resetBackground(otherBackground, background);
2314 this->setChildNode(n, child);
2315 }
2316 }
2317
2318 // Copy active tile values.
2319 for (ValueOnCIter iter = other.cbeginValueOn(); iter; ++iter) {
2320 const Index n = iter.pos();
2321 if (mValueMask.isOff(n)) {
2322 // Replace this node's child or inactive tile with the other node's active tile.
2323 this->makeChildNodeEmpty(n, iter.getValue());
2324 mValueMask.setOn(n);
2325 }
2326 }
2327 break;
2328 }
2329
2330 case MERGE_NODES:
2331 {
2332 for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) {
2333 const Index n = iter.pos();
2334 if (mChildMask.isOn(n)) {
2335 // Merge this node's child with the other node's child.
2336 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2337 } else {
2338 // Replace this node's tile (regardless of its active state) with
2339 // the other node's child and replace the other node's child with
2340 // a tile of undefined value (which is okay since the other tree
2341 // is assumed to be cannibalized in the process of merging).
2342 ChildNodeType* child = other.mNodes[n].getChild();
2343 other.mChildMask.setOff(n);
2344 child->resetBackground(otherBackground, background);
2345 this->setChildNode(n, child);
2346 }
2347 }
2348 break;
2349 }
2350
2351 case MERGE_ACTIVE_STATES_AND_NODES:
2352 {
2353 // Transfer children from the other tree to this tree.
2354 for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) {
2355 const Index n = iter.pos();
2356 if (mChildMask.isOn(n)) {
2357 // Merge this node's child with the other node's child.
2358 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2359 } else {
2360 // Replace this node's tile with the other node's child, leaving the other
2361 // node with an inactive tile of undefined value (which is okay since
2362 // the other tree is assumed to be cannibalized in the process of merging).
2363 ChildNodeType* child = other.mNodes[n].getChild();
2364 other.mChildMask.setOff(n);
2365 child->resetBackground(otherBackground, background);
2366 if (mValueMask.isOn(n)) {
2367 // Merge the child with this node's active tile.
2368 child->template merge<Policy>(mNodes[n].getValue(), /*on=*/true);
2369 mValueMask.setOff(n);
2370 }
2371 mChildMask.setOn(n);
2372 mNodes[n].setChild(child);
2373 }
2374 }
2375
2376 // Merge active tiles into this tree.
2377 for (ValueOnCIter iter = other.cbeginValueOn(); iter; ++iter) {
2378 const Index n = iter.pos();
2379 if (mChildMask.isOn(n)) {
2380 // Merge the other node's active tile into this node's child.
2381 mNodes[n].getChild()->template merge<Policy>(iter.getValue(), /*on=*/true);
2382 } else if (mValueMask.isOff(n)) {
2383 // Replace this node's inactive tile with the other node's active tile.
2384 mNodes[n].setValue(iter.getValue());
2385 mValueMask.setOn(n);
2386 }
2387 }
2388 break;
2389 }
2390
2391 }
2392 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
2393 }
2394
2395
2396 template<typename ChildT, Index Log2Dim>
2397 template<MergePolicy Policy>
2398 inline void
2399 InternalNode<ChildT, Log2Dim>::merge(const ValueType& tileValue, bool tileActive)
2400 {
2401 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
2402
2403 if (Policy != MERGE_ACTIVE_STATES_AND_NODES) return;
2404
2405 // For MERGE_ACTIVE_STATES_AND_NODES, inactive tiles in the other tree are ignored.
2406 if (!tileActive) return;
2407
2408 // Iterate over this node's children and inactive tiles.
2409 for (ValueOffIter iter = this->beginValueOff(); iter; ++iter) {
2410 const Index n = iter.pos();
2411 if (mChildMask.isOn(n)) {
2412 // Merge the other node's active tile into this node's child.
2413 mNodes[n].getChild()->template merge<Policy>(tileValue, /*on=*/true);
2414 } else {
2415 // Replace this node's inactive tile with the other node's active tile.
2416 iter.setValue(tileValue);
2417 mValueMask.setOn(n);
2418 }
2419 }
2420 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
2421 }
2422
2424
2425 template<typename ChildT, Index Log2Dim>
2426 template<typename OtherInternalNode>
2427 struct InternalNode<ChildT, Log2Dim>::TopologyUnion
2428 {
2429 typedef typename NodeMaskType::Word W;
2430 struct A { inline void operator()(W &tV, const W& sV, const W& tC) const
2431 { tV = (tV | sV) & ~tC; }
2432 };
2433 TopologyUnion(const OtherInternalNode* source, InternalNode* target) : s(source), t(target) {
2434 //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//single thread for debugging
2435 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this);
2436
2437 // Bit processing is done in a single thread!
2438 t->mChildMask |= s->mChildMask;//serial but very fast bitwise post-process
2439 A op;
2440 t->mValueMask.foreach(s->mValueMask, t->mChildMask, op);
2441 assert((t->mValueMask & t->mChildMask).isOff());//no overlapping active tiles and child nodes
2442 }
2443 void operator()(const tbb::blocked_range<Index> &r) const {
2444 for (Index i = r.begin(), end=r.end(); i!=end; ++i) {
2445 if (s->mChildMask.isOn(i)) {// Loop over other node's child nodes
2446 const typename OtherInternalNode::ChildNodeType& other = *(s->mNodes[i].getChild());
2447 if (t->mChildMask.isOn(i)) {//this has a child node
2448 t->mNodes[i].getChild()->topologyUnion(other);
2449 } else {// this is a tile so replace it with a child branch with identical topology
2450 ChildT* child = new ChildT(other, t->mNodes[i].getValue(), TopologyCopy());
2451 if (t->mValueMask.isOn(i)) child->setValuesOn();//activate all values
2452 t->mNodes[i].setChild(child);
2453 }
2454 } else if (s->mValueMask.isOn(i) && t->mChildMask.isOn(i)) {
2455 t->mNodes[i].getChild()->setValuesOn();
2456 }
2457 }
2458 }
2459 const OtherInternalNode* s;
2460 InternalNode* t;
2461 };// TopologyUnion
2462
2463 template<typename ChildT, Index Log2Dim>
2464 template<typename OtherChildT>
2465 inline void
2466 InternalNode<ChildT, Log2Dim>::topologyUnion(const InternalNode<OtherChildT, Log2Dim>& other)
2467 {
2468 TopologyUnion<InternalNode<OtherChildT, Log2Dim> > tmp(&other, this);
2469 }
2470
2471 template<typename ChildT, Index Log2Dim>
2472 template<typename OtherInternalNode>
2473 struct InternalNode<ChildT, Log2Dim>::TopologyIntersection
2474 {
2475 typedef typename NodeMaskType::Word W;
2476 struct A { inline void operator()(W &tC, const W& sC, const W& sV, const W& tV) const
2477 { tC = (tC & (sC | sV)) | (tV & sC); }
2478 };
2479 TopologyIntersection(const OtherInternalNode* source, InternalNode* target,
2480 const ValueType& background) : s(source), t(target), b(background) {
2481 //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//single thread for debugging
2482 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this);
2483
2484 // Bit processing is done in a single thread!
2485 A op;
2486 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op);
2487
2488 t->mValueMask &= s->mValueMask;
2489 assert((t->mValueMask & t->mChildMask).isOff());//no overlapping active tiles and child nodes
2490 }
2491 void operator()(const tbb::blocked_range<Index> &r) const {
2492 for (Index i = r.begin(), end=r.end(); i!=end; ++i) {
2493 if (t->mChildMask.isOn(i)) {// Loop over this node's child nodes
2494 ChildT* child = t->mNodes[i].getChild();
2495 if (s->mChildMask.isOn(i)) {//other also has a child node
2496 child->topologyIntersection(*(s->mNodes[i].getChild()), b);
2497 } else if (s->mValueMask.isOff(i)) {//other is an inactive tile
2498 delete child;//convert child to an inactive tile
2499 t->mNodes[i].setValue(b);
2500 }
2501 } else if (t->mValueMask.isOn(i) && s->mChildMask.isOn(i)) {//active tile -> a branch
2502 t->mNodes[i].setChild(new ChildT(*(s->mNodes[i].getChild()),
2503 t->mNodes[i].getValue(), TopologyCopy()));
2504 }
2505 }
2506 }
2507 const OtherInternalNode* s;
2508 InternalNode* t;
2509 const ValueType& b;
2510 };// TopologyIntersection
2511
2512 template<typename ChildT, Index Log2Dim>
2513 template<typename OtherChildT>
2514 inline void
2515 InternalNode<ChildT, Log2Dim>::topologyIntersection(const InternalNode<OtherChildT, Log2Dim>& other,
2516 const ValueType& background)
2517 {
2518 TopologyIntersection<InternalNode<OtherChildT, Log2Dim> > tmp(&other, this, background);
2519 }
2520
2521 template<typename ChildT, Index Log2Dim>
2522 template<typename OtherInternalNode>
2523 struct InternalNode<ChildT, Log2Dim>::TopologyDifference
2524 {
2525 typedef typename NodeMaskType::Word W;
2526 struct A {inline void operator()(W &tC, const W& sC, const W& sV, const W& tV) const
2527 { tC = (tC & (sC | ~sV)) | (tV & sC); }
2528 };
2529 struct B {inline void operator()(W &tV, const W& sC, const W& sV, const W& tC) const
2530 { tV &= ~((tC & sV) | (sC | sV)); }
2531 };
2532 TopologyDifference(const OtherInternalNode* source, InternalNode* target,
2533 const ValueType& background) : s(source), t(target), b(background) {
2534 //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//single thread for debugging
2535 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this);
2536
2537 // Bit processing is done in a single thread!
2538 const NodeMaskType oldChildMask(t->mChildMask);//important to avoid cross pollution
2539 A op1;
2540 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op1);
2541
2542 B op2;
2543 t->mValueMask.foreach(t->mChildMask, s->mValueMask, oldChildMask, op2);
2544 assert((t->mValueMask & t->mChildMask).isOff());//no overlapping active tiles and child nodes
2545 }
2546 void operator()(const tbb::blocked_range<Index> &r) const {
2547 for (Index i = r.begin(), end=r.end(); i!=end; ++i) {
2548 if (t->mChildMask.isOn(i)) {// Loop over this node's child nodes
2549 ChildT* child = t->mNodes[i].getChild();
2550 if (s->mChildMask.isOn(i)) {
2551 child->topologyDifference(*(s->mNodes[i].getChild()), b);
2552 } else if (s->mValueMask.isOn(i)) {
2553 delete child;//convert child to an inactive tile
2554 t->mNodes[i].setValue(b);
2555 }
2556 } else if (t->mValueMask.isOn(i)) {//this is an active tile
2557 if (s->mChildMask.isOn(i)) {
2558 const typename OtherInternalNode::ChildNodeType& other = *(s->mNodes[i].getChild());
2559 ChildT* child = new ChildT(other.origin(), t->mNodes[i].getValue(), true);
2560 child->topologyDifference(other, b);
2561 t->mNodes[i].setChild(child);//replace the active tile with a child branch
2562 }
2563 }
2564 }
2565 }
2566 const OtherInternalNode* s;
2567 InternalNode* t;
2568 const ValueType& b;
2569 };// TopologyDifference
2570
2571 template<typename ChildT, Index Log2Dim>
2572 template<typename OtherChildT>
2573 inline void
2574 InternalNode<ChildT, Log2Dim>::topologyDifference(const InternalNode<OtherChildT, Log2Dim>& other,
2575 const ValueType& background)
2576 {
2577 TopologyDifference<InternalNode<OtherChildT, Log2Dim> > tmp(&other, this, background);
2578 }
2579
2581
2582
2583 template<typename ChildT, Index Log2Dim>
2584 template<typename CombineOp>
2585 inline void
2586 InternalNode<ChildT, Log2Dim>::combine(InternalNode& other, CombineOp& op)
2587 {
2588 const ValueType zero = zeroVal<ValueType>();
2589
2590 CombineArgs<ValueType> args;
2591
2592 for (Index i = 0; i < NUM_VALUES; ++i) {
2593 if (this->isChildMaskOff(i) && other.isChildMaskOff(i)) {
2594 // Both this node and the other node have constant values (tiles).
2595 // Combine the two values and store the result as this node's new tile value.
2596 op(args.setARef(mNodes[i].getValue())
2597 .setAIsActive(isValueMaskOn(i))
2598 .setBRef(other.mNodes[i].getValue())
2599 .setBIsActive(other.isValueMaskOn(i)));
2600 mNodes[i].setValue(args.result());
2601 mValueMask.set(i, args.resultIsActive());
2602 } else if (this->isChildMaskOn(i) && other.isChildMaskOff(i)) {
2603 // Combine this node's child with the other node's constant value.
2604 ChildNodeType* child = mNodes[i].getChild();
2605 assert(child);
2606 if (child) {
2607 child->combine(other.mNodes[i].getValue(), other.isValueMaskOn(i), op);
2608 }
2609 } else if (this->isChildMaskOff(i) && other.isChildMaskOn(i)) {
2610 // Combine this node's constant value with the other node's child.
2611 ChildNodeType* child = other.mNodes[i].getChild();
2612 assert(child);
2613 if (child) {
2614 // Combine this node's constant value with the other node's child,
2615 // but use a new functor in which the A and B values are swapped,
2616 // since the constant value is the A value, not the B value.
2617 SwappedCombineOp<ValueType, CombineOp> swappedOp(op);
2618 child->combine(mNodes[i].getValue(), isValueMaskOn(i), swappedOp);
2619
2620 // Steal the other node's child.
2621 other.mChildMask.setOff(i);
2622 other.mNodes[i].setValue(zero);
2623 this->setChildNode(i, child);
2624 }
2625
2626 } else /*if (isChildMaskOn(i) && other.isChildMaskOn(i))*/ {
2627 // Combine this node's child with the other node's child.
2628 ChildNodeType
2629 *child = mNodes[i].getChild(),
2630 *otherChild = other.mNodes[i].getChild();
2631 assert(child);
2632 assert(otherChild);
2633 if (child && otherChild) {
2634 child->combine(*otherChild, op);
2635 }
2636 }
2637 }
2638 }
2639
2640
2641 template<typename ChildT, Index Log2Dim>
2642 template<typename CombineOp>
2643 inline void
2644 InternalNode<ChildT, Log2Dim>::combine(const ValueType& value, bool valueIsActive, CombineOp& op)
2645 {
2646 CombineArgs<ValueType> args;
2647
2648 for (Index i = 0; i < NUM_VALUES; ++i) {
2649 if (this->isChildMaskOff(i)) {
2650 // Combine this node's constant value with the given constant value.
2651 op(args.setARef(mNodes[i].getValue())
2652 .setAIsActive(isValueMaskOn(i))
2653 .setBRef(value)
2654 .setBIsActive(valueIsActive));
2655 mNodes[i].setValue(args.result());
2656 mValueMask.set(i, args.resultIsActive());
2657 } else /*if (isChildMaskOn(i))*/ {
2658 // Combine this node's child with the given constant value.
2659 ChildNodeType* child = mNodes[i].getChild();
2660 assert(child);
2661 if (child) child->combine(value, valueIsActive, op);
2662 }
2663 }
2664 }
2665
2666
2668
2669
2670 template<typename ChildT, Index Log2Dim>
2671 template<typename CombineOp, typename OtherNodeType>
2672 inline void
2673 InternalNode<ChildT, Log2Dim>::combine2(const InternalNode& other0, const OtherNodeType& other1,
2674 CombineOp& op)
2675 {
2676 CombineArgs<ValueType, typename OtherNodeType::ValueType> args;
2677
2678 for (Index i = 0; i < NUM_VALUES; ++i) {
2679 if (other0.isChildMaskOff(i) && other1.isChildMaskOff(i)) {
2680 op(args.setARef(other0.mNodes[i].getValue())
2681 .setAIsActive(other0.isValueMaskOn(i))
2682 .setBRef(other1.mNodes[i].getValue())
2683 .setBIsActive(other1.isValueMaskOn(i)));
2684 // Replace child i with a constant value.
2685 this->makeChildNodeEmpty(i, args.result());
2686 mValueMask.set(i, args.resultIsActive());
2687 } else {
2688 if (this->isChildMaskOff(i)) {
2689 // Add a new child with the same coordinates, etc. as the other node's child.
2690 const Coord& childOrigin = other0.isChildMaskOn(i)
2691 ? other0.mNodes[i].getChild()->origin()
2692 : other1.mNodes[i].getChild()->origin();
2693 this->setChildNode(i, new ChildNodeType(childOrigin, mNodes[i].getValue()));
2694 }
2695
2696 if (other0.isChildMaskOff(i)) {
2697 // Combine node1's child with node0's constant value
2698 // and write the result into child i.
2699 mNodes[i].getChild()->combine2(other0.mNodes[i].getValue(),
2700 *other1.mNodes[i].getChild(), other0.isValueMaskOn(i), op);
2701 } else if (other1.isChildMaskOff(i)) {
2702 // Combine node0's child with node1's constant value
2703 // and write the result into child i.
2704 mNodes[i].getChild()->combine2(*other0.mNodes[i].getChild(),
2705 other1.mNodes[i].getValue(), other1.isValueMaskOn(i), op);
2706 } else {
2707 // Combine node0's child with node1's child
2708 // and write the result into child i.
2709 mNodes[i].getChild()->combine2(*other0.mNodes[i].getChild(),
2710 *other1.mNodes[i].getChild(), op);
2711 }
2712 }
2713 }
2714 }
2715
2716
2717 template<typename ChildT, Index Log2Dim>
2718 template<typename CombineOp, typename OtherNodeType>
2719 inline void
2720 InternalNode<ChildT, Log2Dim>::combine2(const ValueType& value, const OtherNodeType& other,
2721 bool valueIsActive, CombineOp& op)
2722 {
2723 CombineArgs<ValueType, typename OtherNodeType::ValueType> args;
2724
2725 for (Index i = 0; i < NUM_VALUES; ++i) {
2726 if (other.isChildMaskOff(i)) {
2727 op(args.setARef(value)
2728 .setAIsActive(valueIsActive)
2729 .setBRef(other.mNodes[i].getValue())
2730 .setBIsActive(other.isValueMaskOn(i)));
2731 // Replace child i with a constant value.
2732 this->makeChildNodeEmpty(i, args.result());
2733 mValueMask.set(i, args.resultIsActive());
2734 } else {
2735 typename OtherNodeType::ChildNodeType* otherChild = other.mNodes[i].getChild();
2736 assert(otherChild);
2737 if (this->isChildMaskOff(i)) {
2738 // Add a new child with the same coordinates, etc.
2739 // as the other node's child.
2740 this->setChildNode(i, new ChildNodeType(*otherChild));
2741 }
2742 // Combine the other node's child with a constant value
2743 // and write the result into child i.
2744 mNodes[i].getChild()->combine2(value, *otherChild, valueIsActive, op);
2745 }
2746 }
2747 }
2748
2749
2750 template<typename ChildT, Index Log2Dim>
2751 template<typename CombineOp, typename OtherValueType>
2752 inline void
2753 InternalNode<ChildT, Log2Dim>::combine2(const InternalNode& other, const OtherValueType& value,
2754 bool valueIsActive, CombineOp& op)
2755 {
2756 CombineArgs<ValueType, OtherValueType> args;
2757
2758 for (Index i = 0; i < NUM_VALUES; ++i) {
2759 if (other.isChildMaskOff(i)) {
2760 op(args.setARef(other.mNodes[i].getValue())
2761 .setAIsActive(other.isValueMaskOn(i))
2762 .setBRef(value)
2763 .setBIsActive(valueIsActive));
2764 // Replace child i with a constant value.
2765 this->makeChildNodeEmpty(i, args.result());
2766 mValueMask.set(i, args.resultIsActive());
2767 } else {
2768 ChildNodeType* otherChild = other.mNodes[i].getChild();
2769 assert(otherChild);
2770 if (this->isChildMaskOff(i)) {
2771 // Add a new child with the same coordinates, etc. as the other node's child.
2772 this->setChildNode(i,
2773 new ChildNodeType(otherChild->origin(), mNodes[i].getValue()));
2774 }
2775 // Combine the other node's child with a constant value
2776 // and write the result into child i.
2777 mNodes[i].getChild()->combine2(*otherChild, value, valueIsActive, op);
2778 }
2779 }
2780 }
2781
2782
2784
2785
2786 template<typename ChildT, Index Log2Dim>
2787 template<typename BBoxOp>
2788 inline void
2789 InternalNode<ChildT, Log2Dim>::visitActiveBBox(BBoxOp& op) const
2790 {
2791 for (ValueOnCIter i = this->cbeginValueOn(); i; ++i) {
2792 #ifdef _MSC_VER
2793 op.operator()<LEVEL>(CoordBBox::createCube(i.getCoord(), ChildNodeType::DIM));
2794 #else
2795 op.template operator()<LEVEL>(CoordBBox::createCube(i.getCoord(), ChildNodeType::DIM));
2796 #endif
2797 }
2798 if (op.template descent<LEVEL>()) {
2799 for (ChildOnCIter i = this->cbeginChildOn(); i; ++i) i->visitActiveBBox(op);
2800 } else {
2801 for (ChildOnCIter i = this->cbeginChildOn(); i; ++i) {
2802 #ifdef _MSC_VER
2803 op.operator()<LEVEL>(i->getNodeBoundingBox());
2804 #else
2805 op.template operator()<LEVEL>(i->getNodeBoundingBox());
2806 #endif
2807 }
2808 }
2809 }
2810
2811
2812 template<typename ChildT, Index Log2Dim>
2813 template<typename VisitorOp>
2814 inline void
2815 InternalNode<ChildT, Log2Dim>::visit(VisitorOp& op)
2816 {
2817 doVisit<InternalNode, VisitorOp, ChildAllIter>(*this, op);
2818 }
2819
2820
2821 template<typename ChildT, Index Log2Dim>
2822 template<typename VisitorOp>
2823 inline void
2824 InternalNode<ChildT, Log2Dim>::visit(VisitorOp& op) const
2825 {
2826 doVisit<const InternalNode, VisitorOp, ChildAllCIter>(*this, op);
2827 }
2828
2829
2830 template<typename ChildT, Index Log2Dim>
2831 template<typename NodeT, typename VisitorOp, typename ChildAllIterT>
2832 inline void
2833 InternalNode<ChildT, Log2Dim>::doVisit(NodeT& self, VisitorOp& op)
2834 {
2835 typename NodeT::ValueType val;
2836 for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
2837 if (op(iter)) continue;
2838 if (typename ChildAllIterT::ChildNodeType* child = iter.probeChild(val)) {
2839 child->visit(op);
2840 }
2841 }
2842 }
2843
2844
2846
2847
2848 template<typename ChildT, Index Log2Dim>
2849 template<typename OtherNodeType, typename VisitorOp>
2850 inline void
2851 InternalNode<ChildT, Log2Dim>::visit2Node(OtherNodeType& other, VisitorOp& op)
2852 {
2853 doVisit2Node<InternalNode, OtherNodeType, VisitorOp, ChildAllIter,
2854 typename OtherNodeType::ChildAllIter>(*this, other, op);
2855 }
2856
2857
2858 template<typename ChildT, Index Log2Dim>
2859 template<typename OtherNodeType, typename VisitorOp>
2860 inline void
2861 InternalNode<ChildT, Log2Dim>::visit2Node(OtherNodeType& other, VisitorOp& op) const
2862 {
2863 doVisit2Node<const InternalNode, OtherNodeType, VisitorOp, ChildAllCIter,
2864 typename OtherNodeType::ChildAllCIter>(*this, other, op);
2865 }
2866
2867
2868 template<typename ChildT, Index Log2Dim>
2869 template<
2870 typename NodeT,
2871 typename OtherNodeT,
2872 typename VisitorOp,
2873 typename ChildAllIterT,
2874 typename OtherChildAllIterT>
2875 inline void
2876 InternalNode<ChildT, Log2Dim>::doVisit2Node(NodeT& self, OtherNodeT& other, VisitorOp& op)
2877 {
2878 // Allow the two nodes to have different ValueTypes, but not different dimensions.
2879 BOOST_STATIC_ASSERT(OtherNodeT::NUM_VALUES == NodeT::NUM_VALUES);
2880 BOOST_STATIC_ASSERT(OtherNodeT::LEVEL == NodeT::LEVEL);
2881
2882 typename NodeT::ValueType val;
2883 typename OtherNodeT::ValueType otherVal;
2884
2885 ChildAllIterT iter = self.beginChildAll();
2886 OtherChildAllIterT otherIter = other.beginChildAll();
2887
2888 for ( ; iter && otherIter; ++iter, ++otherIter)
2889 {
2890 const size_t skipBranch = static_cast<size_t>(op(iter, otherIter));
2891
2892 typename ChildAllIterT::ChildNodeType* child =
2893 (skipBranch & 1U) ? NULL : iter.probeChild(val);
2894 typename OtherChildAllIterT::ChildNodeType* otherChild =
2895 (skipBranch & 2U) ? NULL : otherIter.probeChild(otherVal);
2896
2897 if (child != NULL && otherChild != NULL) {
2898 child->visit2Node(*otherChild, op);
2899 } else if (child != NULL) {
2900 child->visit2(otherIter, op);
2901 } else if (otherChild != NULL) {
2902 otherChild->visit2(iter, op, /*otherIsLHS=*/true);
2903 }
2904 }
2905 }
2906
2907
2909
2910
2911 template<typename ChildT, Index Log2Dim>
2912 template<typename OtherChildAllIterType, typename VisitorOp>
2913 inline void
2914 InternalNode<ChildT, Log2Dim>::visit2(OtherChildAllIterType& otherIter,
2915 VisitorOp& op, bool otherIsLHS)
2916 {
2917 doVisit2<InternalNode, VisitorOp, ChildAllIter, OtherChildAllIterType>(
2918 *this, otherIter, op, otherIsLHS);
2919 }
2920
2921
2922 template<typename ChildT, Index Log2Dim>
2923 template<typename OtherChildAllIterType, typename VisitorOp>
2924 inline void
2925 InternalNode<ChildT, Log2Dim>::visit2(OtherChildAllIterType& otherIter,
2926 VisitorOp& op, bool otherIsLHS) const
2927 {
2928 doVisit2<const InternalNode, VisitorOp, ChildAllCIter, OtherChildAllIterType>(
2929 *this, otherIter, op, otherIsLHS);
2930 }
2931
2932
2933 template<typename ChildT, Index Log2Dim>
2934 template<typename NodeT, typename VisitorOp, typename ChildAllIterT, typename OtherChildAllIterT>
2935 inline void
2936 InternalNode<ChildT, Log2Dim>::doVisit2(NodeT& self, OtherChildAllIterT& otherIter,
2937 VisitorOp& op, bool otherIsLHS)
2938 {
2939 if (!otherIter) return;
2940
2941 const size_t skipBitMask = (otherIsLHS ? 2U : 1U);
2942
2943 typename NodeT::ValueType val;
2944 for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) {
2945 const size_t skipBranch = static_cast<size_t>(
2946 otherIsLHS ? op(otherIter, iter) : op(iter, otherIter));
2947
2948 typename ChildAllIterT::ChildNodeType* child =
2949 (skipBranch & skipBitMask) ? NULL : iter.probeChild(val);
2950
2951 if (child != NULL) child->visit2(otherIter, op, otherIsLHS);
2952 }
2953 }
2954
2955
2957
2958
2959 template<typename ChildT, Index Log2Dim>
2960 inline void
2961 InternalNode<ChildT, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
2962 {
2963 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2964 iter->writeBuffers(os, toHalf);
2965 }
2966 }
2967
2968
2969 template<typename ChildT, Index Log2Dim>
2970 inline void
2971 InternalNode<ChildT, Log2Dim>::readBuffers(std::istream& is, bool fromHalf)
2972 {
2973 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2974 iter->readBuffers(is, fromHalf);
2975 }
2976 }
2977
2978
2979 template<typename ChildT, Index Log2Dim>
2980 inline void
2981 InternalNode<ChildT, Log2Dim>::readBuffers(std::istream& is,
2982 const CoordBBox& clipBBox, bool fromHalf)
2983 {
2984 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2985 // Stream in the branch rooted at this child.
2986 // (We can't skip over children that lie outside the clipping region,
2987 // because buffers are serialized in depth-first order and need to be
2988 // unserialized in the same order.)
2989 iter->readBuffers(is, clipBBox, fromHalf);
2990 }
2991
2992 // Get this tree's background value.
2993 ValueType background = zeroVal<ValueType>();
2994 if (const void* bgPtr = io::getGridBackgroundValuePtr(is)) {
2995 background = *static_cast<const ValueType*>(bgPtr);
2996 }
2997 this->clip(clipBBox, background);
2998 }
2999
3000
3002
3003
3004 template<typename ChildT, Index Log2Dim>
3005 void
3006 InternalNode<ChildT, Log2Dim>::getNodeLog2Dims(std::vector<Index>& dims)
3007 {
3008 dims.push_back(Log2Dim);
3009 ChildNodeType::getNodeLog2Dims(dims);
3010 }
3011
3012
3013 template<typename ChildT, Index Log2Dim>
3014 inline void
3015 InternalNode<ChildT, Log2Dim>::offsetToLocalCoord(Index n, Coord &xyz)
3016 {
3017 assert(n<(1<<3*Log2Dim));
3018 xyz.setX(n >> 2*Log2Dim);
3019 n &= ((1<<2*Log2Dim)-1);
3020 xyz.setY(n >> Log2Dim);
3021 xyz.setZ(n & ((1<<Log2Dim)-1));
3022 }
3023
3024
3025 template<typename ChildT, Index Log2Dim>
3026 inline Index
3027 InternalNode<ChildT, Log2Dim>::coordToOffset(const Coord& xyz)
3028 {
3029 return (((xyz[0] & (DIM-1u)) >> ChildNodeType::TOTAL) << 2*Log2Dim)
3030 + (((xyz[1] & (DIM-1u)) >> ChildNodeType::TOTAL) << Log2Dim)
3031 + ((xyz[2] & (DIM-1u)) >> ChildNodeType::TOTAL);
3032 }
3033
3034
3035 template<typename ChildT, Index Log2Dim>
3036 inline Coord
3037 InternalNode<ChildT, Log2Dim>::offsetToGlobalCoord(Index n) const
3038 {
3039 Coord local;
3040 this->offsetToLocalCoord(n, local);
3041 local <<= ChildT::TOTAL;
3042 return local + this->origin();
3043 }
3044
3046
3047 template<typename ChildT, Index Log2Dim>
3048 template<typename ArrayT>
3049 inline void
3050 InternalNode<ChildT, Log2Dim>::getNodes(ArrayT& array)
3051 {
3052 typedef typename ArrayT::value_type T;
3053 BOOST_STATIC_ASSERT(boost::is_pointer<T>::value);
3054 typedef typename boost::mpl::if_<boost::is_const<typename boost::remove_pointer<T>::type>,
3055 const ChildT, ChildT>::type ArrayChildT;
3056 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3057 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
3058 if (boost::is_same<T, ArrayChildT*>::value) {
3059 array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild()));
3060 } else {
3061 iter->getNodes(array);//descent
3062 }
3063 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
3064 }
3065 }
3066
3067 template<typename ChildT, Index Log2Dim>
3068 template<typename ArrayT>
3069 inline void
3070 InternalNode<ChildT, Log2Dim>::getNodes(ArrayT& array) const
3071 {
3072 typedef typename ArrayT::value_type T;
3073 BOOST_STATIC_ASSERT(boost::is_pointer<T>::value);
3074 BOOST_STATIC_ASSERT(boost::is_const<typename boost::remove_pointer<T>::type>::value);
3075 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3076 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
3077 if (boost::is_same<T, const ChildT*>::value) {
3078 array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild()));
3079 } else {
3080 iter->getNodes(array);//descent
3081 }
3082 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
3083 }
3084 }
3085
3087
3088 template<typename ChildT, Index Log2Dim>
3089 template<typename ArrayT>
3090 inline void
3091 InternalNode<ChildT, Log2Dim>::stealNodes(ArrayT& array, const ValueType& value, bool state)
3092 {
3093 typedef typename ArrayT::value_type T;
3094 BOOST_STATIC_ASSERT(boost::is_pointer<T>::value);
3095 typedef typename boost::mpl::if_<boost::is_const<typename boost::remove_pointer<T>::type>,
3096 const ChildT, ChildT>::type ArrayChildT;
3097 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
3098 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3099 const Index n = iter.pos();
3100 if (boost::is_same<T, ArrayChildT*>::value) {
3101 array.push_back(reinterpret_cast<T>(mNodes[n].getChild()));
3102 mValueMask.set(n, state);
3103 mNodes[n].setValue(value);
3104 } else {
3105 iter->stealNodes(array, value, state);//descent
3106 }
3107 }
3108 if (boost::is_same<T, ArrayChildT*>::value) mChildMask.setOff();
3109 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
3110 }
3111
3113
3114
3115 template<typename ChildT, Index Log2Dim>
3116 inline void
3117 InternalNode<ChildT, Log2Dim>::resetBackground(const ValueType& oldBackground,
3118 const ValueType& newBackground)
3119 {
3120 if (math::isExactlyEqual(oldBackground, newBackground)) return;
3121 for (Index i = 0; i < NUM_VALUES; ++i) {
3122 if (this->isChildMaskOn(i)) {
3123 mNodes[i].getChild()->resetBackground(oldBackground, newBackground);
3124 } else if (this->isValueMaskOff(i)) {
3125 if (math::isApproxEqual(mNodes[i].getValue(), oldBackground)) {
3126 mNodes[i].setValue(newBackground);
3127 } else if (math::isApproxEqual(mNodes[i].getValue(), math::negative(oldBackground))) {
3128 mNodes[i].setValue(math::negative(newBackground));
3129 }
3130 }
3131 }
3132 }
3133
3134 template<typename ChildT, Index Log2Dim>
3135 template<typename OtherChildNodeType, Index OtherLog2Dim>
3136 inline bool
3137 InternalNode<ChildT, Log2Dim>::hasSameTopology(
3138 const InternalNode<OtherChildNodeType, OtherLog2Dim>* other) const
3139 {
3140 if (Log2Dim != OtherLog2Dim || mChildMask != other->mChildMask ||
3141 mValueMask != other->mValueMask) return false;
3142 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3143 if (!iter->hasSameTopology(other->mNodes[iter.pos()].getChild())) return false;
3144 }
3145 return true;
3146 }
3147
3148
3149 template<typename ChildT, Index Log2Dim>
3150 inline void
3151 InternalNode<ChildT, Log2Dim>::resetChildNode(Index i, ChildNodeType* child)
3152 {
3153 assert(child);
3154 if (this->isChildMaskOn(i)) {
3155 delete mNodes[i].getChild();
3156 } else {
3157 mChildMask.setOn(i);
3158 mValueMask.setOff(i);
3159 }
3160 mNodes[i].setChild(child);
3161 }
3162
3163 template<typename ChildT, Index Log2Dim>
3164 inline void
3165 InternalNode<ChildT, Log2Dim>::setChildNode(Index i, ChildNodeType* child)
3166 {
3167 assert(child);
3168 assert(mChildMask.isOff(i));
3169 mChildMask.setOn(i);
3170 mValueMask.setOff(i);
3171 mNodes[i].setChild(child);
3172 }
3173
3174
3175 template<typename ChildT, Index Log2Dim>
3176 inline ChildT*
3177 InternalNode<ChildT, Log2Dim>::unsetChildNode(Index i, const ValueType& value)
3178 {
3179 if (this->isChildMaskOff(i)) {
3180 mNodes[i].setValue(value);
3181 return NULL;
3182 }
3183 ChildNodeType* child = mNodes[i].getChild();
3184 mChildMask.setOff(i);
3185 mNodes[i].setValue(value);
3186 return child;
3187 }
3188
3189
3190 template<typename ChildT, Index Log2Dim>
3191 inline void
3192 InternalNode<ChildT, Log2Dim>::makeChildNodeEmpty(Index n, const ValueType& value)
3193 {
3194 delete this->unsetChildNode(n, value);
3195 }
3196
3197 template<typename ChildT, Index Log2Dim>
3198 inline ChildT*
3199 InternalNode<ChildT, Log2Dim>::getChildNode(Index n)
3200 {
3201 assert(this->isChildMaskOn(n));
3202 return mNodes[n].getChild();
3203 }
3204
3205
3206 template<typename ChildT, Index Log2Dim>
3207 inline const ChildT*
3208 InternalNode<ChildT, Log2Dim>::getChildNode(Index n) const
3209 {
3210 assert(this->isChildMaskOn(n));
3211 return mNodes[n].getChild();
3212 }
3213
3214 } // namespace tree
3215 } // namespace OPENVDB_VERSION_NAME
3216 } // namespace openvdb
3217
3218 #endif // OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
3219
3220 // Copyright (c) 2012-2016 DreamWorks Animation LLC
3221 // All rights reserved. This software is distributed under the
3222 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
openvdb::v3_2_0::tree::InternalNode::ValueConverter::Type
InternalNode< typename ChildNodeType::template ValueConverter< OtherValueType >::Type, Log2Dim > Type
Definition: InternalNode.h:88
openvdb::v3_2_0::tree::InternalNode::fill
void fill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
Definition: InternalNode.h:2018
openvdb::v3_2_0::tree::InternalNode::ChildOnCIter
ChildIter< const InternalNode, const ChildNodeType, MaskOnIterator, ChildOn > ChildOnCIter
Definition: InternalNode.h:240
openvdb::v3_2_0::tree::InternalNode::DeepCopy::operator()
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:901
openvdb::v3_2_0::CombineArgs::resultIsActive
bool resultIsActive() const
Definition: Types.h:376
openvdb::v3_2_0::tree::InternalNode::DenseIter
Definition: InternalNode.h:203
openvdb::v3_2_0::tree::InternalNode::setOrigin
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node&#39;s local origin.
Definition: InternalNode.h:302
openvdb::v3_2_0::tree::InternalNode::getNodes
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition: InternalNode.h:3050
openvdb::v3_2_0::math::Coord::minComponent
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition: Coord.h:191
openvdb::v3_2_0::tree::InternalNode::TopologyUnion::s
const OtherInternalNode * s
Definition: InternalNode.h:2459
Types.h
openvdb::v3_2_0::util::NodeMask::isOff
bool isOff(Index32 n) const
Return true if the nth bit is off.
Definition: NodeMasks.h:505
openvdb::v3_2_0::tree::InternalNode::isInactive
bool isInactive() const
Return true if this node has no children and only contains inactive values.
Definition: InternalNode.h:354
openvdb::v3_2_0::tree::InternalNode::getValueOffMask
NodeMaskType getValueOffMask() const
Definition: InternalNode.h:781
openvdb::v3_2_0::tree::InternalNode::visit
void visit(VisitorOp &)
Definition: InternalNode.h:2815
Compression.h
openvdb::v3_2_0::tree::InternalNode::getLastValue
const ValueType & getLastValue() const
If the last entry in this node&#39;s table is a tile, return the tile&#39;s value. Otherwise, return the result of calling getLastValue() on the child.
Definition: InternalNode.h:2216
openvdb::v3_2_0::util::NodeMask::isOn
bool isOn(Index32 n) const
Return true if the nth bit is on.
Definition: NodeMasks.h:499
openvdb::v3_2_0::tree::InternalNode::TopologyDifference::operator()
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2546
openvdb::v3_2_0::tree::InternalNode::TopologyDifference::s
const OtherInternalNode * s
Definition: InternalNode.h:2566
openvdb::v3_2_0::tree::InternalNode::isValueOn
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition: InternalNode.h:1545
openvdb::v3_2_0::tree::InternalNode::isChildMaskOn
bool isChildMaskOn(Index n) const
Definition: InternalNode.h:776
openvdb::v3_2_0::math::isExactlyEqual
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:407
openvdb::v3_2_0::math::Coord::setX
Coord & setX(Int32 x)
Definition: Coord.h:101
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
openvdb::v3_2_0::tree::InternalNode::TopologyCopy1::t
InternalNode * t
Definition: InternalNode.h:957
openvdb::v3_2_0::tree::InternalNode::ValueOffIter
ValueIter< InternalNode, const ValueType, MaskOffIterator, ValueOff > ValueOffIter
Definition: InternalNode.h:248
openvdb::v3_2_0::tools::copyToDense
void copyToDense(const GridOrTreeT &sparse, DenseT &dense, bool serial=false)
Populate a dense grid with the values of voxels from a sparse grid, where the sparse grid intersects ...
Definition: Dense.h:443
openvdb::v3_2_0::TopologyCopy
Definition: Types.h:442
openvdb::v3_2_0::tree::InternalNode::isValueMaskOn
bool isValueMaskOn() const
Definition: InternalNode.h:773
openvdb::v3_2_0::tree::InternalNode::TopologyDifference::t
InternalNode * t
Definition: InternalNode.h:2567
openvdb::v3_2_0::tree::InternalNode::TopologyDifference::A
Definition: InternalNode.h:2526
openvdb::v3_2_0::util::NodeMask::load
void load(std::istream &is)
Definition: NodeMasks.h:566
openvdb::v3_2_0::tree::InternalNode::TopologyDifference::TopologyDifference
TopologyDifference(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:2532
openvdb::v3_2_0::tree::InternalNode::resetChildNode
void resetChildNode(Index i, ChildNodeType *child)
Definition: InternalNode.h:3151
openvdb::v3_2_0::tree::InternalNode::ChildIter::ChildIter
ChildIter(const MaskIterT &iter, NodeT *parent)
Definition: InternalNode.h:164
openvdb::v3_2_0::tree::InternalNode::TopologyCopy1
Definition: InternalNode.h:824
openvdb::v3_2_0::tree::InternalNode::VoxelizeActiveTiles::VoxelizeActiveTiles
VoxelizeActiveTiles(InternalNode &node)
Definition: InternalNode.h:2245
openvdb::v3_2_0::tree::InternalNode::doVisit2
static void doVisit2(NodeT &, OtherChildAllIterT &, VisitorOp &, bool otherIsLHS)
Definition: InternalNode.h:2936
openvdb::v3_2_0::tree::InternalNode::ChildOff
Definition: InternalNode.h:153
openvdb::v3_2_0::tree::InternalNode::unsetChildNode
ChildNodeType * unsetChildNode(Index i, const ValueType &value)
Definition: InternalNode.h:3177
openvdb::v3_2_0::tree::InternalNode::ChildAll
Definition: InternalNode.h:153
openvdb::v3_2_0::MERGE_ACTIVE_STATES
Definition: Types.h:265
openvdb::v3_2_0::tree::InternalNode::nonLeafCount
Index32 nonLeafCount() const
Definition: InternalNode.h:1039
openvdb::v3_2_0::tree::InternalNode::prune
void prune(const ValueType &tolerance=zeroVal< ValueType >())
Reduce the memory footprint of this tree by replacing with tiles any nodes whose values are all the s...
Definition: InternalNode.h:1141
openvdb::v3_2_0::tree::InternalNode::getLevel
static Index getLevel()
Definition: InternalNode.h:282
openvdb::v3_2_0::CombineArgs::setARef
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: Types.h:365
openvdb::v3_2_0::util::NodeMask::countOn
Index32 countOn() const
Return the total number of on bits.
Definition: NodeMasks.h:440
openvdb::v3_2_0::tree::InternalNode::addLeaf
void addLeaf(LeafNodeType *leaf)
Add the specified leaf to this node, possibly creating a child branch in the process. If the leaf node already exists, replace it.
Definition: InternalNode.h:1313
openvdb::v3_2_0::tree::NodeUnion< ValueType, ChildNodeType >
openvdb::v3_2_0::tree::InternalNode::TopologyDifference::A::operator()
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
Definition: InternalNode.h:2526
openvdb::v3_2_0::tree::InternalNode::mChildMask
NodeMaskType mChildMask
Definition: InternalNode.h:832
openvdb::v3_2_0::tree::InternalNode::dim
static Index dim()
Definition: InternalNode.h:279
openvdb::v3_2_0::tree::InternalNode::beginChildOff
ChildOffCIter beginChildOff() const
Definition: InternalNode.h:257
openvdb::v3_2_0::tree::InternalNode::TopologyUnion::A::operator()
void operator()(W &tV, const W &sV, const W &tC) const
Definition: InternalNode.h:2430
openvdb::v3_2_0::tree::InternalNode::isEmpty
bool isEmpty() const
Definition: InternalNode.h:326
openvdb::v3_2_0::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:47
openvdb::v3_2_0::tree::InternalNode::TopologyDifference::b
const ValueType & b
Definition: InternalNode.h:2568
openvdb::v3_2_0::tree::InternalNode::leafCount
Index32 leafCount() const
Definition: InternalNode.h:1026
openvdb::v3_2_0::tree::InternalNode::getNodeLog2Dims
static void getNodeLog2Dims(std::vector< Index > &dims)
Populated an stil::vector with the dimension of all the nodes in the branch starting with this node...
Definition: InternalNode.h:3006
openvdb::v3_2_0::tree::InternalNode::ValueType
ChildNodeType::ValueType ValueType
Definition: InternalNode.h:69
openvdb::v3_2_0::tree::InternalNode::modifyValueAndActiveStateAndCache
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: InternalNode.h:1937
openvdb::v3_2_0::tree::InternalNode::getChildMask
const NodeMaskType & getChildMask() const
Definition: InternalNode.h:780
openvdb::v3_2_0::tree::InternalNode::origin
const Coord & origin() const
Return the grid index coordinates of this node&#39;s local origin.
Definition: InternalNode.h:300
openvdb::v3_2_0::SwappedCombineOp
Definition: Types.h:403
openvdb::v3_2_0::tree::InternalNode::TopologyCopy2::s
const OtherInternalNode * s
Definition: InternalNode.h:992
openvdb::v3_2_0::tree::InternalNode::DeepCopy::t
InternalNode * t
Definition: InternalNode.h:911
openvdb::v3_2_0::tree::InternalNode::merge
void merge(InternalNode &other, const ValueType &background, const ValueType &otherBackground)
Efficiently merge another tree into this tree using one of several schemes.
Definition: InternalNode.h:2290
openvdb::v3_2_0::tree::InternalNode::beginChildAll
ChildAllIter beginChildAll()
Definition: InternalNode.h:261
openvdb::v3_2_0::tree::InternalNode::DenseIter::setItem
void setItem(Index pos, ChildT *child) const
Definition: InternalNode.h:225
openvdb::v3_2_0::tools::composite::max
const boost::disable_if_c< VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:132
openvdb::v3_2_0::tree::InternalNode::TopologyCopy1::TopologyCopy1
TopologyCopy1(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:941
openvdb::v3_2_0::tree::InternalNode::VoxelizeActiveTiles::operator()
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2252
openvdb::v3_2_0::tree::InternalNode::ValueIter::ValueIter
ValueIter()
Definition: InternalNode.h:184
openvdb::v3_2_0::tree::InternalNode::ValueOnIter
ValueIter< InternalNode, const ValueType, MaskOnIterator, ValueOn > ValueOnIter
Definition: InternalNode.h:246
openvdb::v3_2_0::tree::InternalNode::SameConfiguration
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of an Intern...
Definition: InternalNode.h:95
openvdb::v3_2_0::math::Coord::x
Int32 x() const
Definition: Coord.h:146
openvdb::v3_2_0::tree::InternalNode::DenseIter::DenseIter
DenseIter()
Definition: InternalNode.h:209
openvdb::v3_2_0::tree::InternalNode::ValueAll
Definition: InternalNode.h:152
openvdb::v3_2_0::io::getGridBackgroundValuePtr
OPENVDB_API const void * getGridBackgroundValuePtr(std::ios_base &)
Return a pointer to the background value of the grid currently being read from or written to the give...
openvdb::v3_2_0::tree::InternalNode::modifyValueAndActiveState
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: InternalNode.h:1914
openvdb::v3_2_0::util::NodeMask::countOff
Index32 countOff() const
Return the total number of on bits.
Definition: NodeMasks.h:447
openvdb::v3_2_0::tree::InternalNode::ChildAllIter
DenseIter< InternalNode, ChildNodeType, ValueType, ChildAll > ChildAllIter
Definition: InternalNode.h:243
openvdb::v3_2_0::tree::InternalNode::ValueOff
Definition: InternalNode.h:152
openvdb::v3_2_0::tree::InternalNode::topologyIntersection
void topologyIntersection(const InternalNode< OtherChildNodeType, Log2Dim > &other, const ValueType &background)
Intersects this tree&#39;s set of active values with the active values of the other tree, whose ValueType may be different.
openvdb::v3_2_0::tree::InternalNode::TopologyCopy1::operator()
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:946
openvdb::v3_2_0::tree::InternalNode::TopologyDifference::B
Definition: InternalNode.h:2529
openvdb::v3_2_0::tree::InternalNode::TopologyIntersection::operator()
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2491
openvdb::v3_2_0::tree::InternalNode::offVoxelCount
Index64 offVoxelCount() const
Definition: InternalNode.h:1064
openvdb::v3_2_0::math::Coord::setY
Coord & setY(Int32 y)
Definition: Coord.h:102
openvdb::v3_2_0::tree::InternalNode::memUsage
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
Definition: InternalNode.h:1110
openvdb::v3_2_0::math::Coord::lessThan
static bool lessThan(const Coord &a, const Coord &b)
Definition: Coord.h:224
openvdb::v3_2_0::math::isApproxEqual
bool isApproxEqual(const Type &a, const Type &b)
Return true if a is equal to b to within the default floating-point comparison tolerance.
Definition: Math.h:370
openvdb::v3_2_0::tree::InternalNode::visit2
void visit2(IterT &otherIter, VisitorOp &, bool otherIsLHS=false)
openvdb::v3_2_0::Index
Index32 Index
Definition: Types.h:58
openvdb::v3_2_0::util::NodeMask::toggle
void toggle(Index32 n)
Toggle the state of the nth bit.
Definition: NodeMasks.h:480
openvdb::v3_2_0::tree::InternalNode::TopologyUnion::TopologyUnion
TopologyUnion(const OtherInternalNode *source, InternalNode *target)
Definition: InternalNode.h:2433
openvdb::v3_2_0::tree::InternalNode::stealNode
NodeT * stealNode(const Coord &xyz, const ValueType &value, bool state)
Return a pointer to the node of type NodeT that contains voxel (x, y, z) and replace it with a tile o...
Definition: InternalNode.h:1165
openvdb::v3_2_0::tree::InternalNode::beginChildOn
ChildOnIter beginChildOn()
Definition: InternalNode.h:259
openvdb::v3_2_0::tree::InternalNode::MaskOffIterator
NodeMaskType::OffIterator MaskOffIterator
Definition: InternalNode.h:148
openvdb::v3_2_0::util::NodeMask::isConstant
bool isConstant(bool &isOn) const
Definition: NodeMasks.h:523
openvdb::v3_2_0::tree::InternalNode::MaskOnIterator
NodeMaskType::OnIterator MaskOnIterator
Definition: InternalNode.h:147
openvdb::v3_2_0::tree::InternalNode::cbeginChildOn
ChildOnCIter cbeginChildOn() const
Definition: InternalNode.h:253
openvdb::v3_2_0::tree::InternalNode::beginChildAll
ChildAllCIter beginChildAll() const
Definition: InternalNode.h:258
openvdb::v3_2_0::tree::InternalNode::getFirstValue
const ValueType & getFirstValue() const
If the first entry in this node&#39;s table is a tile, return the tile&#39;s value. Otherwise, return the result of calling getFirstValue() on the child.
Definition: InternalNode.h:2208
openvdb::v3_2_0::Int32
int32_t Int32
Definition: Types.h:60
openvdb::v3_2_0::tree::InternalNode::isValueOn
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Definition: InternalNode.h:359
openvdb::v3_2_0::tree::InternalNode::getNodeBoundingBox
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by the node regardless of it...
Definition: InternalNode.h:323
openvdb::v3_2_0::tree::InternalNode::readBuffers
void readBuffers(std::istream &, bool fromHalf=false)
Definition: InternalNode.h:2971
openvdb::v3_2_0::Index64
uint64_t Index64
Definition: Types.h:57
openvdb::v3_2_0::tree::InternalNode::VoxelizeActiveTiles::mNode
InternalNode * mNode
Definition: InternalNode.h:2265
openvdb::v3_2_0::tree::InternalNode::UnionType
NodeUnion< ValueType, ChildNodeType > UnionType
Definition: InternalNode.h:71
openvdb::v3_2_0::tree::InternalNode::beginValueOff
ValueOffCIter beginValueOff() const
Definition: InternalNode.h:269
openvdb::v3_2_0::tree::InternalNode::isValueOnAndCache
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Definition: InternalNode.h:1555
openvdb::v3_2_0::tree::InternalNode::TopologyDifference
Definition: InternalNode.h:827
openvdb::v3_2_0::tree::InternalNode::TopologyDifference::W
NodeMaskType::Word W
Definition: InternalNode.h:2525
openvdb::v3_2_0::tree::InternalNode::DenseIter::getItem
bool getItem(Index pos, ChildT *&child, NonConstValueT &value) const
Definition: InternalNode.h:213
openvdb::v3_2_0::tree::InternalNode::TopologyIntersection::b
const ValueType & b
Definition: InternalNode.h:2509
openvdb::v3_2_0::tree::InternalNode::writeBuffers
void writeBuffers(std::ostream &, bool toHalf=false) const
Definition: InternalNode.h:2961
openvdb::v3_2_0::tree::InternalNode::evalActiveBoundingBox
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Expand the specified bounding box so that it includes the active tiles of this internal node as well ...
Definition: InternalNode.h:1123
openvdb::v3_2_0::tree::InternalNode::cbeginChildAll
ChildAllCIter cbeginChildAll() const
Definition: InternalNode.h:255
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
Definition: version.h:43
openvdb::v3_2_0::tree::InternalNode::coordToOffset
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition: InternalNode.h:3027
openvdb::v3_2_0::tools::clip
OPENVDB_STATIC_SPECIALIZATION GridType::Ptr clip(const GridType &grid, const BBoxd &)
Clip the given grid against a world-space bounding box and return a new grid containing the result...
Definition: Clip.h:356
openvdb::v3_2_0::tree::InternalNode::addLeafAndCache
void addLeafAndCache(LeafNodeType *leaf, AccessorT &)
Same as addLeaf() except, if necessary, update the accessor with pointers to the nodes along the path...
Definition: InternalNode.h:1342
openvdb::v3_2_0::io::readCompressedValues
void readCompressedValues(std::istream &is, ValueT *destBuf, Index destCount, const MaskT &valueMask, bool fromHalf)
Definition: Compression.h:329
openvdb::v3_2_0::tree::InternalNode
Definition: InternalNode.h:64
openvdb::v3_2_0::tree::InternalNode::TopologyDifference::B::operator()
void operator()(W &tV, const W &sC, const W &sV, const W &tC) const
Definition: InternalNode.h:2529
openvdb::v3_2_0::math::Coord::setZ
Coord & setZ(Int32 z)
Definition: Coord.h:103
openvdb::v3_2_0::tree::InternalNode::beginValueOn
ValueOnCIter beginValueOn() const
Definition: InternalNode.h:267
openvdb::v3_2_0::tree::InternalNode::doVisit
static void doVisit(NodeT &, VisitorOp &)
Definition: InternalNode.h:2833
openvdb::v3_2_0::tree::InternalNode::visitActiveBBox
void visitActiveBBox(BBoxOp &) const
Calls the templated functor BBoxOp with bounding box information for all active tiles and leaf nodes ...
Definition: InternalNode.h:2789
openvdb::v3_2_0::tree::InternalNode::copyToDense
void copyToDense(const CoordBBox &bbox, DenseT &dense) const
Copy into a dense grid the values of the voxels that lie within a given bounding box.
Definition: InternalNode.h:2072
openvdb::v3_2_0::tree::InternalNode::topologyUnion
void topologyUnion(const InternalNode< OtherChildNodeType, Log2Dim > &other)
Union this branch&#39;s set of active values with the other branch&#39;s active values. The value type of the...
openvdb::v3_2_0::tree::InternalNode::ValueIter::modifyItem
void modifyItem(Index pos, const ModifyOp &op) const
Definition: InternalNode.h:195
openvdb::v3_2_0::math::CoordBBox::expand
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:401
openvdb::v3_2_0::tree::InternalNode::probeNodeAndCache
NodeType * probeNodeAndCache(const Coord &xyz, AccessorT &)
Same as probeNode() except, if necessary, update the accessor with pointers to the nodes along the pa...
openvdb::v3_2_0::OPENVDB_FILE_VERSION_NODE_MASK_COMPRESSION
Definition: version.h:110
openvdb::v3_2_0::tree::InternalNode::resetBackground
void resetBackground(const ValueType &oldBackground, const ValueType &newBackground)
Change inactive tiles or voxels with value oldBackground to newBackground or -oldBackground to -newBa...
Definition: InternalNode.h:3117
openvdb::v3_2_0::tree::InternalNode::probeLeaf
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return NULL.
Definition: InternalNode.h:1267
openvdb::v3_2_0::tree::InternalNode::ChildNodeType
_ChildNodeType ChildNodeType
Definition: InternalNode.h:67
openvdb::v3_2_0::tree::InternalNode::getValue
const ValueType & getValue(const Coord &xyz) const
Definition: InternalNode.h:1566
openvdb::v3_2_0::tree::InternalNode::ValueIter
Definition: InternalNode.h:181
openvdb::v3_2_0::CombineArgs::result
const AValueType & result() const
Get the output value.
Definition: Types.h:357
openvdb::v3_2_0::tree::InternalNode::isChildMaskOff
bool isChildMaskOff(Index n) const
Definition: InternalNode.h:777
openvdb::v3_2_0::tree::InternalNode::TopologyUnion::A
Definition: InternalNode.h:2430
openvdb::v3_2_0::tree::InternalNode::setActiveStateAndCache
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Definition: InternalNode.h:1817
openvdb::v3_2_0::tree::InternalNode::TopologyCopy2::TopologyCopy2
TopologyCopy2(const OtherInternalNode *source, InternalNode *target, const ValueType &offValue, const ValueType &onValue)
Definition: InternalNode.h:977
openvdb::v3_2_0::tree::InternalNode::modifyValue
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
Definition: InternalNode.h:1852
openvdb::v3_2_0::tree::InternalNode::ChildOffCIter
ValueIter< const InternalNode, const ValueType, MaskOffIterator, ChildOff > ChildOffCIter
Definition: InternalNode.h:242
openvdb::v3_2_0::tree::InternalNode::isValueMaskOff
bool isValueMaskOff(Index n) const
Definition: InternalNode.h:774
openvdb::v3_2_0::tree::InternalNode::TopologyIntersection::A::operator()
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
Definition: InternalNode.h:2476
openvdb::v3_2_0::tree::InternalNode::getValueAndCache
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
openvdb::v3_2_0::tree::InternalNode::TopologyIntersection::t
InternalNode * t
Definition: InternalNode.h:2508
openvdb::v3_2_0::tree::InternalNode::TopologyCopy2::t
InternalNode * t
Definition: InternalNode.h:993
openvdb::v3_2_0::io::getFormatVersion
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
openvdb::v3_2_0::tree::InternalNode::NUM_VALUES
static const Index NUM_VALUES
Definition: InternalNode.h:78
openvdb::v3_2_0::tree::InternalNode::offsetToLocalCoord
static void offsetToLocalCoord(Index n, Coord &xyz)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0...
Definition: InternalNode.h:3015
openvdb::v3_2_0::tree::InternalNode::topologyDifference
void topologyDifference(const InternalNode< OtherChildNodeType, Log2Dim > &other, const ValueType &background)
Difference this node&#39;s set of active values with the active values of the other node, whose ValueType may be different. So a resulting voxel will be active only if the original voxel is active in this node and inactive in the other node.
openvdb::v3_2_0::tree::InternalNode::ValueIter::getItem
const ValueT & getItem(Index pos) const
Definition: InternalNode.h:188
openvdb::v3_2_0::util::NodeMask
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
Definition: NodeMasks.h:304
openvdb::v3_2_0::tree::InternalNode::setValueOn
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don&#39;t change its value.
Definition: InternalNode.h:1655
openvdb::v3_2_0::math::CoordBBox::translate
void translate(const Coord &t)
Translate this bounding box by .
Definition: Coord.h:440
openvdb::v3_2_0::io::writeCompressedValues
void writeCompressedValues(std::ostream &os, ValueT *srcBuf, Index srcCount, const MaskT &valueMask, const MaskT &childMask, bool toHalf)
Definition: Compression.h:431
openvdb::v3_2_0::tree::InternalNode::TopologyUnion::W
NodeMaskType::Word W
Definition: InternalNode.h:2429
openvdb::v3_2_0::tree::InternalNode::probeConstLeaf
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return NULL.
Definition: InternalNode.h:1293
openvdb::v3_2_0::math::Coord::offsetBy
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:111
openvdb::v3_2_0::tree::InternalNode::DenseIter::unsetItem
void unsetItem(Index pos, const ValueT &value) const
Definition: InternalNode.h:231
openvdb::v3_2_0::tree::InternalNode::writeTopology
void writeTopology(std::ostream &, bool toHalf=false) const
Definition: InternalNode.h:2115
openvdb
Definition: Exceptions.h:39
openvdb::v3_2_0::tree::InternalNode::mNodes
UnionType mNodes[NUM_VALUES]
Definition: InternalNode.h:828
openvdb::v3_2_0::tree::InternalNode::setValueAndCache
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1736
openvdb::v3_2_0::Index32
uint32_t Index32
Definition: Types.h:56
openvdb::v3_2_0::tree::InternalNode::beginChildOn
ChildOnCIter beginChildOn() const
Definition: InternalNode.h:256
OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
Definition: Platform.h:129
openvdb::v3_2_0::tree::InternalNode::mValueMask
NodeMaskType mValueMask
Definition: InternalNode.h:832
openvdb::v3_2_0::tree::InternalNode::ValueConverter
ValueConverter<T>::Type is the type of an InternalNode having the same child hierarchy and dimensions...
Definition: InternalNode.h:86
openvdb::v3_2_0::tree::InternalNode::DeepCopy::s
const OtherInternalNode * s
Definition: InternalNode.h:910
openvdb::v3_2_0::tree::InternalNode::cbeginChildOff
ChildOffCIter cbeginChildOff() const
Definition: InternalNode.h:254
openvdb::v3_2_0::tree::InternalNode::setChildNode
void setChildNode(Index i, ChildNodeType *child)
Definition: InternalNode.h:3165
openvdb::v3_2_0::tree::InternalNode::probeValue
bool probeValue(const Coord &xyz, ValueType &value) const
Definition: InternalNode.h:1611
openvdb::v3_2_0::tree::InternalNode::getValueLevelAndCache
Index getValueLevelAndCache(const Coord &xyz, AccessorT &) const
Return the level of the tree (0 = leaf) at which the value at the given coordinates resides...
Definition: InternalNode.h:1598
openvdb::v3_2_0::util::NodeMask::Word
Index64 Word
Definition: NodeMasks.h:313
openvdb::v3_2_0::tree::InternalNode::ValueAllIter
ValueIter< InternalNode, const ValueType, MaskOffIterator, ValueAll > ValueAllIter
Definition: InternalNode.h:250
openvdb::v3_2_0::tree::InternalNode::MaskDenseIterator
NodeMaskType::DenseIterator MaskDenseIterator
Definition: InternalNode.h:149
openvdb::v3_2_0::tree::InternalNode::visit2Node
void visit2Node(OtherNodeType &other, VisitorOp &)
Definition: InternalNode.h:2851
openvdb::v3_2_0::tree::DenseIteratorBase
Base class for dense iterators over internal and leaf nodes.
Definition: Iterator.h:211
openvdb::v3_2_0::tree::SameInternalConfig
Definition: InternalNode.h:60
openvdb::v3_2_0::tree::SparseIteratorBase
Base class for sparse iterators over internal and leaf nodes.
Definition: Iterator.h:148
openvdb::v3_2_0::tree::InternalNode::setValuesOn
void setValuesOn()
Mark all values (both tiles and voxels) as active.
Definition: InternalNode.h:1840
openvdb::v3_2_0::tree::InternalNode::probeConstLeafAndCache
const LeafNodeType * probeConstLeafAndCache(const Coord &xyz, AccessorT &acc) const
Same as probeLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
openvdb::v3_2_0::tree::InternalNode::DenseIter::BaseT
DenseIteratorBase< MaskDenseIterator, DenseIter, NodeT, ChildT, ValueT > BaseT
Definition: InternalNode.h:206
openvdb::v3_2_0::tree::DenseIteratorBase::NonConstValueType
boost::remove_const< UnsetItemT >::type NonConstValueType
Definition: Iterator.h:217
openvdb::v3_2_0::util::NodeMask::set
void set(Index32 n, bool On)
Set the nth bit to the specified state.
Definition: NodeMasks.h:459
openvdb::v3_2_0::tree::InternalNode::probeConstNodeAndCache
const NodeType * probeConstNodeAndCache(const Coord &xyz, AccessorT &) const
Same as probeNode() except, if necessary, update the accessor with pointers to the nodes along the pa...
openvdb::v3_2_0::tree::InternalNode::probeValueAndCache
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Definition: InternalNode.h:1624
openvdb::v3_2_0::tree::InternalNode::setActiveState
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don&#39;t change its value.
Definition: InternalNode.h:1798
openvdb::v3_2_0::math::Coord::z
Int32 z() const
Definition: Coord.h:148
openvdb::v3_2_0::tree::InternalNode::beginValueOff
ValueOffIter beginValueOff()
Definition: InternalNode.h:273
openvdb::v3_2_0::tree::InternalNode::getChildNode
ChildNodeType * getChildNode(Index n)
Returns a pointer to the child node at the linear offset n.
Definition: InternalNode.h:3199
openvdb::v3_2_0::tree::InternalNode::getValueMask
const NodeMaskType & getValueMask() const
Definition: InternalNode.h:779
openvdb::v3_2_0::util::NodeMask::memUsage
static Index32 memUsage()
Return the byte size of this NodeMask.
Definition: NodeMasks.h:438
openvdb::v3_2_0::util::DenseMaskIterator
Definition: NodeMasks.h:267
openvdb::v3_2_0::tree::InternalNode::DeepCopy
Definition: InternalNode.h:823
version.h
openvdb::v3_2_0::tree::InternalNode::cbeginValueOn
ValueOnCIter cbeginValueOn() const
Definition: InternalNode.h:263
openvdb::v3_2_0::tree::InternalNode::probeConstNode
const NodeType * probeConstNode(const Coord &xyz) const
Return a pointer to the node that contains voxel (x, y, z). If no such node exists, return NULL.
openvdb::v3_2_0::tree::InternalNode::mOrigin
Coord mOrigin
Global grid index coordinates (x,y,z) of the local origin of this node.
Definition: InternalNode.h:834
openvdb::v3_2_0::tree::InternalNode::ChildIter::ChildIter
ChildIter()
Definition: InternalNode.h:163
openvdb::v3_2_0::tree::InternalNode::TopologyIntersection
Definition: InternalNode.h:828
openvdb::v3_2_0::tree::InternalNode::TopologyIntersection::A
Definition: InternalNode.h:2476
openvdb::v3_2_0::tree::InternalNode::clip
void clip(const CoordBBox &, const ValueType &background)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: InternalNode.h:1968
openvdb::v3_2_0::util::NodeMask::setOn
void setOn(Index32 n)
Set the nth bit on.
Definition: NodeMasks.h:449
openvdb::v3_2_0::tree::InternalNode::TopologyCopy1::s
const OtherInternalNode * s
Definition: InternalNode.h:956
openvdb::v3_2_0::tree::InternalNode::stealNodes
void stealNodes(ArrayT &array, const ValueType &value, bool state)
Steals all nodes of a certain type from the tree and adds them to a container with the following API:...
Definition: InternalNode.h:3091
openvdb::v3_2_0::tree::InternalNode::beginChildOff
ChildOffIter beginChildOff()
Definition: InternalNode.h:260
openvdb::v3_2_0::math::CoordBBox::min
const Coord & min() const
Definition: Coord.h:332
openvdb::v3_2_0::tree::InternalNode::isConstant
bool isConstant(ValueType &firstValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
Definition: InternalNode.h:1486
openvdb::v3_2_0::OPENVDB_FILE_VERSION_INTERNALNODE_COMPRESSION
Definition: version.h:101
openvdb::v3_2_0::tree::InternalNode::doVisit2Node
static void doVisit2Node(NodeT &, OtherNodeT &, VisitorOp &)
Definition: InternalNode.h:2876
openvdb::v3_2_0::tree::InternalNode::LeafNodeType
ChildNodeType::LeafNodeType LeafNodeType
Definition: InternalNode.h:68
openvdb::v3_2_0::tree::InternalNode::ValueIter::setItem
void setItem(Index pos, const ValueT &v) const
Definition: InternalNode.h:191
openvdb::v3_2_0::tree::InternalNode::hasActiveTiles
bool hasActiveTiles() const
Return true if this node or any of its child nodes have any active tiles.
Definition: InternalNode.h:1530
openvdb::v3_2_0::tree::InternalNode::ValueOnCIter
ValueIter< const InternalNode, const ValueType, MaskOnIterator, ValueOn > ValueOnCIter
Definition: InternalNode.h:247
openvdb::v3_2_0::tree::InternalNode::setValueOnlyAndCache
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1777
openvdb::v3_2_0::tree::InternalNode::InternalNode
InternalNode()
Default constructor.
Definition: InternalNode.h:103
openvdb::v3_2_0::util::NodeMask::save
void save(std::ostream &os) const
Definition: NodeMasks.h:562
openvdb::v3_2_0::tree::InternalNode::getChildDim
static Index getChildDim()
Definition: InternalNode.h:289
openvdb::v3_2_0::math::CoordBBox::hasOverlap
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition: Coord.h:395
openvdb::v3_2_0::tree::InternalNode::negate
void negate()
Definition: InternalNode.h:2228
openvdb::v3_2_0::math::CoordBBox::max
const Coord & max() const
Definition: Coord.h:333
OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:130
openvdb::v3_2_0::tree::InternalNode::setValueOffAndCache
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1691
openvdb::v3_2_0::tree::InternalNode::NodeMaskType
util::NodeMask< Log2Dim > NodeMaskType
Definition: InternalNode.h:72
openvdb::v3_2_0::math::CoordBBox
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:259
openvdb::v3_2_0::tree::InternalNode::ChildOnIter
ChildIter< InternalNode, ChildNodeType, MaskOnIterator, ChildOn > ChildOnIter
Definition: InternalNode.h:239
openvdb::v3_2_0::tree::InternalNode::beginValueOn
ValueOnIter beginValueOn()
Definition: InternalNode.h:271
openvdb::v3_2_0::tree::InternalNode::TopologyIntersection::s
const OtherInternalNode * s
Definition: InternalNode.h:2507
NodeUnion.h
openvdb::v3_2_0::tree::InternalNode::onTileCount
Index64 onTileCount() const
Definition: InternalNode.h:1099
openvdb::v3_2_0::tree::InternalNode::DIM
static const Index DIM
Definition: InternalNode.h:77
openvdb::v3_2_0::tree::InternalNode::onLeafVoxelCount
Index64 onLeafVoxelCount() const
Definition: InternalNode.h:1076
openvdb::v3_2_0::MERGE_ACTIVE_STATES_AND_NODES
Definition: Types.h:267
openvdb::v3_2_0::tree::InternalNode::modifyValueAndCache
void modifyValueAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
Definition: InternalNode.h:1880
openvdb::v3_2_0::tree::InternalNode::ChildIter::setItem
void setItem(Index pos, const ChildT &c) const
Definition: InternalNode.h:174
openvdb::v3_2_0::tree::InternalNode::combine
void combine(InternalNode &other, CombineOp &)
Definition: InternalNode.h:2586
openvdb::v3_2_0::tree::InternalNode::ChildIter
Definition: InternalNode.h:160
openvdb::v3_2_0::tree::InternalNode::addTileAndCache
void addTileAndCache(Index level, const Coord &xyz, const ValueType &, bool state, AccessorT &)
Same as addTile() except, if necessary, update the accessor with pointers to the nodes along the path...
Definition: InternalNode.h:1417
openvdb::v3_2_0::tree::InternalNode::isChildMaskOff
bool isChildMaskOff() const
Definition: InternalNode.h:778
openvdb::v3_2_0::util::NodeMask::setOff
void setOff(Index32 n)
Set the nth bit off.
Definition: NodeMasks.h:454
openvdb::v3_2_0::tree::InternalNode::TopologyCopy2::operator()
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:982
openvdb::v3_2_0::tree::InternalNode::BuildType
ChildNodeType::BuildType BuildType
Definition: InternalNode.h:70
openvdb::v3_2_0::tree::InternalNode::ValueOffCIter
ValueIter< const InternalNode, const ValueType, MaskOffIterator, ValueOff > ValueOffCIter
Definition: InternalNode.h:249
openvdb::v3_2_0::math::Coord::y
Int32 y() const
Definition: Coord.h:147
openvdb::v3_2_0::tree::InternalNode::setValueOff
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don&#39;t change its value.
Definition: InternalNode.h:1639
Iterator.h
openvdb::v3_2_0::tree::InternalNode::TopologyIntersection::W
NodeMaskType::Word W
Definition: InternalNode.h:2475
openvdb::v3_2_0::tree::InternalNode::TopologyIntersection::TopologyIntersection
TopologyIntersection(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:2479
openvdb::v3_2_0::tree::InternalNode::makeChildNodeEmpty
void makeChildNodeEmpty(Index n, const ValueType &value)
Definition: InternalNode.h:3192
openvdb::v3_2_0::tree::InternalNode::onVoxelCount
Index64 onVoxelCount() const
Definition: InternalNode.h:1052
openvdb::v3_2_0::tree::InternalNode::cbeginValueAll
ValueAllCIter cbeginValueAll() const
Definition: InternalNode.h:266
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::tree::InternalNode::ChildAllCIter
DenseIter< const InternalNode, const ChildNodeType, ValueType, ChildAll > ChildAllCIter
Definition: InternalNode.h:244
openvdb::v3_2_0::tree::InternalNode::TopologyUnion
Definition: InternalNode.h:826
openvdb::v3_2_0::tree::InternalNode::DenseIter::DenseIter
DenseIter(const MaskDenseIterator &iter, NodeT *parent)
Definition: InternalNode.h:210
openvdb::v3_2_0::tree::InternalNode::offsetToGlobalCoord
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Definition: InternalNode.h:3037
openvdb::v3_2_0::tree::InternalNode::VoxelizeActiveTiles
Definition: InternalNode.h:2243
openvdb::v3_2_0::tree::InternalNode::voxelizeActiveTiles
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition: InternalNode.h:2270
openvdb::v3_2_0::util::OnMaskIterator
Definition: NodeMasks.h:205
openvdb::v3_2_0::tree::InternalNode::TopologyUnion::t
InternalNode * t
Definition: InternalNode.h:2460
openvdb::v3_2_0::util::OffMaskIterator
Definition: NodeMasks.h:236
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::tree::InternalNode::beginValueAll
ValueAllCIter beginValueAll() const
Definition: InternalNode.h:270
NodeMasks.h
openvdb::v3_2_0::tree::InternalNode::DenseIter::NonConstValueT
BaseT::NonConstValueType NonConstValueT
Definition: InternalNode.h:207
openvdb::v3_2_0::tree::InternalNode::TopologyUnion::operator()
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2443
openvdb::v3_2_0::math::CoordBBox::isInside
bool isInside(const Coord &xyz) const
Return true if point (x, y, z) is inside this bounding box.
Definition: Coord.h:383
openvdb::v3_2_0::tree::InternalNode::ChildIter::getItem
ChildT & getItem(Index pos) const
Definition: InternalNode.h:167
openvdb::v3_2_0::PartialCreate
Definition: Types.h:444
openvdb::v3_2_0::tree::InternalNode::probeNode
NodeType * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists, return NULL.
openvdb::v3_2_0::tree::InternalNode::LEVEL
static const Index LEVEL
Definition: InternalNode.h:79
openvdb::v3_2_0::tree::InternalNode::ValueIter::ValueIter
ValueIter(const MaskIterT &iter, NodeT *parent)
Definition: InternalNode.h:185
openvdb::v3_2_0::tree::InternalNode::ChildOffIter
ValueIter< InternalNode, const ValueType, MaskOffIterator, ChildOff > ChildOffIter
Definition: InternalNode.h:241
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
openvdb::v3_2_0::tree::InternalNode::ChildOn
Definition: InternalNode.h:153
openvdb::v3_2_0::tree::InternalNode::hasSameTopology
bool hasSameTopology(const InternalNode< OtherChildNodeType, OtherLog2Dim > *other) const
Return true if the given tree branch has the same node and active value topology as this tree branch ...
Definition: InternalNode.h:3137
openvdb::v3_2_0::tree::InternalNode::cbeginValueOff
ValueOffCIter cbeginValueOff() const
Definition: InternalNode.h:265
openvdb::v3_2_0::tree::InternalNode::ValueAllCIter
ValueIter< const InternalNode, const ValueType, MaskOffIterator, ValueAll > ValueAllCIter
Definition: InternalNode.h:251
openvdb::v3_2_0::tree::InternalNode::addTile
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly creating a parent bran...
Definition: InternalNode.h:1385
openvdb::v3_2_0::tree::InternalNode::getTable
const UnionType * getTable() const
Definition: InternalNode.h:788
openvdb::v3_2_0::tree::InternalNode::offLeafVoxelCount
Index64 offLeafVoxelCount() const
Definition: InternalNode.h:1088
openvdb::v3_2_0::tree::InternalNode::isValueMaskOff
bool isValueMaskOff() const
Definition: InternalNode.h:775
openvdb::v3_2_0::tree::InternalNode::setValueOnly
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates but don&#39;t change its active state.
Definition: InternalNode.h:1760
openvdb::v3_2_0::MERGE_NODES
Definition: Types.h:266
openvdb::v3_2_0::tree::InternalNode::touchLeaf
LeafNodeType * touchLeaf(const Coord &xyz)
Return the leaf node that contains voxel (x, y, z). If no such node exists, create one...
Definition: InternalNode.h:1453
openvdb::v3_2_0::tree::InternalNode::~InternalNode
virtual ~InternalNode()
Definition: InternalNode.h:1013
openvdb::v3_2_0::tree::InternalNode::TopologyCopy1::b
const ValueType & b
Definition: InternalNode.h:958
openvdb::v3_2_0::tree::InternalNode::getValueLevel
Index getValueLevel(const Coord &xyz) const
Return the level of the tree (0 = leaf) at which the value at the given coordinates resides...
Definition: InternalNode.h:1589
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::tree::InternalNode::TopologyCopy2
Definition: InternalNode.h:825
openvdb::v3_2_0::tree::InternalNode::ValueOn
Definition: InternalNode.h:152
openvdb::v3_2_0::tree::InternalNode::TopologyCopy2::onV
const ValueType & onV
Definition: InternalNode.h:994
openvdb::v3_2_0::tree::InternalNode::isValueMaskOn
bool isValueMaskOn(Index n) const
Definition: InternalNode.h:772
openvdb::v3_2_0::tree::InternalNode::touchLeafAndCache
LeafNodeType * touchLeafAndCache(const Coord &xyz, AccessorT &)
Same as touchLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
openvdb::v3_2_0::tree::InternalNode::probeLeafAndCache
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
openvdb::v3_2_0::tree::InternalNode::combine2
void combine2(const InternalNode &other0, const OtherNodeType &other1, CombineOp &)
Definition: InternalNode.h:2673
openvdb::v3_2_0::math::CoordBBox::createCube
static CoordBBox createCube(const Coord &min, ValueType dim)
Definition: Coord.h:324
openvdb::v3_2_0::tree::InternalNode::DeepCopy::DeepCopy
DeepCopy(const OtherInternalNode *source, InternalNode *target)
Definition: InternalNode.h:897
openvdb::v3_2_0::tree::InternalNode::readTopology
void readTopology(std::istream &, bool fromHalf=false)
Definition: InternalNode.h:2139
Platform.h
openvdb::v3_2_0::tree::InternalNode::beginValueAll
ValueAllIter beginValueAll()
Definition: InternalNode.h:274
openvdb::v3_2_0::tree::IteratorBase
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:58
openvdb::v3_2_0::tools::composite::min
const boost::disable_if_c< VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:128