Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0 | ||
3 | // | ||
4 | /// @file InternalNode.h | ||
5 | /// | ||
6 | /// @brief Internal table nodes for OpenVDB trees | ||
7 | |||
8 | #ifndef OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED | ||
9 | #define OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED | ||
10 | |||
11 | #include <openvdb/Platform.h> | ||
12 | #include <openvdb/util/NodeMasks.h> | ||
13 | #include <openvdb/io/Compression.h> // for io::readCompressedValues(), etc. | ||
14 | #include <openvdb/math/Math.h> // for math::isExactlyEqual(), etc. | ||
15 | #include <openvdb/version.h> | ||
16 | #include <openvdb/Types.h> | ||
17 | #include "Iterator.h" | ||
18 | #include "NodeUnion.h" | ||
19 | #include <tbb/parallel_for.h> | ||
20 | #include <memory> | ||
21 | #include <type_traits> | ||
22 | |||
23 | |||
24 | namespace openvdb { | ||
25 | OPENVDB_USE_VERSION_NAMESPACE | ||
26 | namespace OPENVDB_VERSION_NAME { | ||
27 | namespace tree { | ||
28 | |||
29 | template<typename, Index, typename> struct SameInternalConfig; // forward declaration | ||
30 | |||
31 | |||
32 | template<typename _ChildNodeType, Index Log2Dim> | ||
33 | class InternalNode | ||
34 | { | ||
35 | public: | ||
36 | using ChildNodeType = _ChildNodeType; | ||
37 | using LeafNodeType = typename ChildNodeType::LeafNodeType; | ||
38 | using ValueType = typename ChildNodeType::ValueType; | ||
39 | using BuildType = typename ChildNodeType::BuildType; | ||
40 | using UnionType = NodeUnion<ValueType, ChildNodeType>; | ||
41 | using NodeMaskType = util::NodeMask<Log2Dim>; | ||
42 | |||
43 | static const Index | ||
44 | LOG2DIM = Log2Dim, // log2 of tile count in one dimension | ||
45 | TOTAL = Log2Dim + ChildNodeType::TOTAL, // log2 of voxel count in one dimension | ||
46 | DIM = 1 << TOTAL, // total voxel count in one dimension | ||
47 | NUM_VALUES = 1 << (3 * Log2Dim), // total voxel count represented by this node | ||
48 | LEVEL = 1 + ChildNodeType::LEVEL; // level 0 = leaf | ||
49 | static const Index64 | ||
50 | NUM_VOXELS = uint64_t(1) << (3 * TOTAL); // total voxel count represented by this node | ||
51 | |||
52 | /// @brief ValueConverter<T>::Type is the type of an InternalNode having the same | ||
53 | /// child hierarchy and dimensions as this node but a different value type, T. | ||
54 | template<typename OtherValueType> | ||
55 | struct ValueConverter { | ||
56 | using Type = InternalNode<typename ChildNodeType::template ValueConverter< | ||
57 | OtherValueType>::Type, Log2Dim>; | ||
58 | }; | ||
59 | |||
60 | /// @brief SameConfiguration<OtherNodeType>::value is @c true if and only if OtherNodeType | ||
61 | /// is the type of an InternalNode with the same dimensions as this node and whose | ||
62 | /// ChildNodeType has the same configuration as this node's ChildNodeType. | ||
63 | template<typename OtherNodeType> | ||
64 | struct SameConfiguration { | ||
65 | static const bool value = | ||
66 | SameInternalConfig<ChildNodeType, Log2Dim, OtherNodeType>::value; | ||
67 | }; | ||
68 | |||
69 | |||
70 | /// @brief Default constructor | ||
71 | /// @warning The resulting InternalNode is uninitialized | ||
72 | InternalNode() {} | ||
73 | |||
74 | /// @brief Constructor of an InternalNode with dense inactive tiles of the specified value. | ||
75 | /// @param offValue Background value used for inactive values | ||
76 | explicit InternalNode(const ValueType& offValue); | ||
77 | |||
78 | /// @brief Constructs an InternalNode with dense tiles | ||
79 | /// @param origin The location in index space of the fist tile value | ||
80 | /// @param fillValue Value assigned to all the tiles | ||
81 | /// @param active State assigned to all the tiles | ||
82 | InternalNode(const Coord& origin, const ValueType& fillValue, bool active = false); | ||
83 | |||
84 | InternalNode(PartialCreate, const Coord&, const ValueType& fillValue, bool active = false); | ||
85 | |||
86 | /// @brief Deep copy constructor | ||
87 | /// | ||
88 | /// @note This method is multi-threaded! | ||
89 | InternalNode(const InternalNode&); | ||
90 | |||
91 | /// @brief Value conversion copy constructor | ||
92 | /// | ||
93 | /// @note This method is multi-threaded! | ||
94 | template<typename OtherChildNodeType> | ||
95 | explicit InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other); | ||
96 | |||
97 | /// @brief Topology copy constructor | ||
98 | /// | ||
99 | /// @note This method is multi-threaded! | ||
100 | template<typename OtherChildNodeType> | ||
101 | InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other, | ||
102 | const ValueType& background, TopologyCopy); | ||
103 | |||
104 | /// @brief Topology copy constructor | ||
105 | /// | ||
106 | /// @note This method is multi-threaded! | ||
107 | template<typename OtherChildNodeType> | ||
108 | InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other, | ||
109 | const ValueType& offValue, const ValueType& onValue, TopologyCopy); | ||
110 | |||
111 | ~InternalNode(); | ||
112 | |||
113 | protected: | ||
114 | using MaskOnIterator = typename NodeMaskType::OnIterator; | ||
115 | using MaskOffIterator = typename NodeMaskType::OffIterator; | ||
116 | using MaskDenseIterator = typename NodeMaskType::DenseIterator; | ||
117 | |||
118 | // Type tags to disambiguate template instantiations | ||
119 | struct ValueOn {}; struct ValueOff {}; struct ValueAll {}; | ||
120 | struct ChildOn {}; struct ChildOff {}; struct ChildAll {}; | ||
121 | |||
122 | // The following class templates implement the iterator interfaces specified in Iterator.h | ||
123 | // by providing getItem(), setItem() and/or modifyItem() methods. | ||
124 | |||
125 | // Sparse iterator that visits child nodes of an InternalNode | ||
126 | template<typename NodeT, typename ChildT, typename MaskIterT, typename TagT> | ||
127 | struct ChildIter: public SparseIteratorBase< | ||
128 | MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT> | ||
129 | { | ||
130 | ChildIter() {} | ||
131 | ChildIter(const MaskIterT& iter, NodeT* parent): SparseIteratorBase< | ||
132 | MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>(iter, parent) {} | ||
133 | |||
134 | 137723072 | ChildT& getItem(Index pos) const | |
135 | { | ||
136 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 68861536 times.
|
275446144 | assert(this->parent().isChildMaskOn(pos)); |
137 | 137723072 | return *(this->parent().getChildNode(pos)); | |
138 | } | ||
139 | |||
140 | // Note: setItem() can't be called on const iterators. | ||
141 | void setItem(Index pos, const ChildT& c) const { this->parent().resetChildNode(pos, &c); } | ||
142 | |||
143 | // Note: modifyItem() isn't implemented, since it's not useful for child node pointers. | ||
144 | };// ChildIter | ||
145 | |||
146 | // Sparse iterator that visits tile values of an InternalNode | ||
147 | template<typename NodeT, typename ValueT, typename MaskIterT, typename TagT> | ||
148 | struct ValueIter: public SparseIteratorBase< | ||
149 | MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT> | ||
150 | { | ||
151 | ✗ | ValueIter() {} | |
152 | ValueIter(const MaskIterT& iter, NodeT* parent): SparseIteratorBase< | ||
153 | MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>(iter, parent) {} | ||
154 | |||
155 |
9/34✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✓ Branch 81 taken 1 times.
✗ Branch 82 not taken.
✓ Branch 84 taken 1 times.
✗ Branch 85 not taken.
✓ Branch 87 taken 1 times.
✗ Branch 88 not taken.
✓ Branch 90 taken 1 times.
✗ Branch 91 not taken.
✓ Branch 93 taken 1 times.
✗ Branch 94 not taken.
✓ Branch 96 taken 1 times.
✗ Branch 97 not taken.
✓ Branch 99 taken 1 times.
✗ Branch 100 not taken.
✓ Branch 102 taken 1 times.
✗ Branch 103 not taken.
✓ Branch 105 taken 1 times.
✗ Branch 106 not taken.
|
2073830124 | const ValueT& getItem(Index pos) const { return this->parent().mNodes[pos].getValue(); } |
156 | |||
157 | // Note: setItem() can't be called on const iterators. | ||
158 |
4/15✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 23 taken 99214 times.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✓ Branch 29 taken 2174 times.
✗ Branch 30 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 35 taken 12 times.
✗ Branch 36 not taken.
|
84793180 | void setItem(Index pos, const ValueT& v) const { this->parent().mNodes[pos].setValue(v); } |
159 | |||
160 | // Note: modifyItem() can't be called on const iterators. | ||
161 | template<typename ModifyOp> | ||
162 | void modifyItem(Index pos, const ModifyOp& op) const | ||
163 | { | ||
164 | 1188 | op(this->parent().mNodes[pos].getValue()); | |
165 | } | ||
166 | };// ValueIter | ||
167 | |||
168 | // Dense iterator that visits both tiles and child nodes of an InternalNode | ||
169 | template<typename NodeT, typename ChildT, typename ValueT, typename TagT> | ||
170 | struct DenseIter: public DenseIteratorBase< | ||
171 | MaskDenseIterator, DenseIter<NodeT, ChildT, ValueT, TagT>, NodeT, ChildT, ValueT> | ||
172 | { | ||
173 | using BaseT = DenseIteratorBase<MaskDenseIterator, DenseIter, NodeT, ChildT, ValueT>; | ||
174 | using NonConstValueT = typename BaseT::NonConstValueType; | ||
175 | |||
176 | DenseIter() {} | ||
177 | DenseIter(const MaskDenseIterator& iter, NodeT* parent): | ||
178 | DenseIteratorBase<MaskDenseIterator, DenseIter, NodeT, ChildT, ValueT>(iter, parent) {} | ||
179 | |||
180 | 4743176 | bool getItem(Index pos, ChildT*& child, NonConstValueT& value) const | |
181 | { | ||
182 |
2/2✓ Branch 1 taken 555 times.
✓ Branch 2 taken 2371033 times.
|
9486352 | if (this->parent().isChildMaskOn(pos)) { |
183 | 1110 | child = this->parent().getChildNode(pos); | |
184 | 1110 | return true; | |
185 | } | ||
186 | 4742066 | child = nullptr; | |
187 | 4742066 | value = this->parent().mNodes[pos].getValue(); | |
188 | 4742066 | return false; | |
189 | } | ||
190 | |||
191 | // Note: setItem() can't be called on const iterators. | ||
192 | void setItem(Index pos, ChildT* child) const | ||
193 | { | ||
194 | this->parent().resetChildNode(pos, child); | ||
195 | } | ||
196 | |||
197 | // Note: unsetItem() can't be called on const iterators. | ||
198 | void unsetItem(Index pos, const ValueT& value) const | ||
199 | { | ||
200 | this->parent().unsetChildNode(pos, value); | ||
201 | } | ||
202 | };// DenseIter | ||
203 | |||
204 | public: | ||
205 | // Iterators (see Iterator.h for usage) | ||
206 | using ChildOnIter = ChildIter<InternalNode, ChildNodeType, MaskOnIterator, ChildOn>; | ||
207 | using ChildOnCIter = ChildIter<const InternalNode,const ChildNodeType,MaskOnIterator,ChildOn>; | ||
208 | using ChildOffIter = ValueIter<InternalNode, const ValueType, MaskOffIterator, ChildOff>; | ||
209 | using ChildOffCIter = ValueIter<const InternalNode,const ValueType,MaskOffIterator,ChildOff>; | ||
210 | using ChildAllIter = DenseIter<InternalNode, ChildNodeType, ValueType, ChildAll>; | ||
211 | using ChildAllCIter = DenseIter<const InternalNode,const ChildNodeType, ValueType, ChildAll>; | ||
212 | |||
213 | using ValueOnIter = ValueIter<InternalNode, const ValueType, MaskOnIterator, ValueOn>; | ||
214 | using ValueOnCIter = ValueIter<const InternalNode, const ValueType, MaskOnIterator, ValueOn>; | ||
215 | using ValueOffIter = ValueIter<InternalNode, const ValueType, MaskOffIterator, ValueOff>; | ||
216 | using ValueOffCIter = ValueIter<const InternalNode,const ValueType,MaskOffIterator,ValueOff>; | ||
217 | using ValueAllIter = ValueIter<InternalNode, const ValueType, MaskOffIterator, ValueAll>; | ||
218 | using ValueAllCIter = ValueIter<const InternalNode,const ValueType,MaskOffIterator,ValueAll>; | ||
219 | |||
220 |
12/24✓ Branch 110 taken 1 times.
✗ Branch 111 not taken.
✓ Branch 114 taken 1 times.
✗ Branch 115 not taken.
✓ Branch 118 taken 1 times.
✗ Branch 119 not taken.
✓ Branch 122 taken 1 times.
✗ Branch 123 not taken.
✓ Branch 126 taken 1 times.
✗ Branch 127 not taken.
✓ Branch 130 taken 1 times.
✗ Branch 131 not taken.
✓ Branch 134 taken 1 times.
✗ Branch 135 not taken.
✓ Branch 325 taken 1 times.
✗ Branch 326 not taken.
✓ Branch 329 taken 1 times.
✗ Branch 330 not taken.
✓ Branch 333 taken 1 times.
✗ Branch 334 not taken.
✓ Branch 337 taken 1 times.
✗ Branch 338 not taken.
✓ Branch 341 taken 1 times.
✗ Branch 342 not taken.
|
524713 | ChildOnCIter cbeginChildOn() const { return ChildOnCIter(mChildMask.beginOn(), this); } |
221 | 64 | ChildOffCIter cbeginChildOff() const { return ChildOffCIter(mChildMask.beginOff(), this); } | |
222 | 180 | ChildAllCIter cbeginChildAll() const { return ChildAllCIter(mChildMask.beginDense(), this); } | |
223 | 76956 | ChildOnCIter beginChildOn() const { return cbeginChildOn(); } | |
224 | ChildOffCIter beginChildOff() const { return cbeginChildOff(); } | ||
225 | 90 | ChildAllCIter beginChildAll() const { return cbeginChildAll(); } | |
226 |
1/2✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
|
817281 | ChildOnIter beginChildOn() { return ChildOnIter(mChildMask.beginOn(), this); } |
227 | ChildOffIter beginChildOff() { return ChildOffIter(mChildMask.beginOff(), this); } | ||
228 | 294 | ChildAllIter beginChildAll() { return ChildAllIter(mChildMask.beginDense(), this); } | |
229 | |||
230 |
12/138✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 12 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 14 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 6 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 8 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 6 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✓ Branch 27 taken 8 times.
✓ Branch 28 taken 5 times.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✓ Branch 31 taken 5 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✓ Branch 48 taken 3 times.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 3 times.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 108 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 137 not taken.
✗ Branch 138 not taken.
✗ Branch 140 not taken.
✗ Branch 141 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 156 not taken.
✗ Branch 157 not taken.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 164 not taken.
✗ Branch 165 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 180 not taken.
✗ Branch 181 not taken.
|
375138 | ValueOnCIter cbeginValueOn() const { return ValueOnCIter(mValueMask.beginOn(), this); } |
231 | /// @warning This iterator will also visit child nodes so use isChildMaskOn to skip them! | ||
232 | 1088 | ValueOffCIter cbeginValueOff() const { return ValueOffCIter(mValueMask.beginOff(), this); } | |
233 |
13/26✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
✗ Branch 29 not taken.
✓ Branch 30 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 1 times.
✓ Branch 36 taken 1 times.
✗ Branch 37 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 44 taken 1 times.
✗ Branch 45 not taken.
✗ Branch 47 not taken.
✓ Branch 48 taken 1 times.
✗ Branch 50 not taken.
✓ Branch 51 taken 1 times.
✓ Branch 54 taken 1 times.
✗ Branch 55 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✓ Branch 62 taken 1 times.
✗ Branch 63 not taken.
|
1872 | ValueAllCIter cbeginValueAll() const { return ValueAllCIter(mChildMask.beginOff(), this); } |
234 | ValueOnCIter beginValueOn() const { return cbeginValueOn(); } | ||
235 | /// @warning This iterator will also visit child nodes so use isChildMaskOn to skip them! | ||
236 | ValueOffCIter beginValueOff() const { return cbeginValueOff(); } | ||
237 | 182 | ValueAllCIter beginValueAll() const { return cbeginValueAll(); } | |
238 |
40/80✗ Branch 4 not taken.
✓ Branch 5 taken 102 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 68 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 156 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 104 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 171 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 114 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 150 times.
✗ Branch 31 not taken.
✓ Branch 32 taken 100 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 153 times.
✗ Branch 39 not taken.
✓ Branch 40 taken 102 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 162 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 108 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 165 times.
✗ Branch 55 not taken.
✓ Branch 56 taken 110 times.
✗ Branch 60 not taken.
✓ Branch 61 taken 174 times.
✗ Branch 63 not taken.
✓ Branch 64 taken 116 times.
✗ Branch 68 not taken.
✓ Branch 69 taken 186 times.
✗ Branch 71 not taken.
✓ Branch 72 taken 124 times.
✗ Branch 76 not taken.
✓ Branch 77 taken 306 times.
✗ Branch 79 not taken.
✓ Branch 80 taken 204 times.
✗ Branch 84 not taken.
✓ Branch 85 taken 357 times.
✗ Branch 87 not taken.
✓ Branch 88 taken 238 times.
✗ Branch 92 not taken.
✓ Branch 93 taken 105 times.
✗ Branch 95 not taken.
✓ Branch 96 taken 70 times.
✗ Branch 100 not taken.
✓ Branch 101 taken 105 times.
✗ Branch 103 not taken.
✓ Branch 104 taken 70 times.
✗ Branch 108 not taken.
✓ Branch 109 taken 105 times.
✗ Branch 111 not taken.
✓ Branch 112 taken 70 times.
✗ Branch 116 not taken.
✓ Branch 117 taken 1302 times.
✗ Branch 119 not taken.
✓ Branch 120 taken 868 times.
✗ Branch 124 not taken.
✓ Branch 125 taken 78 times.
✗ Branch 127 not taken.
✓ Branch 128 taken 52 times.
✗ Branch 132 not taken.
✓ Branch 133 taken 765 times.
✗ Branch 135 not taken.
✓ Branch 136 taken 510 times.
✗ Branch 140 not taken.
✓ Branch 141 taken 231 times.
✗ Branch 143 not taken.
✓ Branch 144 taken 154 times.
✗ Branch 148 not taken.
✓ Branch 149 taken 757 times.
✗ Branch 151 not taken.
✓ Branch 152 taken 510 times.
✗ Branch 155 not taken.
✓ Branch 156 taken 1092 times.
✗ Branch 158 not taken.
✓ Branch 159 taken 728 times.
|
56615 | ValueOnIter beginValueOn() { return ValueOnIter(mValueMask.beginOn(), this); } |
239 | /// @warning This iterator will also visit child nodes so use isChildMaskOn to skip them! | ||
240 |
4/160✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 154 not taken.
✗ Branch 155 not taken.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
✗ Branch 160 not taken.
✗ Branch 161 not taken.
✗ Branch 163 not taken.
✗ Branch 164 not taken.
✗ Branch 166 not taken.
✗ Branch 167 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✗ Branch 175 not taken.
✗ Branch 176 not taken.
✗ Branch 178 not taken.
✗ Branch 179 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 184 not taken.
✗ Branch 185 not taken.
✗ Branch 187 not taken.
✗ Branch 188 not taken.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 196 not taken.
✗ Branch 197 not taken.
✗ Branch 199 not taken.
✗ Branch 200 not taken.
✗ Branch 202 not taken.
✗ Branch 203 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 208 not taken.
✗ Branch 209 not taken.
✗ Branch 211 not taken.
✗ Branch 212 not taken.
✗ Branch 214 not taken.
✗ Branch 215 not taken.
✗ Branch 217 not taken.
✓ Branch 218 taken 1 times.
✗ Branch 220 not taken.
✓ Branch 221 taken 1 times.
✗ Branch 223 not taken.
✓ Branch 224 taken 1 times.
✗ Branch 226 not taken.
✓ Branch 227 taken 1 times.
✗ Branch 229 not taken.
✗ Branch 230 not taken.
✗ Branch 232 not taken.
✗ Branch 233 not taken.
✗ Branch 235 not taken.
✗ Branch 236 not taken.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
|
931 | ValueOffIter beginValueOff() { return ValueOffIter(mValueMask.beginOff(), this); } |
241 |
0/80✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 108 not taken.
✗ Branch 109 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 123 not taken.
✗ Branch 124 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✗ Branch 141 not taken.
✗ Branch 142 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✗ Branch 147 not taken.
✗ Branch 148 not taken.
✗ Branch 150 not taken.
✗ Branch 151 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 156 not taken.
✗ Branch 157 not taken.
✗ Branch 159 not taken.
✗ Branch 160 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 168 not taken.
✗ Branch 169 not taken.
✗ Branch 171 not taken.
✗ Branch 172 not taken.
✗ Branch 174 not taken.
✗ Branch 175 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 180 not taken.
✗ Branch 181 not taken.
✗ Branch 183 not taken.
✗ Branch 184 not taken.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 192 not taken.
✗ Branch 193 not taken.
✗ Branch 195 not taken.
✗ Branch 196 not taken.
✗ Branch 198 not taken.
✗ Branch 199 not taken.
|
12248 | ValueAllIter beginValueAll() { return ValueAllIter(mChildMask.beginOff(), this); } |
242 | |||
243 | |||
244 | /// @return The dimension of this InternalNode | ||
245 | /// @details The number of voxels in one coordinate direction covered by this node | ||
246 | static Index dim() { return DIM; } | ||
247 | /// @return The level of this node | ||
248 | /// @details Level 0 is by definition the level of the leaf nodes | ||
249 | static Index getLevel() { return LEVEL; } | ||
250 | /// @brief Populated an std::vector with the dimension of all the | ||
251 | /// nodes in the branch starting with this node. | ||
252 | static void getNodeLog2Dims(std::vector<Index>& dims); | ||
253 | /// @return The dimension of the child nodes of this node. | ||
254 | /// @details The number of voxels in one coordinate direction | ||
255 | /// covered by a child node of this node. | ||
256 | static Index getChildDim() { return ChildNodeType::DIM; } | ||
257 | |||
258 | /// Return the linear table offset of the given global or local coordinates. | ||
259 | static Index coordToOffset(const Coord& xyz); | ||
260 | /// @brief Return the local coordinates for a linear table offset, | ||
261 | /// where offset 0 has coordinates (0, 0, 0). | ||
262 | static void offsetToLocalCoord(Index n, Coord& xyz); | ||
263 | /// Return the global coordinates for a linear table offset. | ||
264 | Coord offsetToGlobalCoord(Index n) const; | ||
265 | |||
266 | /// Return the grid index coordinates of this node's local origin. | ||
267 |
2/4✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
5637 | const Coord& origin() const { return mOrigin; } |
268 | /// Set the grid index coordinates of this node's local origin. | ||
269 |
1/18✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 19 taken 8 times.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
|
8 | void setOrigin(const Coord& origin) { mOrigin = origin; } |
270 | |||
271 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
272 | /// Return the transient data value. | ||
273 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
|
3 | Index32 transientData() const { return mTransientData; } |
274 | /// Set the transient data value. | ||
275 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | void setTransientData(Index32 transientData) { mTransientData = transientData; } |
276 | #endif | ||
277 | |||
278 | Index32 leafCount() const; | ||
279 | void nodeCount(std::vector<Index32> &vec) const; | ||
280 | Index32 nonLeafCount() const; | ||
281 | Index32 childCount() const; | ||
282 | Index64 onVoxelCount() const; | ||
283 | Index64 offVoxelCount() const; | ||
284 | Index64 onLeafVoxelCount() const; | ||
285 | Index64 offLeafVoxelCount() const; | ||
286 | Index64 onTileCount() const; | ||
287 | |||
288 | /// Return the total amount of memory in bytes occupied by this node and its children. | ||
289 | Index64 memUsage() const; | ||
290 | |||
291 | /// @brief Expand the specified bounding box so that it includes the active tiles | ||
292 | /// of this internal node as well as all the active values in its child nodes. | ||
293 | /// If visitVoxels is false LeafNodes will be approximated as dense, i.e. with all | ||
294 | /// voxels active. Else the individual active voxels are visited to produce a tight bbox. | ||
295 | void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const; | ||
296 | |||
297 | /// @brief Return the bounding box of this node, i.e., the full index space | ||
298 | /// spanned by the node regardless of its content. | ||
299 | 43662 | CoordBBox getNodeBoundingBox() const { return CoordBBox::createCube(mOrigin, DIM); } | |
300 | |||
301 | /// @return True if this node contains no child nodes. | ||
302 | bool isEmpty() const { return mChildMask.isOff(); } | ||
303 | |||
304 | /// Return @c true if all of this node's table entries have the same active state | ||
305 | /// and the same constant value to within the given tolerance, | ||
306 | /// and return that value in @a firstValue and the active state in @a state. | ||
307 | /// | ||
308 | /// @note This method also returns @c false if this node contains any child nodes. | ||
309 | bool isConstant(ValueType& firstValue, bool& state, | ||
310 |
13/52✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 10 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 16 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 9 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 9 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✓ Branch 27 taken 9 times.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✓ Branch 31 taken 9 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 9 times.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✓ Branch 39 taken 9 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✓ Branch 43 taken 12 times.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✓ Branch 47 taken 12 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 12 times.
|
136 | const ValueType& tolerance = zeroVal<ValueType>()) const; |
311 | |||
312 | /// Return @c true if all of this node's tables entries have | ||
313 | /// the same active @a state and the range of its values satisfy | ||
314 | /// (@a maxValue - @a minValue) <= @a tolerance. | ||
315 | /// | ||
316 | /// @param minValue Is updated with the minimum of all values IF method | ||
317 | /// returns @c true. Else the value is undefined! | ||
318 | /// @param maxValue Is updated with the maximum of all values IF method | ||
319 | /// returns @c true. Else the value is undefined! | ||
320 | /// @param state Is updated with the state of all values IF method | ||
321 | /// returns @c true. Else the value is undefined! | ||
322 | /// @param tolerance The tolerance used to determine if values are | ||
323 | /// approximately constant. | ||
324 | /// | ||
325 | /// @note This method also returns @c false if this node contains any child nodes. | ||
326 | bool isConstant(ValueType& minValue, ValueType& maxValue, | ||
327 | bool& state, const ValueType& tolerance = zeroVal<ValueType>()) const; | ||
328 | |||
329 | /// Return @c true if this node has no children and only contains inactive values. | ||
330 |
7/8✓ Branch 0 taken 2942 times.
✓ Branch 1 taken 12468 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 2931 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 23 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
|
67483 | bool isInactive() const { return this->isChildMaskOff() && this->isValueMaskOff(); } |
331 | |||
332 | /// Return @c true if the voxel at the given coordinates is active. | ||
333 | bool isValueOn(const Coord& xyz) const; | ||
334 | /// Return @c true if the voxel at the given offset is active. | ||
335 | 19 | bool isValueOn(Index offset) const { return mValueMask.isOn(offset); } | |
336 | |||
337 | /// Return @c true if this node or any of its child nodes have any active tiles. | ||
338 | bool hasActiveTiles() const; | ||
339 | |||
340 | const ValueType& getValue(const Coord& xyz) const; | ||
341 | bool probeValue(const Coord& xyz, ValueType& value) const; | ||
342 | |||
343 | /// @brief Return the level of the tree (0 = leaf) at which the value | ||
344 | /// at the given coordinates resides. | ||
345 | Index getValueLevel(const Coord& xyz) const; | ||
346 | |||
347 | /// @brief If the first entry in this node's table is a tile, return the tile's value. | ||
348 | /// Otherwise, return the result of calling getFirstValue() on the child. | ||
349 | const ValueType& getFirstValue() const; | ||
350 | /// @brief If the last entry in this node's table is a tile, return the tile's value. | ||
351 | /// Otherwise, return the result of calling getLastValue() on the child. | ||
352 | const ValueType& getLastValue() const; | ||
353 | |||
354 | /// Set the active state of the voxel at the given coordinates but don't change its value. | ||
355 | void setActiveState(const Coord& xyz, bool on); | ||
356 | /// Set the value of the voxel at the given coordinates but don't change its active state. | ||
357 | void setValueOnly(const Coord& xyz, const ValueType& value); | ||
358 | /// Mark the voxel at the given coordinates as active but don't change its value. | ||
359 | void setValueOn(const Coord& xyz); | ||
360 | /// Set the value of the voxel at the given coordinates and mark the voxel as active. | ||
361 | void setValueOn(const Coord& xyz, const ValueType& value); | ||
362 | /// Mark the voxel at the given coordinates as inactive but don't change its value. | ||
363 | void setValueOff(const Coord& xyz); | ||
364 | /// Set the value of the voxel at the given coordinates and mark the voxel as inactive. | ||
365 | void setValueOff(const Coord& xyz, const ValueType& value); | ||
366 | |||
367 | /// @brief Apply a functor to the value of the voxel at the given coordinates | ||
368 | /// and mark the voxel as active. | ||
369 | template<typename ModifyOp> | ||
370 | void modifyValue(const Coord& xyz, const ModifyOp& op); | ||
371 | /// Apply a functor to the voxel at the given coordinates. | ||
372 | template<typename ModifyOp> | ||
373 | void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op); | ||
374 | |||
375 | /// Return the value of the voxel at the given coordinates and, if necessary, update | ||
376 | /// the accessor with pointers to the nodes along the path from the root node to | ||
377 | /// the node containing the voxel. | ||
378 | /// @note Used internally by ValueAccessor. | ||
379 | template<typename AccessorT> | ||
380 | const ValueType& getValueAndCache(const Coord& xyz, AccessorT&) const; | ||
381 | |||
382 | /// Return @c true if the voxel at the given coordinates is active and, if necessary, | ||
383 | /// update the accessor with pointers to the nodes along the path from the root node | ||
384 | /// to the node containing the voxel. | ||
385 | /// @note Used internally by ValueAccessor. | ||
386 | template<typename AccessorT> | ||
387 | bool isValueOnAndCache(const Coord& xyz, AccessorT&) const; | ||
388 | |||
389 | /// Change the value of the voxel at the given coordinates and mark it as active. | ||
390 | /// If necessary, update the accessor with pointers to the nodes along the path | ||
391 | /// from the root node to the node containing the voxel. | ||
392 | /// @note Used internally by ValueAccessor. | ||
393 | template<typename AccessorT> | ||
394 | void setValueAndCache(const Coord& xyz, const ValueType& value, AccessorT&); | ||
395 | |||
396 | /// Set the value of the voxel at the given coordinate but preserves its active state. | ||
397 | /// If necessary, update the accessor with pointers to the nodes along the path | ||
398 | /// from the root node to the node containing the voxel. | ||
399 | /// @note Used internally by ValueAccessor. | ||
400 | template<typename AccessorT> | ||
401 | void setValueOnlyAndCache(const Coord& xyz, const ValueType& value, AccessorT&); | ||
402 | |||
403 | /// @brief Apply a functor to the value of the voxel at the given coordinates | ||
404 | /// and mark the voxel as active. | ||
405 | /// If necessary, update the accessor with pointers to the nodes along the path | ||
406 | /// from the root node to the node containing the voxel. | ||
407 | /// @note Used internally by ValueAccessor. | ||
408 | template<typename ModifyOp, typename AccessorT> | ||
409 | void modifyValueAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&); | ||
410 | |||
411 | /// Apply a functor to the voxel at the given coordinates. | ||
412 | /// If necessary, update the accessor with pointers to the nodes along the path | ||
413 | /// from the root node to the node containing the voxel. | ||
414 | /// @note Used internally by ValueAccessor. | ||
415 | template<typename ModifyOp, typename AccessorT> | ||
416 | void modifyValueAndActiveStateAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&); | ||
417 | |||
418 | /// Change the value of the voxel at the given coordinates and mark it as inactive. | ||
419 | /// If necessary, update the accessor with pointers to the nodes along the path | ||
420 | /// from the root node to the node containing the voxel. | ||
421 | /// @note Used internally by ValueAccessor. | ||
422 | template<typename AccessorT> | ||
423 | void setValueOffAndCache(const Coord& xyz, const ValueType& value, AccessorT&); | ||
424 | |||
425 | /// Set the active state of the voxel at the given coordinates without changing its value. | ||
426 | /// If necessary, update the accessor with pointers to the nodes along the path | ||
427 | /// from the root node to the node containing the voxel. | ||
428 | /// @note Used internally by ValueAccessor. | ||
429 | template<typename AccessorT> | ||
430 | void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT&); | ||
431 | |||
432 | /// Return, in @a value, the value of the voxel at the given coordinates and, | ||
433 | /// if necessary, update the accessor with pointers to the nodes along | ||
434 | /// the path from the root node to the node containing the voxel. | ||
435 | /// @return @c true if the voxel at the given coordinates is active | ||
436 | /// @note Used internally by ValueAccessor. | ||
437 | template<typename AccessorT> | ||
438 | bool probeValueAndCache(const Coord& xyz, ValueType& value, AccessorT&) const; | ||
439 | |||
440 | /// @brief Return the level of the tree (0 = leaf) at which the value | ||
441 | /// at the given coordinates resides. | ||
442 | /// | ||
443 | /// If necessary, update the accessor with pointers to the nodes along the path | ||
444 | /// from the root node to the node containing the voxel. | ||
445 | /// @note Used internally by ValueAccessor. | ||
446 | template<typename AccessorT> | ||
447 | Index getValueLevelAndCache(const Coord& xyz, AccessorT&) const; | ||
448 | |||
449 | /// Mark all values (both tiles and voxels) as active. | ||
450 | void setValuesOn(); | ||
451 | |||
452 | // | ||
453 | // I/O | ||
454 | // | ||
455 | void writeTopology(std::ostream&, bool toHalf = false) const; | ||
456 | void readTopology(std::istream&, bool fromHalf = false); | ||
457 | void writeBuffers(std::ostream&, bool toHalf = false) const; | ||
458 | void readBuffers(std::istream&, bool fromHalf = false); | ||
459 | void readBuffers(std::istream&, const CoordBBox&, bool fromHalf = false); | ||
460 | |||
461 | |||
462 | // | ||
463 | // Aux methods | ||
464 | // | ||
465 | |||
466 | /// Change the sign of all the values represented in this node and its child nodes. | ||
467 | void negate(); | ||
468 | |||
469 | /// @brief Set all voxels within a given axis-aligned box to a constant value. | ||
470 | /// @param bbox inclusive coordinates of opposite corners of an axis-aligned box | ||
471 | /// @param value the value to which to set voxels within the box | ||
472 | /// @param active if true, mark voxels within the box as active, | ||
473 | /// otherwise mark them as inactive | ||
474 | /// @note This operation generates a sparse, but not always optimally sparse, | ||
475 | /// representation of the filled box. Follow fill operations with a prune() | ||
476 | /// operation for optimal sparseness. | ||
477 | void fill(const CoordBBox& bbox, const ValueType& value, bool active = true); | ||
478 | |||
479 | /// @brief Set all voxels within a given axis-aligned box to a constant value | ||
480 | /// and ensure that those voxels are all represented at the leaf level. | ||
481 | /// @param bbox inclusive coordinates of opposite corners of an axis-aligned box. | ||
482 | /// @param value the value to which to set voxels within the box. | ||
483 | /// @param active if true, mark voxels within the box as active, | ||
484 | /// otherwise mark them as inactive. | ||
485 | /// @sa voxelizeActiveTiles() | ||
486 | void denseFill(const CoordBBox& bbox, const ValueType& value, bool active = true); | ||
487 | |||
488 | /// @brief Densify active tiles, i.e., replace them with leaf-level active voxels. | ||
489 | /// @param threaded if true, this operation is multi-threaded (over the internal nodes). | ||
490 | /// @sa denseFill() | ||
491 | void voxelizeActiveTiles(bool threaded = true); | ||
492 | |||
493 | /// @brief Copy into a dense grid the values of the voxels that lie within | ||
494 | /// a given bounding box. | ||
495 | /// @param bbox inclusive bounding box of the voxels to be copied into the dense grid | ||
496 | /// @param dense dense grid with a stride in @e z of one (see tools::Dense | ||
497 | /// in tools/Dense.h for the required API) | ||
498 | /// @note @a bbox is assumed to be identical to or contained in the coordinate domains | ||
499 | /// of both the dense grid and this node, i.e., no bounds checking is performed. | ||
500 | template<typename DenseT> | ||
501 | void copyToDense(const CoordBBox& bbox, DenseT& dense) const; | ||
502 | |||
503 | /// @brief Efficiently merge another tree into this tree using one of several schemes. | ||
504 | /// @warning This operation cannibalizes the other tree. | ||
505 | template<MergePolicy Policy> | ||
506 | void merge(InternalNode& other, const ValueType& background, const ValueType& otherBackground); | ||
507 | |||
508 | /// @brief Merge, using one of several schemes, this node (and its descendants) | ||
509 | /// with a tile of the same dimensions and the given value and active state. | ||
510 | template<MergePolicy Policy> void merge(const ValueType& tileValue, bool tileActive); | ||
511 | |||
512 | /// @brief Union this branch's set of active values with the other branch's | ||
513 | /// active values. The value type of the other branch can be different. | ||
514 | /// @details The resulting state of a value is active if the corresponding value | ||
515 | /// was already active OR if it is active in the other tree. Also, a resulting | ||
516 | /// value maps to a voxel if the corresponding value already mapped to a voxel | ||
517 | /// OR if it is a voxel in the other tree. Thus, a resulting value can only | ||
518 | /// map to a tile if the corresponding value already mapped to a tile | ||
519 | /// AND if it is a tile value in other tree. | ||
520 | /// | ||
521 | /// Specifically, active tiles and voxels in this branch are not changed, and | ||
522 | /// tiles or voxels that were inactive in this branch but active in the other branch | ||
523 | /// are marked as active in this branch but left with their original values. | ||
524 | template<typename OtherChildNodeType> | ||
525 | void topologyUnion(const InternalNode<OtherChildNodeType, Log2Dim>& other, const bool preserveTiles = false); | ||
526 | |||
527 | /// @brief Intersects this tree's set of active values with the active values | ||
528 | /// of the other tree, whose @c ValueType may be different. | ||
529 | /// @details The resulting state of a value is active only if the corresponding | ||
530 | /// value was already active AND if it is active in the other tree. Also, a | ||
531 | /// resulting value maps to a voxel if the corresponding value | ||
532 | /// already mapped to an active voxel in either of the two grids | ||
533 | /// and it maps to an active tile or voxel in the other grid. | ||
534 | /// | ||
535 | /// @note This operation can delete branches in this grid if they | ||
536 | /// overlap with inactive tiles in the other grid. Likewise active | ||
537 | /// voxels can be turned into inactive voxels resulting in leaf | ||
538 | /// nodes with no active values. Thus, it is recommended to | ||
539 | /// subsequently call prune. | ||
540 | template<typename OtherChildNodeType> | ||
541 | void topologyIntersection(const InternalNode<OtherChildNodeType, Log2Dim>& other, | ||
542 | const ValueType& background); | ||
543 | |||
544 | /// @brief Difference this node's set of active values with the active values | ||
545 | /// of the other node, whose @c ValueType may be different. So a | ||
546 | /// resulting voxel will be active only if the original voxel is | ||
547 | /// active in this node and inactive in the other node. | ||
548 | /// | ||
549 | /// @details The last dummy argument is required to match the signature | ||
550 | /// for InternalNode::topologyDifference. | ||
551 | /// | ||
552 | /// @note This operation modifies only active states, not | ||
553 | /// values. Also note that this operation can result in all voxels | ||
554 | /// being inactive so consider subsequently calling prune. | ||
555 | template<typename OtherChildNodeType> | ||
556 | void topologyDifference(const InternalNode<OtherChildNodeType, Log2Dim>& other, | ||
557 | const ValueType& background); | ||
558 | |||
559 | template<typename CombineOp> | ||
560 | void combine(InternalNode& other, CombineOp&); | ||
561 | template<typename CombineOp> | ||
562 | void combine(const ValueType& value, bool valueIsActive, CombineOp&); | ||
563 | |||
564 | template<typename CombineOp, typename OtherNodeType /*= InternalNode*/> | ||
565 | void combine2(const InternalNode& other0, const OtherNodeType& other1, CombineOp&); | ||
566 | template<typename CombineOp, typename OtherNodeType /*= InternalNode*/> | ||
567 | void combine2(const ValueType& value, const OtherNodeType& other, bool valIsActive, CombineOp&); | ||
568 | template<typename CombineOp, typename OtherValueType> | ||
569 | void combine2(const InternalNode& other, const OtherValueType&, bool valIsActive, CombineOp&); | ||
570 | |||
571 | /// @brief Calls the templated functor BBoxOp with bounding box | ||
572 | /// information for all active tiles and leaf nodes in this node. | ||
573 | /// An additional level argument is provided for each callback. | ||
574 | /// | ||
575 | /// @note The bounding boxes are guaranteed to be non-overlapping. | ||
576 | template<typename BBoxOp> void visitActiveBBox(BBoxOp&) const; | ||
577 | |||
578 | template<typename VisitorOp> void visit(VisitorOp&); | ||
579 | template<typename VisitorOp> void visit(VisitorOp&) const; | ||
580 | |||
581 | template<typename OtherNodeType, typename VisitorOp> | ||
582 | void visit2Node(OtherNodeType& other, VisitorOp&); | ||
583 | template<typename OtherNodeType, typename VisitorOp> | ||
584 | void visit2Node(OtherNodeType& other, VisitorOp&) const; | ||
585 | template<typename IterT, typename VisitorOp> | ||
586 | void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false); | ||
587 | template<typename IterT, typename VisitorOp> | ||
588 | void visit2(IterT& otherIter, VisitorOp&, bool otherIsLHS = false) const; | ||
589 | |||
590 | /// Set all voxels that lie outside the given axis-aligned box to the background. | ||
591 | void clip(const CoordBBox&, const ValueType& background); | ||
592 | |||
593 | /// @brief Reduce the memory footprint of this tree by replacing with tiles | ||
594 | /// any nodes whose values are all the same (optionally to within a tolerance) | ||
595 | /// and have the same active state. | ||
596 | ✗ | void prune(const ValueType& tolerance = zeroVal<ValueType>()); | |
597 | |||
598 | /// @brief Add the specified leaf to this node, possibly creating a child branch | ||
599 | /// in the process. If the leaf node already exists, replace it. | ||
600 | void addLeaf(LeafNodeType* leaf); | ||
601 | |||
602 | /// @brief Same as addLeaf() except, if necessary, update the accessor with pointers | ||
603 | /// to the nodes along the path from the root node to the node containing the coordinate. | ||
604 | template<typename AccessorT> | ||
605 | void addLeafAndCache(LeafNodeType* leaf, AccessorT&); | ||
606 | |||
607 | /// @brief Return a pointer to the node of type @c NodeT that contains voxel (x, y, z) | ||
608 | /// and replace it with a tile of the specified value and state. | ||
609 | /// If no such node exists, leave the tree unchanged and return @c nullptr. | ||
610 | /// | ||
611 | /// @note The caller takes ownership of the node and is responsible for deleting it. | ||
612 | /// | ||
613 | /// @warning Since this method potentially removes nodes and branches of the tree, | ||
614 | /// it is important to clear the caches of all ValueAccessors associated with this tree. | ||
615 | template<typename NodeT> | ||
616 | NodeT* stealNode(const Coord& xyz, const ValueType& value, bool state); | ||
617 | |||
618 | /// @brief Add the given child node at this level deducing the offset from it's origin. | ||
619 | /// If a child node with this offset already exists, delete the old node and add the | ||
620 | /// new node in its place (i.e. ownership of the new child node is transferred to | ||
621 | /// this InternalNode) | ||
622 | /// @return @c true if inserting the child has been successful, otherwise the caller | ||
623 | /// retains ownership of the node and is responsible for deleting it. | ||
624 | bool addChild(ChildNodeType* child); | ||
625 | |||
626 | /// @brief Add a tile at the specified tree level that contains voxel (x, y, z), | ||
627 | /// possibly creating a parent branch or deleting a child branch in the process. | ||
628 | void addTile(Index level, const Coord& xyz, const ValueType& value, bool state); | ||
629 | |||
630 | /// @brief Delete any existing child branch at the specified offset and add a tile. | ||
631 | void addTile(Index offset, const ValueType& value, bool state); | ||
632 | |||
633 | /// @brief Same as addTile() except, if necessary, update the accessor with pointers | ||
634 | /// to the nodes along the path from the root node to the node containing (x, y, z). | ||
635 | template<typename AccessorT> | ||
636 | void addTileAndCache(Index level, const Coord& xyz, const ValueType&, bool state, AccessorT&); | ||
637 | |||
638 | //@{ | ||
639 | /// @brief Return a pointer to the node that contains voxel (x, y, z). | ||
640 | /// If no such node exists, return nullptr. | ||
641 | template<typename NodeType> NodeType* probeNode(const Coord& xyz); | ||
642 | template<typename NodeType> const NodeType* probeConstNode(const Coord& xyz) const; | ||
643 | //@} | ||
644 | |||
645 | //@{ | ||
646 | /// @brief Same as probeNode() except, if necessary, update the accessor with pointers | ||
647 | /// to the nodes along the path from the root node to the node containing (x, y, z). | ||
648 | template<typename NodeType, typename AccessorT> | ||
649 | NodeType* probeNodeAndCache(const Coord& xyz, AccessorT&); | ||
650 | template<typename NodeType, typename AccessorT> | ||
651 | const NodeType* probeConstNodeAndCache(const Coord& xyz, AccessorT&) const; | ||
652 | //@} | ||
653 | |||
654 | //@{ | ||
655 | /// @brief Return a pointer to the leaf node that contains voxel (x, y, z). | ||
656 | /// If no such node exists, return @c nullptr. | ||
657 | LeafNodeType* probeLeaf(const Coord& xyz); | ||
658 | const LeafNodeType* probeConstLeaf(const Coord& xyz) const; | ||
659 | const LeafNodeType* probeLeaf(const Coord& xyz) const; | ||
660 | //@} | ||
661 | |||
662 | //@{ | ||
663 | /// @brief Same as probeLeaf() except, if necessary, update the accessor with pointers | ||
664 | /// to the nodes along the path from the root node to the node containing (x, y, z). | ||
665 | template<typename AccessorT> | ||
666 | LeafNodeType* probeLeafAndCache(const Coord& xyz, AccessorT& acc); | ||
667 | template<typename AccessorT> | ||
668 | const LeafNodeType* probeConstLeafAndCache(const Coord& xyz, AccessorT& acc) const; | ||
669 | template<typename AccessorT> | ||
670 | const LeafNodeType* probeLeafAndCache(const Coord& xyz, AccessorT& acc) const; | ||
671 | //@} | ||
672 | |||
673 | /// @brief Return the leaf node that contains voxel (x, y, z). | ||
674 | /// If no such node exists, create one, but preserve the values and | ||
675 | /// active states of all voxels. | ||
676 | /// | ||
677 | /// @details Use this method to preallocate a static tree topology | ||
678 | /// over which to safely perform multithreaded processing. | ||
679 | LeafNodeType* touchLeaf(const Coord& xyz); | ||
680 | |||
681 | /// @brief Same as touchLeaf() except, if necessary, update the accessor with pointers | ||
682 | /// to the nodes along the path from the root node to the node containing the coordinate. | ||
683 | template<typename AccessorT> | ||
684 | LeafNodeType* touchLeafAndCache(const Coord& xyz, AccessorT&); | ||
685 | |||
686 | //@{ | ||
687 | /// @brief Adds all nodes of a certain type to a container with the following API: | ||
688 | /// @code | ||
689 | /// struct ArrayT { | ||
690 | /// using value_type = ...;// defines the type of nodes to be added to the array | ||
691 | /// void push_back(value_type nodePtr);// method that add nodes to the array | ||
692 | /// }; | ||
693 | /// @endcode | ||
694 | /// @details An example of a wrapper around a c-style array is: | ||
695 | /// @code | ||
696 | /// struct MyArray { | ||
697 | /// using value_type = LeafType*; | ||
698 | /// value_type* ptr; | ||
699 | /// MyArray(value_type* array) : ptr(array) {} | ||
700 | /// void push_back(value_type leaf) { *ptr++ = leaf; } | ||
701 | ///}; | ||
702 | /// @endcode | ||
703 | /// @details An example that constructs a list of pointer to all leaf nodes is: | ||
704 | /// @code | ||
705 | /// std::vector<const LeafNodeType*> array;//most std contains have the required API | ||
706 | /// array.reserve(tree.leafCount());//this is a fast preallocation. | ||
707 | /// tree.getNodes(array); | ||
708 | /// @endcode | ||
709 | template<typename ArrayT> | ||
710 | void getNodes(ArrayT& array); | ||
711 | template<typename ArrayT> | ||
712 | void getNodes(ArrayT& array) const; | ||
713 | //@} | ||
714 | |||
715 | /// @brief Steals all nodes of a certain type from the tree and | ||
716 | /// adds them to a container with the following API: | ||
717 | /// @code | ||
718 | /// struct ArrayT { | ||
719 | /// using value_type = ...;// defines the type of nodes to be added to the array | ||
720 | /// void push_back(value_type nodePtr);// method that add nodes to the array | ||
721 | /// }; | ||
722 | /// @endcode | ||
723 | /// @details An example of a wrapper around a c-style array is: | ||
724 | /// @code | ||
725 | /// struct MyArray { | ||
726 | /// using value_type = LeafType*; | ||
727 | /// value_type* ptr; | ||
728 | /// MyArray(value_type* array) : ptr(array) {} | ||
729 | /// void push_back(value_type leaf) { *ptr++ = leaf; } | ||
730 | ///}; | ||
731 | /// @endcode | ||
732 | /// @details An example that constructs a list of pointer to all leaf nodes is: | ||
733 | /// @code | ||
734 | /// std::vector<const LeafNodeType*> array;//most std contains have the required API | ||
735 | /// array.reserve(tree.leafCount());//this is a fast preallocation. | ||
736 | /// tree.stealNodes(array); | ||
737 | /// @endcode | ||
738 | template<typename ArrayT> | ||
739 | void stealNodes(ArrayT& array, const ValueType& value, bool state); | ||
740 | |||
741 | /// @brief Change inactive tiles or voxels with value oldBackground to newBackground | ||
742 | /// or -oldBackground to -newBackground. Active values are unchanged. | ||
743 | void resetBackground(const ValueType& oldBackground, const ValueType& newBackground); | ||
744 | |||
745 | /// @brief Return @c true if the given tree branch has the same node and active value | ||
746 | /// topology as this tree branch (but possibly a different @c ValueType). | ||
747 | template<typename OtherChildNodeType, Index OtherLog2Dim> | ||
748 | bool hasSameTopology(const InternalNode<OtherChildNodeType, OtherLog2Dim>* other) const; | ||
749 | |||
750 | protected: | ||
751 | //@{ | ||
752 | /// Allow iterators to call mask accessor methods (setValueMask(), setChildMask(), etc.). | ||
753 | /// @todo Make mask accessors public? | ||
754 | friend class IteratorBase<MaskOnIterator, InternalNode>; | ||
755 | friend class IteratorBase<MaskOffIterator, InternalNode>; | ||
756 | friend class IteratorBase<MaskDenseIterator, InternalNode>; | ||
757 | //@} | ||
758 | |||
759 | /// @brief During topology-only construction, access is needed | ||
760 | /// to protected/private members of other template instances. | ||
761 | template<typename, Index> friend class InternalNode; | ||
762 | |||
763 | // Mask accessors | ||
764 | public: | ||
765 | 497658246 | bool isValueMaskOn(Index n) const { return mValueMask.isOn(n); } | |
766 | bool isValueMaskOn() const { return mValueMask.isOn(); } | ||
767 | 462844 | bool isValueMaskOff(Index n) const { return mValueMask.isOff(n); } | |
768 | bool isValueMaskOff() const { return mValueMask.isOff(); } | ||
769 | 4492402214 | bool isChildMaskOn(Index n) const { return mChildMask.isOn(n); } | |
770 | 6348730 | bool isChildMaskOff(Index n) const { return mChildMask.isOff(n); } | |
771 | bool isChildMaskOff() const { return mChildMask.isOff(); } | ||
772 | 4265256 | const NodeMaskType& getValueMask() const { return mValueMask; } | |
773 | 178580 | const NodeMaskType& getChildMask() const { return mChildMask; } | |
774 | 4 | NodeMaskType getValueOffMask() const | |
775 | { | ||
776 | NodeMaskType mask = mValueMask; | ||
777 | mask |= mChildMask; | ||
778 | mask.toggle(); | ||
779 | 4 | return mask; | |
780 | } | ||
781 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
4268657 | const UnionType* getTable() const { return mNodes; } |
782 | protected: | ||
783 | //@{ | ||
784 | /// Use a mask accessor to ensure consistency between the child and value masks; | ||
785 | /// i.e., the value mask should always be off wherever the child mask is on. | ||
786 |
1/2✓ Branch 1 taken 351119 times.
✗ Branch 2 not taken.
|
702238 | void setValueMask(Index n, bool on) { mValueMask.set(n, mChildMask.isOn(n) ? false : on); } |
787 | //@} | ||
788 | |||
789 | void makeChildNodeEmpty(Index n, const ValueType& value); | ||
790 | void setChildNode( Index i, ChildNodeType* child);//assumes a tile | ||
791 | void resetChildNode(Index i, ChildNodeType* child);//checks for an existing child | ||
792 | ChildNodeType* unsetChildNode(Index i, const ValueType& value); | ||
793 | |||
794 | template<typename NodeT, typename VisitorOp, typename ChildAllIterT> | ||
795 | static inline void doVisit(NodeT&, VisitorOp&); | ||
796 | |||
797 | template<typename NodeT, typename OtherNodeT, typename VisitorOp, | ||
798 | typename ChildAllIterT, typename OtherChildAllIterT> | ||
799 | static inline void doVisit2Node(NodeT&, OtherNodeT&, VisitorOp&); | ||
800 | |||
801 | template<typename NodeT, typename VisitorOp, | ||
802 | typename ChildAllIterT, typename OtherChildAllIterT> | ||
803 | static inline void doVisit2(NodeT&, OtherChildAllIterT&, VisitorOp&, bool otherIsLHS); | ||
804 | |||
805 | ///@{ | ||
806 | /// @brief Returns a pointer to the child node at the linear offset n. | ||
807 | /// @warning This protected method assumes that a child node exists at | ||
808 | /// the specified linear offset! | ||
809 | ChildNodeType* getChildNode(Index n); | ||
810 | const ChildNodeType* getChildNode(Index n) const; | ||
811 | ///@} | ||
812 | |||
813 | ///@{ | ||
814 | /// @brief Protected member classes for recursive multi-threading | ||
815 | struct VoxelizeActiveTiles; | ||
816 | template<typename OtherInternalNode> struct DeepCopy; | ||
817 | template<typename OtherInternalNode> struct TopologyCopy1; | ||
818 | template<typename OtherInternalNode> struct TopologyCopy2; | ||
819 | template<typename OtherInternalNode> struct TopologyUnion; | ||
820 | template<typename OtherInternalNode> struct TopologyDifference; | ||
821 | template<typename OtherInternalNode> struct TopologyIntersection; | ||
822 | ///@} | ||
823 | |||
824 | UnionType mNodes[NUM_VALUES]; | ||
825 | NodeMaskType mChildMask, mValueMask; | ||
826 | /// Global grid index coordinates (x,y,z) of the local origin of this node | ||
827 | Coord mOrigin; | ||
828 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
829 | /// Transient data (not serialized) | ||
830 | Index32 mTransientData = 0; | ||
831 | #endif | ||
832 | }; // class InternalNode | ||
833 | |||
834 | |||
835 | //////////////////////////////////////// | ||
836 | |||
837 | |||
838 | //@{ | ||
839 | /// Helper metafunction used to implement InternalNode::SameConfiguration | ||
840 | /// (which, as an inner class, can't be independently specialized) | ||
841 | template<typename ChildT1, Index Dim1, typename NodeT2> | ||
842 | struct SameInternalConfig { | ||
843 | static const bool value = false; | ||
844 | }; | ||
845 | |||
846 | template<typename ChildT1, Index Dim1, typename ChildT2> | ||
847 | struct SameInternalConfig<ChildT1, Dim1, InternalNode<ChildT2, Dim1> > { | ||
848 | static const bool value = ChildT1::template SameConfiguration<ChildT2>::value; | ||
849 | }; | ||
850 | //@} | ||
851 | |||
852 | |||
853 | //////////////////////////////////////// | ||
854 | |||
855 | |||
856 | template<typename ChildT, Index Log2Dim> | ||
857 | inline | ||
858 | InternalNode<ChildT, Log2Dim>::InternalNode(const ValueType& background) | ||
859 | { | ||
860 | for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(background); | ||
861 | } | ||
862 | |||
863 | |||
864 | template<typename ChildT, Index Log2Dim> | ||
865 | inline | ||
866 | 477391 | InternalNode<ChildT, Log2Dim>::InternalNode(const Coord& origin, const ValueType& val, bool active): | |
867 | mOrigin(origin[0] & ~(DIM - 1), // zero out the low-order bits | ||
868 | origin[1] & ~(DIM - 1), | ||
869 |
40/56✓ Branch 0 taken 3005841216 times.
✓ Branch 1 taken 214417 times.
✓ Branch 2 taken 37449 times.
✓ Branch 3 taken 176838 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1536 times.
✓ Branch 9 taken 24 times.
✓ Branch 10 taken 132 times.
✓ Branch 11 taken 22 times.
✓ Branch 12 taken 20480 times.
✓ Branch 13 taken 42 times.
✓ Branch 14 taken 2000000 times.
✓ Branch 15 taken 31290 times.
✓ Branch 16 taken 128 times.
✓ Branch 17 taken 31252 times.
✓ Branch 18 taken 1281 times.
✓ Branch 19 taken 21 times.
✓ Branch 20 taken 128 times.
✓ Branch 21 taken 22 times.
✓ Branch 22 taken 513 times.
✓ Branch 23 taken 9 times.
✓ Branch 24 taken 64 times.
✓ Branch 25 taken 1 times.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 1108224 times.
✓ Branch 29 taken 17316 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 15625 times.
✓ Branch 32 taken 8320 times.
✓ Branch 33 taken 130 times.
✓ Branch 34 taken 256 times.
✓ Branch 35 taken 4 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 4 times.
✓ Branch 38 taken 1664 times.
✓ Branch 39 taken 26 times.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✓ Branch 44 taken 25600 times.
✓ Branch 45 taken 400 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 400 times.
✓ Branch 48 taken 256 times.
✓ Branch 49 taken 4 times.
✓ Branch 50 taken 256 times.
✓ Branch 51 taken 4 times.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
|
6015712911 | origin[2] & ~(DIM - 1)) |
870 | { | ||
871 |
12/20✓ Branch 0 taken 37449 times.
✓ Branch 1 taken 176838 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 22 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 31294 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 17 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 15629 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 400 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
475398 | if (active) mValueMask.setOn(); |
872 |
30/40✓ Branch 0 taken 3005841216 times.
✓ Branch 1 taken 214417 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1536 times.
✓ Branch 5 taken 24 times.
✓ Branch 6 taken 20608 times.
✓ Branch 7 taken 42 times.
✓ Branch 8 taken 2000128 times.
✓ Branch 9 taken 31252 times.
✓ Branch 10 taken 1152 times.
✓ Branch 11 taken 18 times.
✓ Branch 12 taken 320 times.
✓ Branch 13 taken 5 times.
✓ Branch 14 taken 576 times.
✓ Branch 15 taken 9 times.
✓ Branch 16 taken 1000000 times.
✓ Branch 17 taken 15625 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 108160 times.
✓ Branch 21 taken 1690 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 8320 times.
✓ Branch 25 taken 130 times.
✓ Branch 26 taken 256 times.
✓ Branch 27 taken 4 times.
✓ Branch 28 taken 1664 times.
✓ Branch 29 taken 26 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 25600 times.
✓ Branch 33 taken 400 times.
✓ Branch 34 taken 256 times.
✓ Branch 35 taken 4 times.
✓ Branch 36 taken 256 times.
✓ Branch 37 taken 4 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
|
6015285391 | for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(val); |
873 | 427522 | } | |
874 | |||
875 | |||
876 | // For InternalNodes, the PartialCreate constructor is identical to its | ||
877 | // non-PartialCreate counterpart. | ||
878 | template<typename ChildT, Index Log2Dim> | ||
879 | inline | ||
880 | 1010 | InternalNode<ChildT, Log2Dim>::InternalNode(PartialCreate, | |
881 | const Coord& origin, const ValueType& val, bool active) | ||
882 |
3/12✓ Branch 0 taken 9222144 times.
✓ Branch 1 taken 505 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 505 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
18446308 | : mOrigin(origin[0] & ~(DIM-1), origin[1] & ~(DIM-1), origin[2] & ~(DIM-1)) |
883 | { | ||
884 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 505 times.
|
1010 | if (active) mValueMask.setOn(); |
885 |
2/12✓ Branch 0 taken 9222144 times.
✓ Branch 1 taken 505 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
18445298 | for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(val); |
886 | } | ||
887 | |||
888 | template<typename ChildT, Index Log2Dim> | ||
889 | template<typename OtherInternalNode> | ||
890 | struct InternalNode<ChildT, Log2Dim>::DeepCopy | ||
891 | { | ||
892 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
7997 | DeepCopy(const OtherInternalNode* source, InternalNode* target) : s(source), t(target) { |
893 |
2/12✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
|
7997 | tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this); |
894 | //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//serial | ||
895 | } | ||
896 | 2351522 | void operator()(const tbb::blocked_range<Index> &r) const { | |
897 |
2/2✓ Branch 0 taken 129753088 times.
✓ Branch 1 taken 1175761 times.
|
261857698 | for (Index i = r.begin(), end=r.end(); i!=end; ++i) { |
898 |
2/2✓ Branch 1 taken 129671652 times.
✓ Branch 2 taken 81436 times.
|
259506176 | if (s->mChildMask.isOff(i)) { |
899 | 260195248 | t->mNodes[i].setValue(ValueType(s->mNodes[i].getValue())); | |
900 | } else { | ||
901 |
1/2✓ Branch 2 taken 79303 times.
✗ Branch 3 not taken.
|
162872 | t->mNodes[i].setChild(new ChildNodeType(*(s->mNodes[i].getChild()))); |
902 | } | ||
903 | } | ||
904 | 2351522 | } | |
905 | const OtherInternalNode* s; | ||
906 | InternalNode* t; | ||
907 | };// DeepCopy | ||
908 | |||
909 | template<typename ChildT, Index Log2Dim> | ||
910 | inline | ||
911 | 9094 | InternalNode<ChildT, Log2Dim>::InternalNode(const InternalNode& other) | |
912 | : mChildMask(other.mChildMask) | ||
913 | , mValueMask(other.mValueMask) | ||
914 | , mOrigin(other.mOrigin) | ||
915 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
916 |
3/4✓ Branch 0 taken 85803008 times.
✓ Branch 1 taken 4547 times.
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
|
171624204 | , mTransientData(other.mTransientData) |
917 | #endif | ||
918 | { | ||
919 | DeepCopy<InternalNode<ChildT, Log2Dim> > tmp(&other, this); | ||
920 | 9094 | } | |
921 | |||
922 | |||
923 | // Copy-construct from a node with the same configuration but a different ValueType. | ||
924 | template<typename ChildT, Index Log2Dim> | ||
925 | template<typename OtherChildNodeType> | ||
926 | inline | ||
927 | 6900 | InternalNode<ChildT, Log2Dim>::InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other) | |
928 | : mChildMask(other.mChildMask) | ||
929 | , mValueMask(other.mValueMask) | ||
930 | , mOrigin(other.mOrigin) | ||
931 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
932 |
2/2✓ Branch 0 taken 43950080 times.
✓ Branch 1 taken 3450 times.
|
87913960 | , mTransientData(other.mTransientData) |
933 | #endif | ||
934 | { | ||
935 | DeepCopy<InternalNode<OtherChildNodeType, Log2Dim> > tmp(&other, this); | ||
936 | 6900 | } | |
937 | |||
938 | template<typename ChildT, Index Log2Dim> | ||
939 | template<typename OtherInternalNode> | ||
940 | struct InternalNode<ChildT, Log2Dim>::TopologyCopy1 | ||
941 | { | ||
942 | 44950 | TopologyCopy1(const OtherInternalNode* source, InternalNode* target, | |
943 | 44950 | const ValueType& background) : s(source), t(target), b(background) { | |
944 | 44950 | tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this); | |
945 | //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//serial | ||
946 | } | ||
947 | 12655502 | void operator()(const tbb::blocked_range<Index> &r) const { | |
948 |
2/2✓ Branch 0 taken 622682112 times.
✓ Branch 1 taken 6327751 times.
|
1258019726 | for (Index i = r.begin(), end=r.end(); i!=end; ++i) { |
949 |
2/2✓ Branch 1 taken 1185679 times.
✓ Branch 2 taken 621496433 times.
|
1245364224 | if (s->isChildMaskOn(i)) { |
950 |
1/2✓ Branch 1 taken 108558 times.
✗ Branch 2 not taken.
|
2435382 | t->mNodes[i].setChild(new ChildNodeType(*(s->mNodes[i].getChild()), |
951 |
1/2✓ Branch 1 taken 108558 times.
✗ Branch 2 not taken.
|
797056 | b, TopologyCopy())); |
952 | } else { | ||
953 | 1242992866 | t->mNodes[i].setValue(b); | |
954 | } | ||
955 | } | ||
956 | 12655502 | } | |
957 | const OtherInternalNode* s; | ||
958 | InternalNode* t; | ||
959 | const ValueType &b; | ||
960 | };// TopologyCopy1 | ||
961 | |||
962 | template<typename ChildT, Index Log2Dim> | ||
963 | template<typename OtherChildNodeType> | ||
964 | inline | ||
965 | 89900 | InternalNode<ChildT, Log2Dim>::InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other, | |
966 | const ValueType& background, TopologyCopy) | ||
967 | : mChildMask(other.mChildMask) | ||
968 | , mValueMask(other.mValueMask) | ||
969 | , mOrigin(other.mOrigin) | ||
970 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
971 |
2/2✓ Branch 0 taken 622682112 times.
✓ Branch 1 taken 44950 times.
|
1245544024 | , mTransientData(other.mTransientData) |
972 | #endif | ||
973 | { | ||
974 | TopologyCopy1<InternalNode<OtherChildNodeType, Log2Dim> > tmp(&other, this, background); | ||
975 | 89900 | } | |
976 | |||
977 | template<typename ChildT, Index Log2Dim> | ||
978 | template<typename OtherInternalNode> | ||
979 | struct InternalNode<ChildT, Log2Dim>::TopologyCopy2 | ||
980 | { | ||
981 | 172 | TopologyCopy2(const OtherInternalNode* source, InternalNode* target, | |
982 | const ValueType& offValue, const ValueType& onValue) | ||
983 | 172 | : s(source), t(target), offV(offValue), onV(onValue) { | |
984 | 172 | tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this); | |
985 | } | ||
986 | 43682 | void operator()(const tbb::blocked_range<Index> &r) const { | |
987 |
2/2✓ Branch 0 taken 1894400 times.
✓ Branch 1 taken 21841 times.
|
3832482 | for (Index i = r.begin(), end=r.end(); i!=end; ++i) { |
988 |
2/2✓ Branch 1 taken 14460 times.
✓ Branch 2 taken 1879940 times.
|
3788800 | if (s->isChildMaskOn(i)) { |
989 |
1/2✓ Branch 1 taken 94 times.
✗ Branch 2 not taken.
|
57840 | t->mNodes[i].setChild(new ChildNodeType(*(s->mNodes[i].getChild()), |
990 |
1/2✓ Branch 1 taken 94 times.
✗ Branch 2 not taken.
|
28920 | offV, onV, TopologyCopy())); |
991 | } else { | ||
992 |
2/2✓ Branch 1 taken 164 times.
✓ Branch 2 taken 1879776 times.
|
3759880 | t->mNodes[i].setValue(s->isValueMaskOn(i) ? onV : offV); |
993 | } | ||
994 | } | ||
995 | 43682 | } | |
996 | const OtherInternalNode* s; | ||
997 | InternalNode* t; | ||
998 | const ValueType &offV, &onV; | ||
999 | };// TopologyCopy2 | ||
1000 | |||
1001 | template<typename ChildT, Index Log2Dim> | ||
1002 | template<typename OtherChildNodeType> | ||
1003 | inline | ||
1004 | 344 | InternalNode<ChildT, Log2Dim>::InternalNode(const InternalNode<OtherChildNodeType, Log2Dim>& other, | |
1005 | const ValueType& offValue, | ||
1006 | const ValueType& onValue, TopologyCopy) | ||
1007 | : mChildMask(other.mChildMask) | ||
1008 | , mValueMask(other.mValueMask) | ||
1009 | , mOrigin(other.mOrigin) | ||
1010 | #if OPENVDB_ABI_VERSION_NUMBER >= 9 | ||
1011 |
2/2✓ Branch 0 taken 1894400 times.
✓ Branch 1 taken 172 times.
|
3789424 | , mTransientData(other.mTransientData) |
1012 | #endif | ||
1013 | { | ||
1014 | TopologyCopy2<InternalNode<OtherChildNodeType, Log2Dim> > tmp(&other, this, offValue, onValue); | ||
1015 | 344 | } | |
1016 | |||
1017 | |||
1018 | template<typename ChildT, Index Log2Dim> | ||
1019 | inline | ||
1020 | 634548 | InternalNode<ChildT, Log2Dim>::~InternalNode() | |
1021 | { | ||
1022 |
2/2✓ Branch 0 taken 297102 times.
✓ Branch 1 taken 317274 times.
|
1228752 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
1023 |
1/2✓ Branch 0 taken 297102 times.
✗ Branch 1 not taken.
|
641680 | delete mNodes[iter.pos()].getChild(); |
1024 | } | ||
1025 |
3/4✓ Branch 0 taken 487 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10129984 times.
✓ Branch 3 taken 487 times.
|
20895490 | } |
1026 | |||
1027 | |||
1028 | //////////////////////////////////////// | ||
1029 | |||
1030 | |||
1031 | template<typename ChildT, Index Log2Dim> | ||
1032 | inline Index32 | ||
1033 | 214937 | InternalNode<ChildT, Log2Dim>::leafCount() const | |
1034 | { | ||
1035 |
7/14✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 21 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 9 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 155 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 174 times.
✗ Branch 20 not taken.
|
217684 | if (ChildNodeType::getLevel() == 0) return mChildMask.countOn(); |
1036 | Index32 sum = 0; | ||
1037 |
2/2✓ Branch 0 taken 108674 times.
✓ Branch 1 taken 107475 times.
|
432262 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { |
1038 | 217325 | sum += iter->leafCount(); | |
1039 | } | ||
1040 | return sum; | ||
1041 | } | ||
1042 | |||
1043 | template<typename ChildT, Index Log2Dim> | ||
1044 | inline void | ||
1045 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
|
672 | InternalNode<ChildT, Log2Dim>::nodeCount(std::vector<Index32> &vec) const |
1046 | { | ||
1047 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 336 times.
|
672 | assert(vec.size() > ChildNodeType::LEVEL); |
1048 | 672 | const auto count = mChildMask.countOn(); | |
1049 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
48 | if (ChildNodeType::LEVEL > 0 && count > 0) { |
1050 |
2/2✓ Branch 0 taken 312 times.
✓ Branch 1 taken 24 times.
|
1296 | for (auto iter = this->cbeginChildOn(); iter; ++iter) iter->nodeCount(vec); |
1051 | } | ||
1052 | 672 | vec[ChildNodeType::LEVEL] += count; | |
1053 | } | ||
1054 | |||
1055 | |||
1056 | template<typename ChildT, Index Log2Dim> | ||
1057 | inline Index32 | ||
1058 | 2405 | InternalNode<ChildT, Log2Dim>::nonLeafCount() const | |
1059 | { | ||
1060 | Index32 sum = 1; | ||
1061 | if (ChildNodeType::getLevel() == 0) return sum; | ||
1062 |
2/2✓ Branch 0 taken 1394 times.
✓ Branch 1 taken 1209 times.
|
5170 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { |
1063 | 2765 | sum += iter->nonLeafCount(); | |
1064 | } | ||
1065 | return sum; | ||
1066 | } | ||
1067 | |||
1068 | |||
1069 | template<typename ChildT, Index Log2Dim> | ||
1070 | inline Index32 | ||
1071 | InternalNode<ChildT, Log2Dim>::childCount() const | ||
1072 | { | ||
1073 |
20/511✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✓ Branch 42 taken 3 times.
✓ Branch 43 taken 3 times.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✓ Branch 124 taken 1 times.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✗ Branch 141 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 147 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 150 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 155 not taken.
✗ Branch 156 not taken.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
✗ Branch 160 not taken.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 164 not taken.
✗ Branch 165 not taken.
✓ Branch 166 taken 8 times.
✗ Branch 167 not taken.
✗ Branch 168 not taken.
✓ Branch 169 taken 8 times.
✗ Branch 170 not taken.
✓ Branch 171 taken 1 times.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✓ Branch 174 taken 1 times.
✗ Branch 175 not taken.
✗ Branch 176 not taken.
✓ Branch 177 taken 1 times.
✗ Branch 178 not taken.
✗ Branch 179 not taken.
✓ Branch 180 taken 1 times.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✓ Branch 183 taken 1 times.
✗ Branch 184 not taken.
✗ Branch 185 not taken.
✓ Branch 186 taken 1 times.
✗ Branch 187 not taken.
✗ Branch 188 not taken.
✓ Branch 189 taken 1 times.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 196 not taken.
✗ Branch 197 not taken.
✗ Branch 199 not taken.
✗ Branch 200 not taken.
✗ Branch 202 not taken.
✗ Branch 203 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 208 not taken.
✗ Branch 209 not taken.
✗ Branch 211 not taken.
✗ Branch 212 not taken.
✗ Branch 214 not taken.
✗ Branch 215 not taken.
✗ Branch 217 not taken.
✗ Branch 218 not taken.
✗ Branch 220 not taken.
✗ Branch 221 not taken.
✗ Branch 223 not taken.
✗ Branch 224 not taken.
✗ Branch 226 not taken.
✗ Branch 227 not taken.
✗ Branch 229 not taken.
✗ Branch 230 not taken.
✗ Branch 232 not taken.
✗ Branch 233 not taken.
✗ Branch 235 not taken.
✗ Branch 236 not taken.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
✗ Branch 241 not taken.
✗ Branch 242 not taken.
✗ Branch 244 not taken.
✗ Branch 245 not taken.
✗ Branch 247 not taken.
✗ Branch 248 not taken.
✗ Branch 250 not taken.
✗ Branch 251 not taken.
✗ Branch 253 not taken.
✗ Branch 254 not taken.
✗ Branch 256 not taken.
✗ Branch 257 not taken.
✗ Branch 259 not taken.
✗ Branch 260 not taken.
✗ Branch 262 not taken.
✗ Branch 263 not taken.
✗ Branch 265 not taken.
✗ Branch 266 not taken.
✗ Branch 268 not taken.
✗ Branch 269 not taken.
✗ Branch 271 not taken.
✗ Branch 272 not taken.
✗ Branch 274 not taken.
✗ Branch 275 not taken.
✗ Branch 277 not taken.
✗ Branch 278 not taken.
✗ Branch 280 not taken.
✗ Branch 281 not taken.
✗ Branch 283 not taken.
✗ Branch 284 not taken.
✗ Branch 286 not taken.
✗ Branch 287 not taken.
✗ Branch 289 not taken.
✗ Branch 290 not taken.
✗ Branch 292 not taken.
✗ Branch 293 not taken.
✗ Branch 295 not taken.
✗ Branch 296 not taken.
✗ Branch 298 not taken.
✗ Branch 299 not taken.
✗ Branch 301 not taken.
✗ Branch 302 not taken.
✗ Branch 304 not taken.
✗ Branch 305 not taken.
✗ Branch 307 not taken.
✗ Branch 308 not taken.
✗ Branch 310 not taken.
✗ Branch 311 not taken.
✗ Branch 313 not taken.
✗ Branch 314 not taken.
✗ Branch 316 not taken.
✗ Branch 317 not taken.
✓ Branch 319 taken 1 times.
✗ Branch 320 not taken.
✓ Branch 322 taken 1 times.
✗ Branch 323 not taken.
✓ Branch 325 taken 1 times.
✗ Branch 326 not taken.
✓ Branch 328 taken 1 times.
✗ Branch 329 not taken.
✓ Branch 331 taken 1 times.
✗ Branch 332 not taken.
✓ Branch 334 taken 1 times.
✗ Branch 335 not taken.
✗ Branch 337 not taken.
✗ Branch 338 not taken.
✗ Branch 340 not taken.
✗ Branch 341 not taken.
✗ Branch 343 not taken.
✗ Branch 344 not taken.
✗ Branch 346 not taken.
✗ Branch 347 not taken.
✗ Branch 349 not taken.
✗ Branch 350 not taken.
✗ Branch 352 not taken.
✗ Branch 353 not taken.
✗ Branch 355 not taken.
✗ Branch 356 not taken.
✗ Branch 358 not taken.
✗ Branch 359 not taken.
✗ Branch 361 not taken.
✗ Branch 362 not taken.
✗ Branch 364 not taken.
✗ Branch 365 not taken.
✗ Branch 367 not taken.
✗ Branch 368 not taken.
✗ Branch 370 not taken.
✗ Branch 371 not taken.
✗ Branch 373 not taken.
✗ Branch 374 not taken.
✗ Branch 376 not taken.
✗ Branch 377 not taken.
✗ Branch 379 not taken.
✗ Branch 380 not taken.
✗ Branch 382 not taken.
✗ Branch 383 not taken.
✗ Branch 385 not taken.
✗ Branch 386 not taken.
✗ Branch 388 not taken.
✗ Branch 389 not taken.
✗ Branch 391 not taken.
✗ Branch 392 not taken.
✗ Branch 394 not taken.
✗ Branch 395 not taken.
✗ Branch 397 not taken.
✗ Branch 398 not taken.
✗ Branch 400 not taken.
✗ Branch 401 not taken.
✗ Branch 403 not taken.
✗ Branch 404 not taken.
✗ Branch 406 not taken.
✗ Branch 407 not taken.
✗ Branch 409 not taken.
✗ Branch 410 not taken.
✗ Branch 412 not taken.
✗ Branch 413 not taken.
✗ Branch 415 not taken.
✗ Branch 416 not taken.
✗ Branch 418 not taken.
✗ Branch 419 not taken.
✗ Branch 421 not taken.
✗ Branch 422 not taken.
✗ Branch 424 not taken.
✗ Branch 425 not taken.
✗ Branch 427 not taken.
✗ Branch 428 not taken.
✗ Branch 430 not taken.
✗ Branch 431 not taken.
✗ Branch 433 not taken.
✗ Branch 434 not taken.
✗ Branch 436 not taken.
✗ Branch 437 not taken.
✗ Branch 439 not taken.
✗ Branch 440 not taken.
✗ Branch 442 not taken.
✗ Branch 443 not taken.
✗ Branch 445 not taken.
✗ Branch 446 not taken.
✗ Branch 448 not taken.
✗ Branch 449 not taken.
✗ Branch 451 not taken.
✗ Branch 452 not taken.
✗ Branch 454 not taken.
✗ Branch 455 not taken.
✗ Branch 457 not taken.
✗ Branch 458 not taken.
✗ Branch 460 not taken.
✗ Branch 461 not taken.
✗ Branch 463 not taken.
✗ Branch 464 not taken.
✗ Branch 466 not taken.
✗ Branch 467 not taken.
✗ Branch 469 not taken.
✗ Branch 470 not taken.
✗ Branch 472 not taken.
✗ Branch 473 not taken.
✗ Branch 475 not taken.
✗ Branch 476 not taken.
✗ Branch 478 not taken.
✗ Branch 479 not taken.
✗ Branch 481 not taken.
✗ Branch 482 not taken.
✗ Branch 484 not taken.
✗ Branch 485 not taken.
✗ Branch 487 not taken.
✗ Branch 488 not taken.
✗ Branch 490 not taken.
✗ Branch 491 not taken.
✗ Branch 493 not taken.
✗ Branch 494 not taken.
✗ Branch 496 not taken.
✗ Branch 497 not taken.
✗ Branch 499 not taken.
✗ Branch 500 not taken.
✗ Branch 502 not taken.
✗ Branch 503 not taken.
✗ Branch 505 not taken.
✗ Branch 506 not taken.
✗ Branch 508 not taken.
✗ Branch 509 not taken.
✗ Branch 511 not taken.
✗ Branch 512 not taken.
✗ Branch 514 not taken.
✗ Branch 515 not taken.
✗ Branch 517 not taken.
✗ Branch 518 not taken.
✗ Branch 520 not taken.
✗ Branch 521 not taken.
✗ Branch 523 not taken.
✗ Branch 524 not taken.
✗ Branch 526 not taken.
✗ Branch 527 not taken.
✗ Branch 529 not taken.
✗ Branch 530 not taken.
✗ Branch 532 not taken.
✗ Branch 533 not taken.
✗ Branch 535 not taken.
✗ Branch 536 not taken.
✗ Branch 538 not taken.
✗ Branch 539 not taken.
✗ Branch 541 not taken.
✗ Branch 542 not taken.
✗ Branch 544 not taken.
✗ Branch 545 not taken.
✗ Branch 547 not taken.
✗ Branch 548 not taken.
✗ Branch 550 not taken.
✗ Branch 551 not taken.
✗ Branch 553 not taken.
✗ Branch 554 not taken.
✗ Branch 556 not taken.
✗ Branch 557 not taken.
✗ Branch 559 not taken.
✗ Branch 560 not taken.
✗ Branch 562 not taken.
✗ Branch 563 not taken.
✗ Branch 565 not taken.
✗ Branch 566 not taken.
✗ Branch 568 not taken.
✗ Branch 569 not taken.
✗ Branch 571 not taken.
✗ Branch 572 not taken.
✗ Branch 574 not taken.
✗ Branch 575 not taken.
✗ Branch 577 not taken.
✗ Branch 578 not taken.
✗ Branch 580 not taken.
✗ Branch 581 not taken.
✗ Branch 583 not taken.
✗ Branch 584 not taken.
✗ Branch 586 not taken.
✗ Branch 587 not taken.
✗ Branch 589 not taken.
✗ Branch 590 not taken.
✗ Branch 592 not taken.
✗ Branch 593 not taken.
✗ Branch 595 not taken.
✗ Branch 596 not taken.
✗ Branch 598 not taken.
✗ Branch 599 not taken.
✗ Branch 601 not taken.
✗ Branch 602 not taken.
✗ Branch 604 not taken.
✗ Branch 605 not taken.
✗ Branch 607 not taken.
✗ Branch 608 not taken.
✗ Branch 610 not taken.
✗ Branch 611 not taken.
✗ Branch 613 not taken.
✗ Branch 614 not taken.
✗ Branch 616 not taken.
✗ Branch 617 not taken.
✗ Branch 619 not taken.
✗ Branch 620 not taken.
✗ Branch 622 not taken.
✗ Branch 623 not taken.
✗ Branch 625 not taken.
✗ Branch 626 not taken.
✗ Branch 628 not taken.
✗ Branch 629 not taken.
✗ Branch 631 not taken.
✗ Branch 632 not taken.
✗ Branch 634 not taken.
✗ Branch 635 not taken.
✗ Branch 637 not taken.
✗ Branch 638 not taken.
✗ Branch 640 not taken.
✗ Branch 641 not taken.
✗ Branch 643 not taken.
✗ Branch 644 not taken.
✗ Branch 646 not taken.
✗ Branch 647 not taken.
✗ Branch 649 not taken.
✗ Branch 650 not taken.
✗ Branch 652 not taken.
✗ Branch 653 not taken.
✗ Branch 655 not taken.
✗ Branch 656 not taken.
✗ Branch 658 not taken.
✗ Branch 659 not taken.
✗ Branch 661 not taken.
✗ Branch 662 not taken.
✗ Branch 664 not taken.
✗ Branch 665 not taken.
✗ Branch 667 not taken.
✗ Branch 668 not taken.
✗ Branch 670 not taken.
✗ Branch 671 not taken.
✗ Branch 673 not taken.
✗ Branch 674 not taken.
✗ Branch 676 not taken.
✗ Branch 677 not taken.
✗ Branch 679 not taken.
✗ Branch 680 not taken.
✗ Branch 682 not taken.
✗ Branch 683 not taken.
✗ Branch 685 not taken.
✗ Branch 686 not taken.
✗ Branch 688 not taken.
✗ Branch 689 not taken.
✗ Branch 691 not taken.
✗ Branch 692 not taken.
✗ Branch 694 not taken.
✗ Branch 695 not taken.
✗ Branch 697 not taken.
✗ Branch 698 not taken.
✗ Branch 700 not taken.
✗ Branch 701 not taken.
✗ Branch 703 not taken.
✗ Branch 704 not taken.
✗ Branch 706 not taken.
✗ Branch 707 not taken.
✗ Branch 709 not taken.
✗ Branch 710 not taken.
✗ Branch 712 not taken.
✗ Branch 713 not taken.
✗ Branch 715 not taken.
✗ Branch 716 not taken.
✗ Branch 718 not taken.
✗ Branch 719 not taken.
|
171188 | return this->getChildMask().countOn(); |
1074 | } | ||
1075 | |||
1076 | |||
1077 | template<typename ChildT, Index Log2Dim> | ||
1078 | inline Index64 | ||
1079 | InternalNode<ChildT, Log2Dim>::onVoxelCount() const | ||
1080 | { | ||
1081 | Index64 sum = ChildT::NUM_VOXELS * mValueMask.countOn(); | ||
1082 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { | ||
1083 | sum += iter->onVoxelCount(); | ||
1084 | } | ||
1085 | return sum; | ||
1086 | } | ||
1087 | |||
1088 | |||
1089 | template<typename ChildT, Index Log2Dim> | ||
1090 | inline Index64 | ||
1091 | InternalNode<ChildT, Log2Dim>::offVoxelCount() const | ||
1092 | { | ||
1093 | Index64 sum = ChildT::NUM_VOXELS * (NUM_VALUES-mValueMask.countOn()-mChildMask.countOn()); | ||
1094 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { | ||
1095 | sum += iter->offVoxelCount(); | ||
1096 | } | ||
1097 | return sum; | ||
1098 | } | ||
1099 | |||
1100 | |||
1101 | template<typename ChildT, Index Log2Dim> | ||
1102 | inline Index64 | ||
1103 | InternalNode<ChildT, Log2Dim>::onLeafVoxelCount() const | ||
1104 | { | ||
1105 | Index64 sum = 0; | ||
1106 | for (ChildOnCIter iter = this->beginChildOn(); iter; ++iter) { | ||
1107 | sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount(); | ||
1108 | } | ||
1109 | return sum; | ||
1110 | } | ||
1111 | |||
1112 | |||
1113 | template<typename ChildT, Index Log2Dim> | ||
1114 | inline Index64 | ||
1115 | InternalNode<ChildT, Log2Dim>::offLeafVoxelCount() const | ||
1116 | { | ||
1117 | Index64 sum = 0; | ||
1118 | for (ChildOnCIter iter = this->beginChildOn(); iter; ++iter) { | ||
1119 | sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount(); | ||
1120 | } | ||
1121 | return sum; | ||
1122 | } | ||
1123 | |||
1124 | template<typename ChildT, Index Log2Dim> | ||
1125 | inline Index64 | ||
1126 | 1 | InternalNode<ChildT, Log2Dim>::onTileCount() const | |
1127 | { | ||
1128 | 3 | Index64 sum = mValueMask.countOn(); | |
1129 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) { |
1130 | 2 | sum += iter->onTileCount(); | |
1131 | } | ||
1132 | 1 | return sum; | |
1133 | } | ||
1134 | |||
1135 | template<typename ChildT, Index Log2Dim> | ||
1136 | inline Index64 | ||
1137 | InternalNode<ChildT, Log2Dim>::memUsage() const | ||
1138 | { | ||
1139 | Index64 sum = NUM_VALUES * sizeof(UnionType) + mChildMask.memUsage() | ||
1140 | + mValueMask.memUsage() + sizeof(mOrigin); | ||
1141 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { | ||
1142 | sum += iter->memUsage(); | ||
1143 | } | ||
1144 | return sum; | ||
1145 | } | ||
1146 | |||
1147 | |||
1148 | template<typename ChildT, Index Log2Dim> | ||
1149 | inline void | ||
1150 | 5828 | InternalNode<ChildT, Log2Dim>::evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels) const | |
1151 | { | ||
1152 | 11656 | if (bbox.isInside(this->getNodeBoundingBox())) return; | |
1153 | |||
1154 |
2/2✓ Branch 0 taken 13628 times.
✓ Branch 1 taken 2761 times.
|
32778 | for (ValueOnCIter i = this->cbeginValueOn(); i; ++i) { |
1155 | 27256 | bbox.expand(i.getCoord(), ChildT::DIM); | |
1156 | } | ||
1157 |
2/2✓ Branch 0 taken 120649 times.
✓ Branch 1 taken 2761 times.
|
246820 | for (ChildOnCIter i = this->cbeginChildOn(); i; ++i) { |
1158 | 241298 | i->evalActiveBoundingBox(bbox, visitVoxels); | |
1159 | } | ||
1160 | } | ||
1161 | |||
1162 | |||
1163 | //////////////////////////////////////// | ||
1164 | |||
1165 | |||
1166 | template<typename ChildT, Index Log2Dim> | ||
1167 | inline void | ||
1168 | 864 | InternalNode<ChildT, Log2Dim>::prune(const ValueType& tolerance) | |
1169 | { | ||
1170 | 864 | bool state = false; | |
1171 | 736 | ValueType value = zeroVal<ValueType>(); | |
1172 |
2/2✓ Branch 0 taken 22128 times.
✓ Branch 1 taken 432 times.
|
45120 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
1173 | const Index i = iter.pos(); | ||
1174 | ChildT* child = mNodes[i].getChild(); | ||
1175 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
434 | child->prune(tolerance); |
1176 |
2/5✗ Branch 0 not taken.
✓ Branch 1 taken 190 times.
✓ Branch 2 taken 21938 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
44256 | if (child->isConstant(value, state, tolerance)) { |
1177 |
1/2✓ Branch 0 taken 190 times.
✗ Branch 1 not taken.
|
734 | delete child; |
1178 | 380 | mChildMask.setOff(i); | |
1179 |
2/2✓ Branch 0 taken 58 times.
✓ Branch 1 taken 132 times.
|
380 | mValueMask.set(i, state); |
1180 | mNodes[i].setValue(value); | ||
1181 | } | ||
1182 | } | ||
1183 | } | ||
1184 | |||
1185 | |||
1186 | //////////////////////////////////////// | ||
1187 | |||
1188 | |||
1189 | template<typename ChildT, Index Log2Dim> | ||
1190 | template<typename NodeT> | ||
1191 | inline NodeT* | ||
1192 | 126866 | InternalNode<ChildT, Log2Dim>::stealNode(const Coord& xyz, const ValueType& value, bool state) | |
1193 | { | ||
1194 | if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) || | ||
1195 | NodeT::LEVEL > ChildT::LEVEL) return nullptr; | ||
1196 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
1197 | const Index n = this->coordToOffset(xyz); | ||
1198 |
2/2✓ Branch 0 taken 63431 times.
✓ Branch 1 taken 2 times.
|
126866 | if (mChildMask.isOff(n)) return nullptr; |
1199 | ChildT* child = mNodes[n].getChild(); | ||
1200 | if (std::is_same<NodeT, ChildT>::value) { | ||
1201 | 63498 | mChildMask.setOff(n); | |
1202 |
2/2✓ Branch 0 taken 3174 times.
✓ Branch 1 taken 28575 times.
|
63498 | mValueMask.set(n, state); |
1203 | mNodes[n].setValue(value); | ||
1204 | } | ||
1205 | return (std::is_same<NodeT, ChildT>::value) | ||
1206 | 63364 | ? reinterpret_cast<NodeT*>(child) | |
1207 | 126862 | : child->template stealNode<NodeT>(xyz, value, state); | |
1208 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
1209 | } | ||
1210 | |||
1211 | |||
1212 | //////////////////////////////////////// | ||
1213 | |||
1214 | |||
1215 | template<typename ChildT, Index Log2Dim> | ||
1216 | template<typename NodeT> | ||
1217 | inline NodeT* | ||
1218 | 156456 | InternalNode<ChildT, Log2Dim>::probeNode(const Coord& xyz) | |
1219 | { | ||
1220 | if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) || | ||
1221 | NodeT::LEVEL > ChildT::LEVEL) return nullptr; | ||
1222 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
1223 | const Index n = this->coordToOffset(xyz); | ||
1224 |
2/2✓ Branch 0 taken 60650 times.
✓ Branch 1 taken 19306 times.
|
156456 | if (mChildMask.isOff(n)) return nullptr; |
1225 | ChildT* child = mNodes[n].getChild(); | ||
1226 | return (std::is_same<NodeT, ChildT>::value) | ||
1227 | 76382 | ? reinterpret_cast<NodeT*>(child) | |
1228 | 117844 | : child->template probeNode<NodeT>(xyz); | |
1229 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
1230 | } | ||
1231 | |||
1232 | |||
1233 | template<typename ChildT, Index Log2Dim> | ||
1234 | template<typename NodeT, typename AccessorT> | ||
1235 | inline NodeT* | ||
1236 | 7144828 | InternalNode<ChildT, Log2Dim>::probeNodeAndCache(const Coord& xyz, AccessorT& acc) | |
1237 | { | ||
1238 | if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) || | ||
1239 | NodeT::LEVEL > ChildT::LEVEL) return nullptr; | ||
1240 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
1241 | const Index n = this->coordToOffset(xyz); | ||
1242 |
2/2✓ Branch 0 taken 3063946 times.
✓ Branch 1 taken 508468 times.
|
7144828 | if (mChildMask.isOff(n)) return nullptr; |
1243 | ChildT* child = mNodes[n].getChild(); | ||
1244 | 6127892 | acc.insert(xyz, child); | |
1245 | return (std::is_same<NodeT, ChildT>::value) | ||
1246 | 1690896 | ? reinterpret_cast<NodeT*>(child) | |
1247 | 6127892 | : child->template probeNodeAndCache<NodeT>(xyz, acc); | |
1248 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
1249 | } | ||
1250 | |||
1251 | |||
1252 | template<typename ChildT, Index Log2Dim> | ||
1253 | template<typename NodeT> | ||
1254 | inline const NodeT* | ||
1255 | 358846 | InternalNode<ChildT, Log2Dim>::probeConstNode(const Coord& xyz) const | |
1256 | { | ||
1257 | if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) || | ||
1258 | NodeT::LEVEL > ChildT::LEVEL) return nullptr; | ||
1259 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
1260 | const Index n = this->coordToOffset(xyz); | ||
1261 |
2/2✓ Branch 0 taken 166101 times.
✓ Branch 1 taken 13322 times.
|
358846 | if (mChildMask.isOff(n)) return nullptr; |
1262 | const ChildT* child = mNodes[n].getChild(); | ||
1263 | return (std::is_same<NodeT, ChildT>::value) | ||
1264 | 179202 | ? reinterpret_cast<const NodeT*>(child) | |
1265 | 332202 | : child->template probeConstNode<NodeT>(xyz); | |
1266 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
1267 | } | ||
1268 | |||
1269 | |||
1270 | template<typename ChildT, Index Log2Dim> | ||
1271 | template<typename NodeT, typename AccessorT> | ||
1272 | inline const NodeT* | ||
1273 | 806133010 | InternalNode<ChildT, Log2Dim>::probeConstNodeAndCache(const Coord& xyz, AccessorT& acc) const | |
1274 | { | ||
1275 | if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) || | ||
1276 | NodeT::LEVEL > ChildT::LEVEL) return nullptr; | ||
1277 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
1278 | const Index n = this->coordToOffset(xyz); | ||
1279 |
2/2✓ Branch 0 taken 1273827 times.
✓ Branch 1 taken 401792678 times.
|
806133010 | if (mChildMask.isOff(n)) return nullptr; |
1280 | const ChildT* child = mNodes[n].getChild(); | ||
1281 | 2547654 | acc.insert(xyz, child); | |
1282 | return (std::is_same<NodeT, ChildT>::value) | ||
1283 | 1541734 | ? reinterpret_cast<const NodeT*>(child) | |
1284 | 2547654 | : child->template probeConstNodeAndCache<NodeT>(xyz, acc); | |
1285 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
1286 | } | ||
1287 | |||
1288 | |||
1289 | //////////////////////////////////////// | ||
1290 | |||
1291 | |||
1292 | template<typename ChildT, Index Log2Dim> | ||
1293 | inline typename ChildT::LeafNodeType* | ||
1294 | InternalNode<ChildT, Log2Dim>::probeLeaf(const Coord& xyz) | ||
1295 | { | ||
1296 | 1 | return this->template probeNode<LeafNodeType>(xyz); | |
1297 | } | ||
1298 | |||
1299 | |||
1300 | template<typename ChildT, Index Log2Dim> | ||
1301 | template<typename AccessorT> | ||
1302 | inline typename ChildT::LeafNodeType* | ||
1303 | InternalNode<ChildT, Log2Dim>::probeLeafAndCache(const Coord& xyz, AccessorT& acc) | ||
1304 | { | ||
1305 | return this->template probeNodeAndCache<LeafNodeType>(xyz, acc); | ||
1306 | } | ||
1307 | |||
1308 | |||
1309 | template<typename ChildT, Index Log2Dim> | ||
1310 | template<typename AccessorT> | ||
1311 | inline const typename ChildT::LeafNodeType* | ||
1312 | InternalNode<ChildT, Log2Dim>::probeLeafAndCache(const Coord& xyz, AccessorT& acc) const | ||
1313 | { | ||
1314 | return this->probeConstLeafAndCache(xyz, acc); | ||
1315 | } | ||
1316 | |||
1317 | |||
1318 | template<typename ChildT, Index Log2Dim> | ||
1319 | inline const typename ChildT::LeafNodeType* | ||
1320 | InternalNode<ChildT, Log2Dim>::probeConstLeaf(const Coord& xyz) const | ||
1321 | { | ||
1322 | return this->template probeConstNode<LeafNodeType>(xyz); | ||
1323 | } | ||
1324 | |||
1325 | |||
1326 | template<typename ChildT, Index Log2Dim> | ||
1327 | template<typename AccessorT> | ||
1328 | inline const typename ChildT::LeafNodeType* | ||
1329 | InternalNode<ChildT, Log2Dim>::probeConstLeafAndCache(const Coord& xyz, AccessorT& acc) const | ||
1330 | { | ||
1331 | return this->template probeConstNodeAndCache<LeafNodeType>(xyz, acc); | ||
1332 | } | ||
1333 | |||
1334 | |||
1335 | //////////////////////////////////////// | ||
1336 | |||
1337 | |||
1338 | template<typename ChildT, Index Log2Dim> | ||
1339 | inline void | ||
1340 | 773192 | InternalNode<ChildT, Log2Dim>::addLeaf(LeafNodeType* leaf) | |
1341 | { | ||
1342 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 386596 times.
|
773192 | assert(leaf != nullptr); |
1343 | const Coord& xyz = leaf->origin(); | ||
1344 | const Index n = this->coordToOffset(xyz); | ||
1345 | ChildT* child = nullptr; | ||
1346 |
2/2✓ Branch 0 taken 349129 times.
✓ Branch 1 taken 37467 times.
|
773192 | if (mChildMask.isOff(n)) { |
1347 | if (ChildT::LEVEL>0) { | ||
1348 | 40814 | child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n)); | |
1349 | } else { | ||
1350 | child = reinterpret_cast<ChildT*>(leaf); | ||
1351 | } | ||
1352 | 698258 | this->setChildNode(n, child); | |
1353 | } else { | ||
1354 | if (ChildT::LEVEL>0) { | ||
1355 | child = mNodes[n].getChild(); | ||
1356 | } else { | ||
1357 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
4 | delete mNodes[n].getChild(); |
1358 | child = reinterpret_cast<ChildT*>(leaf); | ||
1359 | mNodes[n].setChild(child); | ||
1360 | } | ||
1361 | } | ||
1362 | 115746 | child->addLeaf(leaf); | |
1363 | 773192 | } | |
1364 | |||
1365 | |||
1366 | template<typename ChildT, Index Log2Dim> | ||
1367 | template<typename AccessorT> | ||
1368 | inline void | ||
1369 | 247342 | InternalNode<ChildT, Log2Dim>::addLeafAndCache(LeafNodeType* leaf, AccessorT& acc) | |
1370 | { | ||
1371 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 123671 times.
|
247342 | assert(leaf != nullptr); |
1372 | const Coord& xyz = leaf->origin(); | ||
1373 | const Index n = this->coordToOffset(xyz); | ||
1374 | ChildT* child = nullptr; | ||
1375 |
2/2✓ Branch 0 taken 122423 times.
✓ Branch 1 taken 1248 times.
|
247342 | if (mChildMask.isOff(n)) { |
1376 | if (ChildT::LEVEL>0) { | ||
1377 | 6408 | child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n)); | |
1378 | 6408 | acc.insert(xyz, child);//we only cache internal nodes | |
1379 | } else { | ||
1380 | child = reinterpret_cast<ChildT*>(leaf); | ||
1381 | } | ||
1382 | 244846 | this->setChildNode(n, child); | |
1383 | } else { | ||
1384 | if (ChildT::LEVEL>0) { | ||
1385 | child = mNodes[n].getChild(); | ||
1386 | 2464 | acc.insert(xyz, child);//we only cache internal nodes | |
1387 | } else { | ||
1388 |
1/2✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
|
64 | delete mNodes[n].getChild(); |
1389 | child = reinterpret_cast<ChildT*>(leaf); | ||
1390 | mNodes[n].setChild(child); | ||
1391 | } | ||
1392 | } | ||
1393 | 8872 | child->addLeafAndCache(leaf, acc); | |
1394 | 247342 | } | |
1395 | |||
1396 | |||
1397 | //////////////////////////////////////// | ||
1398 | |||
1399 | |||
1400 | template<typename ChildT, Index Log2Dim> | ||
1401 | inline bool | ||
1402 | 151160 | InternalNode<ChildT, Log2Dim>::addChild(ChildT* child) | |
1403 | { | ||
1404 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75580 times.
|
151160 | assert(child); |
1405 | const Coord& xyz = child->origin(); | ||
1406 | // verify that the child belongs in this internal node | ||
1407 | 2 | if (Coord((xyz & ~(DIM-1))) != this->origin()) return false; | |
1408 | // compute the offset and insert the child node | ||
1409 | const Index n = this->coordToOffset(xyz); | ||
1410 | // this also deletes an existing child node | ||
1411 | 151158 | this->resetChildNode(n, child); | |
1412 | 151158 | return true; | |
1413 | } | ||
1414 | |||
1415 | |||
1416 | template<typename ChildT, Index Log2Dim> | ||
1417 | inline void | ||
1418 | 646716 | InternalNode<ChildT, Log2Dim>::addTile(Index n, const ValueType& value, bool state) | |
1419 | { | ||
1420 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 323358 times.
|
646716 | assert(n < NUM_VALUES); |
1421 | 646716 | this->makeChildNodeEmpty(n, value); | |
1422 |
2/2✓ Branch 0 taken 51040 times.
✓ Branch 1 taken 272318 times.
|
646716 | mValueMask.set(n, state); |
1423 | 646716 | } | |
1424 | |||
1425 | |||
1426 | template<typename ChildT, Index Log2Dim> | ||
1427 | inline void | ||
1428 | 35504 | InternalNode<ChildT, Log2Dim>::addTile(Index level, const Coord& xyz, | |
1429 | const ValueType& value, bool state) | ||
1430 | { | ||
1431 |
1/2✓ Branch 0 taken 17752 times.
✗ Branch 1 not taken.
|
35504 | if (LEVEL >= level) { |
1432 | const Index n = this->coordToOffset(xyz); | ||
1433 |
2/2✓ Branch 0 taken 14292 times.
✓ Branch 1 taken 3460 times.
|
35504 | if (mChildMask.isOff(n)) {// tile case |
1434 |
2/2✓ Branch 0 taken 3673 times.
✓ Branch 1 taken 10619 times.
|
28584 | if (LEVEL > level) { |
1435 |
1/2✓ Branch 3 taken 94 times.
✗ Branch 4 not taken.
|
7346 | ChildT* child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n)); |
1436 | 7346 | this->setChildNode(n, child); | |
1437 | 7346 | child->addTile(level, xyz, value, state); | |
1438 | } else { | ||
1439 |
2/2✓ Branch 0 taken 10605 times.
✓ Branch 1 taken 14 times.
|
21238 | mValueMask.set(n, state); |
1440 | mNodes[n].setValue(value); | ||
1441 | } | ||
1442 | } else {// child branch case | ||
1443 | ChildT* child = mNodes[n].getChild(); | ||
1444 |
2/2✓ Branch 0 taken 3459 times.
✓ Branch 1 taken 1 times.
|
6920 | if (LEVEL > level) { |
1445 | 6918 | child->addTile(level, xyz, value, state); | |
1446 | } else { | ||
1447 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | delete child; |
1448 | 2 | mChildMask.setOff(n); | |
1449 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
2 | mValueMask.set(n, state); |
1450 | mNodes[n].setValue(value); | ||
1451 | } | ||
1452 | } | ||
1453 | } | ||
1454 | 35504 | } | |
1455 | |||
1456 | |||
1457 | template<typename ChildT, Index Log2Dim> | ||
1458 | template<typename AccessorT> | ||
1459 | inline void | ||
1460 | 14654 | InternalNode<ChildT, Log2Dim>::addTileAndCache(Index level, const Coord& xyz, | |
1461 | const ValueType& value, bool state, AccessorT& acc) | ||
1462 | { | ||
1463 |
1/2✓ Branch 0 taken 7327 times.
✗ Branch 1 not taken.
|
14654 | if (LEVEL >= level) { |
1464 | const Index n = this->coordToOffset(xyz); | ||
1465 |
2/2✓ Branch 0 taken 353 times.
✓ Branch 1 taken 6974 times.
|
14654 | if (mChildMask.isOff(n)) {// tile case |
1466 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 342 times.
|
706 | if (LEVEL > level) { |
1467 |
0/2✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
22 | ChildT* child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n)); |
1468 | 22 | this->setChildNode(n, child); | |
1469 | 22 | acc.insert(xyz, child); | |
1470 | 22 | child->addTileAndCache(level, xyz, value, state, acc); | |
1471 | } else { | ||
1472 |
1/2✓ Branch 0 taken 342 times.
✗ Branch 1 not taken.
|
684 | mValueMask.set(n, state); |
1473 | mNodes[n].setValue(value); | ||
1474 | } | ||
1475 | } else {// child branch case | ||
1476 | ChildT* child = mNodes[n].getChild(); | ||
1477 |
2/2✓ Branch 0 taken 1238 times.
✓ Branch 1 taken 5736 times.
|
13948 | if (LEVEL > level) { |
1478 | 2476 | acc.insert(xyz, child); | |
1479 | 2476 | child->addTileAndCache(level, xyz, value, state, acc); | |
1480 | } else { | ||
1481 |
1/2✓ Branch 0 taken 5736 times.
✗ Branch 1 not taken.
|
11472 | delete child; |
1482 | 11472 | mChildMask.setOff(n); | |
1483 |
1/2✓ Branch 0 taken 5736 times.
✗ Branch 1 not taken.
|
11472 | mValueMask.set(n, state); |
1484 | mNodes[n].setValue(value); | ||
1485 | } | ||
1486 | } | ||
1487 | } | ||
1488 | 14654 | } | |
1489 | |||
1490 | |||
1491 | //////////////////////////////////////// | ||
1492 | |||
1493 | |||
1494 | template<typename ChildT, Index Log2Dim> | ||
1495 | inline typename ChildT::LeafNodeType* | ||
1496 | 15760 | InternalNode<ChildT, Log2Dim>::touchLeaf(const Coord& xyz) | |
1497 | { | ||
1498 | const Index n = this->coordToOffset(xyz); | ||
1499 | ChildT* child = nullptr; | ||
1500 |
2/2✓ Branch 0 taken 3507 times.
✓ Branch 1 taken 4373 times.
|
15760 | if (mChildMask.isOff(n)) { |
1501 |
1/2✓ Branch 3 taken 83 times.
✗ Branch 4 not taken.
|
7014 | child = new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n)); |
1502 | 7014 | this->setChildNode(n, child); | |
1503 | } else { | ||
1504 | child = mNodes[n].getChild(); | ||
1505 | } | ||
1506 | 15760 | return child->touchLeaf(xyz); | |
1507 | } | ||
1508 | |||
1509 | |||
1510 | template<typename ChildT, Index Log2Dim> | ||
1511 | template<typename AccessorT> | ||
1512 | inline typename ChildT::LeafNodeType* | ||
1513 | 1027698 | InternalNode<ChildT, Log2Dim>::touchLeafAndCache(const Coord& xyz, AccessorT& acc) | |
1514 | { | ||
1515 | const Index n = this->coordToOffset(xyz); | ||
1516 |
2/2✓ Branch 0 taken 170184 times.
✓ Branch 1 taken 343665 times.
|
1027698 | if (mChildMask.isOff(n)) { |
1517 |
1/2✓ Branch 3 taken 7674 times.
✗ Branch 4 not taken.
|
340368 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), mValueMask.isOn(n))); |
1518 | } | ||
1519 | 1027698 | acc.insert(xyz, mNodes[n].getChild()); | |
1520 | 1027698 | return mNodes[n].getChild()->touchLeafAndCache(xyz, acc); | |
1521 | } | ||
1522 | |||
1523 | |||
1524 | //////////////////////////////////////// | ||
1525 | |||
1526 | |||
1527 | template<typename ChildT, Index Log2Dim> | ||
1528 | inline bool | ||
1529 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
68606 | InternalNode<ChildT, Log2Dim>::isConstant(ValueType& firstValue, bool& state, |
1530 | const ValueType& tolerance) const | ||
1531 | { | ||
1532 |
3/6✓ Branch 0 taken 32155 times.
✓ Branch 1 taken 2148 times.
✓ Branch 2 taken 32147 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
132916 | if (!mChildMask.isOff() || !mValueMask.isConstant(state)) return false;// early termination |
1533 | |||
1534 | 64272 | firstValue = mNodes[0].getValue(); | |
1535 |
2/6✓ Branch 0 taken 133849709 times.
✓ Branch 1 taken 32147 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
267763712 | for (Index i = 1; i < NUM_VALUES; ++i) { |
1536 |
2/6✓ Branch 0 taken 133403354 times.
✓ Branch 1 taken 188370 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
267183448 | if (!math::isApproxEqual(mNodes[i].getValue(), firstValue, tolerance)) { |
1537 | return false; // early termination | ||
1538 | } | ||
1539 | } | ||
1540 | return true; | ||
1541 | } | ||
1542 | |||
1543 | |||
1544 | //////////////////////////////////////// | ||
1545 | |||
1546 | |||
1547 | template<typename ChildT, Index Log2Dim> | ||
1548 | inline bool | ||
1549 |
1/2✓ Branch 0 taken 296 times.
✗ Branch 1 not taken.
|
3146 | InternalNode<ChildT, Log2Dim>::isConstant(ValueType& minValue, |
1550 | ValueType& maxValue, | ||
1551 | bool& state, | ||
1552 | const ValueType& tolerance) const | ||
1553 | { | ||
1554 | |||
1555 |
3/4✓ Branch 0 taken 316 times.
✓ Branch 1 taken 1257 times.
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
|
3186 | if (!mChildMask.isOff() || !mValueMask.isConstant(state)) return false;// early termination |
1556 | 630 | minValue = maxValue = mNodes[0].getValue(); | |
1557 |
2/2✓ Branch 0 taken 350917 times.
✓ Branch 1 taken 315 times.
|
702464 | for (Index i = 1; i < NUM_VALUES; ++i) { |
1558 | const ValueType& v = mNodes[i].getValue(); | ||
1559 |
1/3✗ Branch 0 not taken.
✓ Branch 1 taken 350917 times.
✗ Branch 2 not taken.
|
701834 | if (v < minValue) { |
1560 | ✗ | if ((maxValue - v) > tolerance) return false;// early termination | |
1561 | ✗ | minValue = v; | |
1562 |
1/3✗ Branch 0 not taken.
✓ Branch 1 taken 350917 times.
✗ Branch 2 not taken.
|
701834 | } else if (v > maxValue) { |
1563 | ✗ | if ((v - minValue) > tolerance) return false;// early termination | |
1564 | ✗ | maxValue = v; | |
1565 | } | ||
1566 | } | ||
1567 | return true; | ||
1568 | } | ||
1569 | |||
1570 | |||
1571 | //////////////////////////////////////// | ||
1572 | |||
1573 | |||
1574 | template<typename ChildT, Index Log2Dim> | ||
1575 | inline bool | ||
1576 | 18422 | InternalNode<ChildT, Log2Dim>::hasActiveTiles() const | |
1577 | { | ||
1578 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
1579 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
18949 | const bool anyActiveTiles = !mValueMask.isOff(); |
1580 |
2/2✓ Branch 0 taken 9361 times.
✓ Branch 1 taken 5 times.
|
18422 | if (LEVEL==1 || anyActiveTiles) return anyActiveTiles; |
1581 |
2/2✓ Branch 0 taken 9383 times.
✓ Branch 1 taken 6816 times.
|
31792 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { |
1582 |
2/2✓ Branch 0 taken 2545 times.
✓ Branch 1 taken 6838 times.
|
18453 | if (iter->hasActiveTiles()) return true; |
1583 | } | ||
1584 | 13339 | return false; | |
1585 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
1586 | } | ||
1587 | |||
1588 | |||
1589 | template<typename ChildT, Index Log2Dim> | ||
1590 | inline bool | ||
1591 | 126779646 | InternalNode<ChildT, Log2Dim>::isValueOn(const Coord& xyz) const | |
1592 | { | ||
1593 | const Index n = this->coordToOffset(xyz); | ||
1594 |
2/2✓ Branch 0 taken 2554922 times.
✓ Branch 1 taken 60834901 times.
|
131889490 | if (this->isChildMaskOff(n)) return this->isValueMaskOn(n); |
1595 | 121669802 | return mNodes[n].getChild()->isValueOn(xyz); | |
1596 | } | ||
1597 | |||
1598 | template<typename ChildT, Index Log2Dim> | ||
1599 | template<typename AccessorT> | ||
1600 | inline bool | ||
1601 | 501093166 | InternalNode<ChildT, Log2Dim>::isValueOnAndCache(const Coord& xyz, AccessorT& acc) const | |
1602 | { | ||
1603 | const Index n = this->coordToOffset(xyz); | ||
1604 |
2/2✓ Branch 0 taken 246271400 times.
✓ Branch 1 taken 4275183 times.
|
993635966 | if (this->isChildMaskOff(n)) return this->isValueMaskOn(n); |
1605 | 8550240 | acc.insert(xyz, mNodes[n].getChild()); | |
1606 | 8550366 | return mNodes[n].getChild()->isValueOnAndCache(xyz, acc); | |
1607 | } | ||
1608 | |||
1609 | |||
1610 | template<typename ChildT, Index Log2Dim> | ||
1611 | inline const typename ChildT::ValueType& | ||
1612 | 114326376 | InternalNode<ChildT, Log2Dim>::getValue(const Coord& xyz) const | |
1613 | { | ||
1614 | const Index n = this->coordToOffset(xyz); | ||
1615 |
2/2✓ Branch 0 taken 17301502 times.
✓ Branch 1 taken 19461938 times.
|
105703538 | return this->isChildMaskOff(n) ? mNodes[n].getValue() |
1616 |
2/2✓ Branch 0 taken 4311419 times.
✓ Branch 1 taken 16088329 times.
|
114326376 | : mNodes[n].getChild()->getValue(xyz); |
1617 | } | ||
1618 | |||
1619 | template<typename ChildT, Index Log2Dim> | ||
1620 | template<typename AccessorT> | ||
1621 | inline const typename ChildT::ValueType& | ||
1622 | 10331632662 | InternalNode<ChildT, Log2Dim>::getValueAndCache(const Coord& xyz, AccessorT& acc) const | |
1623 | { | ||
1624 | const Index n = this->coordToOffset(xyz); | ||
1625 |
2/2✓ Branch 0 taken 196770741 times.
✓ Branch 1 taken 4969045590 times.
|
10331632662 | if (this->isChildMaskOn(n)) { |
1626 | 393486194 | acc.insert(xyz, mNodes[n].getChild()); | |
1627 | 393541482 | return mNodes[n].getChild()->getValueAndCache(xyz, acc); | |
1628 | } | ||
1629 | 9938091180 | return mNodes[n].getValue(); | |
1630 | } | ||
1631 | |||
1632 | |||
1633 | template<typename ChildT, Index Log2Dim> | ||
1634 | inline Index | ||
1635 | 620218 | InternalNode<ChildT, Log2Dim>::getValueLevel(const Coord& xyz) const | |
1636 | { | ||
1637 | const Index n = this->coordToOffset(xyz); | ||
1638 |
2/2✓ Branch 0 taken 310030 times.
✓ Branch 1 taken 79 times.
|
620218 | return this->isChildMaskOff(n) ? LEVEL : mNodes[n].getChild()->getValueLevel(xyz); |
1639 | } | ||
1640 | |||
1641 | template<typename ChildT, Index Log2Dim> | ||
1642 | template<typename AccessorT> | ||
1643 | inline Index | ||
1644 | 12770174 | InternalNode<ChildT, Log2Dim>::getValueLevelAndCache(const Coord& xyz, AccessorT& acc) const | |
1645 | { | ||
1646 | const Index n = this->coordToOffset(xyz); | ||
1647 |
2/2✓ Branch 0 taken 234 times.
✓ Branch 1 taken 6384853 times.
|
12770174 | if (this->isChildMaskOn(n)) { |
1648 | 234 | acc.insert(xyz, mNodes[n].getChild()); | |
1649 | 468 | return mNodes[n].getChild()->getValueLevelAndCache(xyz, acc); | |
1650 | } | ||
1651 | return LEVEL; | ||
1652 | } | ||
1653 | |||
1654 | |||
1655 | template<typename ChildT, Index Log2Dim> | ||
1656 | inline bool | ||
1657 | 639002 | InternalNode<ChildT, Log2Dim>::probeValue(const Coord& xyz, ValueType& value) const | |
1658 | { | ||
1659 | const Index n = this->coordToOffset(xyz); | ||
1660 |
2/2✓ Branch 0 taken 311415 times.
✓ Branch 1 taken 8086 times.
|
639002 | if (this->isChildMaskOff(n)) { |
1661 | 622830 | value = mNodes[n].getValue(); | |
1662 | 622830 | return this->isValueMaskOn(n); | |
1663 | } | ||
1664 | 16172 | return mNodes[n].getChild()->probeValue(xyz, value); | |
1665 | } | ||
1666 | |||
1667 | template<typename ChildT, Index Log2Dim> | ||
1668 | template<typename AccessorT> | ||
1669 | inline bool | ||
1670 | 2617807248 | InternalNode<ChildT, Log2Dim>::probeValueAndCache(const Coord& xyz, | |
1671 | ValueType& value, AccessorT& acc) const | ||
1672 | { | ||
1673 | const Index n = this->coordToOffset(xyz); | ||
1674 |
2/2✓ Branch 0 taken 148297750 times.
✓ Branch 1 taken 1160605874 times.
|
2617807248 | if (this->isChildMaskOn(n)) { |
1675 | 296595500 | acc.insert(xyz, mNodes[n].getChild()); | |
1676 | 296595500 | return mNodes[n].getChild()->probeValueAndCache(xyz, value, acc); | |
1677 | } | ||
1678 | 2321211544 | value = mNodes[n].getValue(); | |
1679 | 2321211748 | return this->isValueMaskOn(n); | |
1680 | } | ||
1681 | |||
1682 | |||
1683 | template<typename ChildT, Index Log2Dim> | ||
1684 | inline void | ||
1685 | 136 | InternalNode<ChildT, Log2Dim>::setValueOff(const Coord& xyz) | |
1686 | { | ||
1687 | const Index n = this->coordToOffset(xyz); | ||
1688 | bool hasChild = this->isChildMaskOn(n); | ||
1689 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
140 | if (!hasChild && this->isValueMaskOn(n)) { |
1690 | // If the voxel belongs to a constant tile that is active, | ||
1691 | // a child subtree must be constructed. | ||
1692 | hasChild = true; | ||
1693 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
6 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), /*active=*/true)); |
1694 | } | ||
1695 |
1/2✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
|
136 | if (hasChild) mNodes[n].getChild()->setValueOff(xyz); |
1696 | 136 | } | |
1697 | |||
1698 | |||
1699 | template<typename ChildT, Index Log2Dim> | ||
1700 | inline void | ||
1701 | InternalNode<ChildT, Log2Dim>::setValueOn(const Coord& xyz) | ||
1702 | { | ||
1703 | const Index n = this->coordToOffset(xyz); | ||
1704 | bool hasChild = this->isChildMaskOn(n); | ||
1705 | if (!hasChild && !this->isValueMaskOn(n)) { | ||
1706 | // If the voxel belongs to a constant tile that is inactive, | ||
1707 | // a child subtree must be constructed. | ||
1708 | hasChild = true; | ||
1709 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), /*active=*/false)); | ||
1710 | } | ||
1711 | if (hasChild) mNodes[n].getChild()->setValueOn(xyz); | ||
1712 | } | ||
1713 | |||
1714 | |||
1715 | template<typename ChildT, Index Log2Dim> | ||
1716 | inline void | ||
1717 | 648 | InternalNode<ChildT, Log2Dim>::setValueOff(const Coord& xyz, const ValueType& value) | |
1718 | { | ||
1719 | const Index n = InternalNode::coordToOffset(xyz); | ||
1720 | bool hasChild = this->isChildMaskOn(n); | ||
1721 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 284 times.
|
648 | if (!hasChild) { |
1722 | const bool active = this->isValueMaskOn(n); | ||
1723 |
3/4✓ Branch 0 taken 38 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
|
80 | if (active || !math::isExactlyEqual(mNodes[n].getValue(), value)) { |
1724 | // If the voxel belongs to a tile that is either active or that | ||
1725 | // has a constant value that is different from the one provided, | ||
1726 | // a child subtree must be constructed. | ||
1727 | hasChild = true; | ||
1728 |
1/2✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
|
82 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
1729 | } | ||
1730 | } | ||
1731 |
1/2✓ Branch 0 taken 284 times.
✗ Branch 1 not taken.
|
648 | if (hasChild) mNodes[n].getChild()->setValueOff(xyz, value); |
1732 | 648 | } | |
1733 | |||
1734 | template<typename ChildT, Index Log2Dim> | ||
1735 | template<typename AccessorT> | ||
1736 | inline void | ||
1737 | 478163502 | InternalNode<ChildT, Log2Dim>::setValueOffAndCache(const Coord& xyz, | |
1738 | const ValueType& value, AccessorT& acc) | ||
1739 | { | ||
1740 | const Index n = InternalNode::coordToOffset(xyz); | ||
1741 | bool hasChild = this->isChildMaskOn(n); | ||
1742 |
2/2✓ Branch 0 taken 239017631 times.
✓ Branch 1 taken 64120 times.
|
478163502 | if (!hasChild) { |
1743 | const bool active = this->isValueMaskOn(n); | ||
1744 |
3/4✓ Branch 0 taken 239017631 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 911 times.
✓ Branch 3 taken 188264252 times.
|
478035262 | if (active || !math::isExactlyEqual(mNodes[n].getValue(), value)) { |
1745 | // If the voxel belongs to a tile that is either active or that | ||
1746 | // has a constant value that is different from the one provided, | ||
1747 | // a child subtree must be constructed. | ||
1748 | hasChild = true; | ||
1749 |
1/2✓ Branch 2 taken 925 times.
✗ Branch 3 not taken.
|
1982 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
1750 | } | ||
1751 | } | ||
1752 |
2/2✓ Branch 0 taken 64120 times.
✓ Branch 1 taken 239016640 times.
|
478161520 | if (hasChild) { |
1753 | ChildT* child = mNodes[n].getChild(); | ||
1754 | 130222 | acc.insert(xyz, child); | |
1755 | 132 | child->setValueOffAndCache(xyz, value, acc); | |
1756 | } | ||
1757 | 478163502 | } | |
1758 | |||
1759 | |||
1760 | template<typename ChildT, Index Log2Dim> | ||
1761 | inline void | ||
1762 | 1266024 | InternalNode<ChildT, Log2Dim>::setValueOn(const Coord& xyz, const ValueType& value) | |
1763 | { | ||
1764 | const Index n = this->coordToOffset(xyz); | ||
1765 | bool hasChild = this->isChildMaskOn(n); | ||
1766 |
2/2✓ Branch 0 taken 127912 times.
✓ Branch 1 taken 505100 times.
|
1266024 | if (!hasChild) { |
1767 | const bool active = this->isValueMaskOn(n); // tile's active state | ||
1768 |
3/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 127900 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
255824 | if (!active || !math::isExactlyEqual(mNodes[n].getValue(), value)) { |
1769 | // If the voxel belongs to a tile that is either inactive or that | ||
1770 | // has a constant value that is different from the one provided, | ||
1771 | // a child subtree must be constructed. | ||
1772 | hasChild = true; | ||
1773 |
1/2✓ Branch 2 taken 98467 times.
✗ Branch 3 not taken.
|
287128 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
1774 | } | ||
1775 | } | ||
1776 |
1/2✓ Branch 0 taken 505100 times.
✗ Branch 1 not taken.
|
1266024 | if (hasChild) mNodes[n].getChild()->setValueOn(xyz, value); |
1777 | 1266024 | } | |
1778 | |||
1779 | template<typename ChildT, Index Log2Dim> | ||
1780 | template<typename AccessorT> | ||
1781 | inline void | ||
1782 | 43143130 | InternalNode<ChildT, Log2Dim>::setValueAndCache(const Coord& xyz, | |
1783 | const ValueType& value, AccessorT& acc) | ||
1784 | { | ||
1785 | const Index n = this->coordToOffset(xyz); | ||
1786 | bool hasChild = this->isChildMaskOn(n); | ||
1787 |
2/2✓ Branch 0 taken 478865 times.
✓ Branch 1 taken 21092700 times.
|
43143130 | if (!hasChild) { |
1788 | const bool active = this->isValueMaskOn(n); | ||
1789 |
3/4✓ Branch 0 taken 246 times.
✓ Branch 1 taken 478619 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 246 times.
|
957730 | if (!active || !math::isExactlyEqual(mNodes[n].getValue(), value)) { |
1790 | // If the voxel belongs to a tile that is either inactive or that | ||
1791 | // has a constant value that is different from the one provided, | ||
1792 | // a child subtree must be constructed. | ||
1793 | hasChild = true; | ||
1794 |
1/2✓ Branch 2 taken 439025 times.
✗ Branch 3 not taken.
|
1019738 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
1795 | } | ||
1796 | } | ||
1797 |
2/2✓ Branch 0 taken 21092700 times.
✓ Branch 1 taken 246 times.
|
42185892 | if (hasChild) { |
1798 | 43127900 | acc.insert(xyz, mNodes[n].getChild()); | |
1799 | 11704886 | mNodes[n].getChild()->setValueAndCache(xyz, value, acc); | |
1800 | } | ||
1801 | 43143130 | } | |
1802 | |||
1803 | |||
1804 | template<typename ChildT, Index Log2Dim> | ||
1805 | inline void | ||
1806 | 64 | InternalNode<ChildT, Log2Dim>::setValueOnly(const Coord& xyz, const ValueType& value) | |
1807 | { | ||
1808 | const Index n = this->coordToOffset(xyz); | ||
1809 | bool hasChild = this->isChildMaskOn(n); | ||
1810 |
3/4✓ Branch 0 taken 20 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
64 | if (!hasChild && !math::isExactlyEqual(mNodes[n].getValue(), value)) { |
1811 | // If the voxel has a tile value that is different from the one provided, | ||
1812 | // a child subtree must be constructed. | ||
1813 | const bool active = this->isValueMaskOn(n); | ||
1814 | hasChild = true; | ||
1815 |
1/2✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
|
40 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
1816 | } | ||
1817 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
64 | if (hasChild) mNodes[n].getChild()->setValueOnly(xyz, value); |
1818 | 64 | } | |
1819 | |||
1820 | template<typename ChildT, Index Log2Dim> | ||
1821 | template<typename AccessorT> | ||
1822 | inline void | ||
1823 | 89196 | InternalNode<ChildT, Log2Dim>::setValueOnlyAndCache(const Coord& xyz, | |
1824 | const ValueType& value, AccessorT& acc) | ||
1825 | { | ||
1826 | const Index n = this->coordToOffset(xyz); | ||
1827 | bool hasChild = this->isChildMaskOn(n); | ||
1828 |
3/4✓ Branch 0 taken 25129 times.
✓ Branch 1 taken 19469 times.
✓ Branch 2 taken 25129 times.
✗ Branch 3 not taken.
|
89196 | if (!hasChild && !math::isExactlyEqual(mNodes[n].getValue(), value)) { |
1829 | // If the voxel has a tile value that is different from the one provided, | ||
1830 | // a child subtree must be constructed. | ||
1831 | const bool active = this->isValueMaskOn(n); | ||
1832 | hasChild = true; | ||
1833 |
1/2✓ Branch 2 taken 23815 times.
✗ Branch 3 not taken.
|
50258 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
1834 | } | ||
1835 |
1/2✓ Branch 0 taken 19469 times.
✗ Branch 1 not taken.
|
38938 | if (hasChild) { |
1836 | 89196 | acc.insert(xyz, mNodes[n].getChild()); | |
1837 | 6984 | mNodes[n].getChild()->setValueOnlyAndCache(xyz, value, acc); | |
1838 | } | ||
1839 | } | ||
1840 | |||
1841 | |||
1842 | template<typename ChildT, Index Log2Dim> | ||
1843 | inline void | ||
1844 | 132 | InternalNode<ChildT, Log2Dim>::setActiveState(const Coord& xyz, bool on) | |
1845 | { | ||
1846 | const Index n = this->coordToOffset(xyz); | ||
1847 | bool hasChild = this->isChildMaskOn(n); | ||
1848 |
2/2✓ Branch 0 taken 50 times.
✓ Branch 1 taken 16 times.
|
132 | if (!hasChild) { |
1849 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 2 times.
|
100 | if (on != this->isValueMaskOn(n)) { |
1850 | // If the voxel belongs to a tile with the wrong active state, | ||
1851 | // then a child subtree must be constructed. | ||
1852 | // 'on' is the voxel's new state, therefore '!on' is the tile's current state | ||
1853 | hasChild = true; | ||
1854 |
1/2✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
98 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), !on)); |
1855 | } | ||
1856 | } | ||
1857 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
|
132 | if (hasChild) mNodes[n].getChild()->setActiveState(xyz, on); |
1858 | 132 | } | |
1859 | |||
1860 | template<typename ChildT, Index Log2Dim> | ||
1861 | template<typename AccessorT> | ||
1862 | inline void | ||
1863 | 23142398 | InternalNode<ChildT, Log2Dim>::setActiveStateAndCache(const Coord& xyz, bool on, AccessorT& acc) | |
1864 | { | ||
1865 | const Index n = this->coordToOffset(xyz); | ||
1866 | bool hasChild = this->isChildMaskOn(n); | ||
1867 |
2/2✓ Branch 0 taken 1340532 times.
✓ Branch 1 taken 10230667 times.
|
23142398 | if (!hasChild) { |
1868 |
1/2✓ Branch 0 taken 1340532 times.
✗ Branch 1 not taken.
|
2681064 | if (on != this->isValueMaskOn(n)) { |
1869 | // If the voxel belongs to a tile with the wrong active state, | ||
1870 | // then a child subtree must be constructed. | ||
1871 | // 'on' is the voxel's new state, therefore '!on' is the tile's current state | ||
1872 | hasChild = true; | ||
1873 |
1/2✓ Branch 2 taken 1269 times.
✗ Branch 3 not taken.
|
2681064 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), !on)); |
1874 | } | ||
1875 | } | ||
1876 |
1/2✓ Branch 0 taken 10230667 times.
✗ Branch 1 not taken.
|
20461334 | if (hasChild) { |
1877 | ChildT* child = mNodes[n].getChild(); | ||
1878 | 23142398 | acc.insert(xyz, child); | |
1879 | 23142398 | child->setActiveStateAndCache(xyz, on, acc); | |
1880 | } | ||
1881 | 23142398 | } | |
1882 | |||
1883 | |||
1884 | template<typename ChildT, Index Log2Dim> | ||
1885 | inline void | ||
1886 | 20 | InternalNode<ChildT, Log2Dim>::setValuesOn() | |
1887 | { | ||
1888 | 20 | mValueMask = !mChildMask; | |
1889 |
2/2✓ Branch 0 taken 2729 times.
✓ Branch 1 taken 10 times.
|
5478 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
1890 | 4 | mNodes[iter.pos()].getChild()->setValuesOn(); | |
1891 | } | ||
1892 | } | ||
1893 | |||
1894 | |||
1895 | template<typename ChildT, Index Log2Dim> | ||
1896 | template<typename ModifyOp> | ||
1897 | inline void | ||
1898 | 26 | InternalNode<ChildT, Log2Dim>::modifyValue(const Coord& xyz, const ModifyOp& op) | |
1899 | { | ||
1900 | const Index n = InternalNode::coordToOffset(xyz); | ||
1901 | bool hasChild = this->isChildMaskOn(n); | ||
1902 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 8 times.
|
26 | if (!hasChild) { |
1903 | // Need to create a child if the tile is inactive, | ||
1904 | // in order to activate voxel (x, y, z). | ||
1905 | const bool active = this->isValueMaskOn(n); | ||
1906 | 10 | bool createChild = !active; | |
1907 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
10 | if (!createChild) { |
1908 | // Need to create a child if applying the functor | ||
1909 | // to the tile value produces a different value. | ||
1910 | const ValueType& tileVal = mNodes[n].getValue(); | ||
1911 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
10 | ValueType modifiedVal = tileVal; |
1912 | op(modifiedVal); | ||
1913 | 10 | createChild = !math::isExactlyEqual(tileVal, modifiedVal); | |
1914 | } | ||
1915 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
|
10 | if (createChild) { |
1916 | hasChild = true; | ||
1917 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
12 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
1918 | } | ||
1919 | } | ||
1920 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
|
26 | if (hasChild) mNodes[n].getChild()->modifyValue(xyz, op); |
1921 | 26 | } | |
1922 | |||
1923 | template<typename ChildT, Index Log2Dim> | ||
1924 | template<typename ModifyOp, typename AccessorT> | ||
1925 | inline void | ||
1926 | 266527302 | InternalNode<ChildT, Log2Dim>::modifyValueAndCache(const Coord& xyz, const ModifyOp& op, | |
1927 | AccessorT& acc) | ||
1928 | { | ||
1929 | const Index n = InternalNode::coordToOffset(xyz); | ||
1930 | bool hasChild = this->isChildMaskOn(n); | ||
1931 |
2/2✓ Branch 0 taken 16868 times.
✓ Branch 1 taken 133246783 times.
|
266527302 | if (!hasChild) { |
1932 | // Need to create a child if the tile is inactive, | ||
1933 | // in order to activate voxel (x, y, z). | ||
1934 | const bool active = this->isValueMaskOn(n); | ||
1935 | 33736 | bool createChild = !active; | |
1936 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16868 times.
|
33736 | if (!createChild) { |
1937 | // Need to create a child if applying the functor | ||
1938 | // to the tile value produces a different value. | ||
1939 | const ValueType& tileVal = mNodes[n].getValue(); | ||
1940 | ✗ | ValueType modifiedVal = tileVal; | |
1941 | op(modifiedVal); | ||
1942 | ✗ | createChild = !math::isExactlyEqual(tileVal, modifiedVal); | |
1943 | } | ||
1944 |
1/2✓ Branch 0 taken 16868 times.
✗ Branch 1 not taken.
|
33736 | if (createChild) { |
1945 | hasChild = true; | ||
1946 |
1/2✓ Branch 2 taken 16489 times.
✗ Branch 3 not taken.
|
33736 | this->setChildNode(n, new ChildNodeType(xyz, mNodes[n].getValue(), active)); |
1947 | } | ||
1948 | } | ||
1949 |
1/2✓ Branch 0 taken 133246783 times.
✗ Branch 1 not taken.
|
266493566 | if (hasChild) { |
1950 | ChildNodeType* child = mNodes[n].getChild(); | ||
1951 | 266527302 | acc.insert(xyz, child); | |
1952 | 34772582 | child->modifyValueAndCache(xyz, op, acc); | |
1953 | } | ||
1954 | } | ||
1955 | |||
1956 | |||
1957 | template<typename ChildT, Index Log2Dim> | ||
1958 | template<typename ModifyOp> | ||
1959 | inline void | ||
1960 | 16 | InternalNode<ChildT, Log2Dim>::modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op) | |
1961 | { | ||
1962 | const Index n = InternalNode::coordToOffset(xyz); | ||
1963 | bool hasChild = this->isChildMaskOn(n); | ||
1964 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
16 | if (!hasChild) { |
1965 | const bool tileState = this->isValueMaskOn(n); | ||
1966 | const ValueType& tileVal = mNodes[n].getValue(); | ||
1967 | ✗ | bool modifiedState = !tileState; | |
1968 | ✗ | ValueType modifiedVal = tileVal; | |
1969 | ✗ | op(modifiedVal, modifiedState); | |
1970 | // Need to create a child if applying the functor to the tile | ||
1971 | // produces a different value or active state. | ||
1972 | ✗ | if (modifiedState != tileState || !math::isExactlyEqual(modifiedVal, tileVal)) { | |
1973 | hasChild = true; | ||
1974 | ✗ | this->setChildNode(n, new ChildNodeType(xyz, tileVal, tileState)); | |
1975 | } | ||
1976 | } | ||
1977 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
16 | if (hasChild) mNodes[n].getChild()->modifyValueAndActiveState(xyz, op); |
1978 | 16 | } | |
1979 | |||
1980 | template<typename ChildT, Index Log2Dim> | ||
1981 | template<typename ModifyOp, typename AccessorT> | ||
1982 | inline void | ||
1983 | ✗ | InternalNode<ChildT, Log2Dim>::modifyValueAndActiveStateAndCache( | |
1984 | const Coord& xyz, const ModifyOp& op, AccessorT& acc) | ||
1985 | { | ||
1986 | const Index n = InternalNode::coordToOffset(xyz); | ||
1987 | bool hasChild = this->isChildMaskOn(n); | ||
1988 | ✗ | if (!hasChild) { | |
1989 | const bool tileState = this->isValueMaskOn(n); | ||
1990 | const ValueType& tileVal = mNodes[n].getValue(); | ||
1991 | bool modifiedState = !tileState; | ||
1992 | ✗ | ValueType modifiedVal = tileVal; | |
1993 | op(modifiedVal, modifiedState); | ||
1994 | // Need to create a child if applying the functor to the tile | ||
1995 | // produces a different value or active state. | ||
1996 | ✗ | if (modifiedState != tileState || !math::isExactlyEqual(modifiedVal, tileVal)) { | |
1997 | hasChild = true; | ||
1998 | ✗ | this->setChildNode(n, new ChildNodeType(xyz, tileVal, tileState)); | |
1999 | } | ||
2000 | } | ||
2001 | ✗ | if (hasChild) { | |
2002 | ChildNodeType* child = mNodes[n].getChild(); | ||
2003 | ✗ | acc.insert(xyz, child); | |
2004 | ✗ | child->modifyValueAndActiveStateAndCache(xyz, op, acc); | |
2005 | } | ||
2006 | } | ||
2007 | |||
2008 | |||
2009 | //////////////////////////////////////// | ||
2010 | |||
2011 | |||
2012 | template<typename ChildT, Index Log2Dim> | ||
2013 | inline void | ||
2014 | 194 | InternalNode<ChildT, Log2Dim>::clip(const CoordBBox& clipBBox, const ValueType& background) | |
2015 | { | ||
2016 | 194 | CoordBBox nodeBBox = this->getNodeBoundingBox(); | |
2017 | if (!clipBBox.hasOverlap(nodeBBox)) { | ||
2018 | // This node lies completely outside the clipping region. Fill it with background tiles. | ||
2019 | 72 | this->fill(nodeBBox, background, /*active=*/false); | |
2020 | } else if (clipBBox.isInside(nodeBBox)) { | ||
2021 | // This node lies completely inside the clipping region. Leave it intact. | ||
2022 | ✗ | return; | |
2023 | } | ||
2024 | |||
2025 | // This node isn't completely contained inside the clipping region. | ||
2026 | // Clip tiles and children, and replace any that lie outside the region | ||
2027 | // with background tiles. | ||
2028 | |||
2029 |
2/2✓ Branch 0 taken 1687552 times.
✓ Branch 1 taken 97 times.
|
3375298 | for (Index pos = 0; pos < NUM_VALUES; ++pos) { |
2030 | 3375104 | const Coord xyz = this->offsetToGlobalCoord(pos); // tile or child origin | |
2031 |
2/2✓ Branch 0 taken 487168 times.
✓ Branch 1 taken 1200384 times.
|
3375104 | CoordBBox tileBBox(xyz, xyz.offsetBy(ChildT::DIM - 1)); // tile or child bounds |
2032 | if (!clipBBox.hasOverlap(tileBBox)) { | ||
2033 | // This table entry lies completely outside the clipping region. | ||
2034 | // Replace it with a background tile. | ||
2035 | 3374940 | this->makeChildNodeEmpty(pos, background); | |
2036 | 3374940 | mValueMask.setOff(pos); | |
2037 | } else if (!clipBBox.isInside(tileBBox)) { | ||
2038 | // This table entry does not lie completely inside the clipping region | ||
2039 | // and must be clipped. | ||
2040 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 25 times.
|
158 | if (this->isChildMaskOn(pos)) { |
2041 | 108 | mNodes[pos].getChild()->clip(clipBBox, background); | |
2042 | } else { | ||
2043 | // Replace this tile with a background tile, then fill the clip region | ||
2044 | // with the tile's original value. (This might create a child branch.) | ||
2045 | 50 | tileBBox.intersect(clipBBox); | |
2046 | 50 | const ValueType val = mNodes[pos].getValue(); | |
2047 | const bool on = this->isValueMaskOn(pos); | ||
2048 | mNodes[pos].setValue(background); | ||
2049 | 50 | mValueMask.setOff(pos); | |
2050 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
50 | this->fill(tileBBox, val, on); |
2051 | } | ||
2052 | } else { | ||
2053 | // This table entry lies completely inside the clipping region. Leave it intact. | ||
2054 | } | ||
2055 | } | ||
2056 | } | ||
2057 | |||
2058 | |||
2059 | //////////////////////////////////////// | ||
2060 | |||
2061 | |||
2062 | template<typename ChildT, Index Log2Dim> | ||
2063 | inline void | ||
2064 | 30036 | InternalNode<ChildT, Log2Dim>::fill(const CoordBBox& bbox, const ValueType& value, bool active) | |
2065 | { | ||
2066 | 30036 | auto clippedBBox = this->getNodeBoundingBox(); | |
2067 | 30036 | clippedBBox.intersect(bbox); | |
2068 | ✗ | if (!clippedBBox) return; | |
2069 | |||
2070 | // Iterate over the fill region in axis-aligned, tile-sized chunks. | ||
2071 | // (The first and last chunks along each axis might be smaller than a tile.) | ||
2072 | Coord xyz, tileMin, tileMax; | ||
2073 |
2/2✓ Branch 0 taken 40090 times.
✓ Branch 1 taken 15018 times.
|
110216 | for (int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.x() + 1) { |
2074 | xyz.setX(x); | ||
2075 |
2/2✓ Branch 0 taken 318163 times.
✓ Branch 1 taken 40090 times.
|
716506 | for (int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.y() + 1) { |
2076 | xyz.setY(y); | ||
2077 |
2/2✓ Branch 0 taken 4160096 times.
✓ Branch 1 taken 318163 times.
|
8956518 | for (int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.z() + 1) { |
2078 | xyz.setZ(z); | ||
2079 | |||
2080 | // Get the bounds of the tile that contains voxel (x, y, z). | ||
2081 | const Index n = this->coordToOffset(xyz); | ||
2082 | 8320192 | tileMin = this->offsetToGlobalCoord(n); | |
2083 |
2/2✓ Branch 0 taken 4146735 times.
✓ Branch 1 taken 13361 times.
|
8320192 | tileMax = tileMin.offsetBy(ChildT::DIM - 1); |
2084 | |||
2085 | if (xyz != tileMin || Coord::lessThan(clippedBBox.max(), tileMax)) { | ||
2086 | // If the box defined by (xyz, clippedBBox.max()) doesn't completely enclose | ||
2087 | // the tile to which xyz belongs, create a child node (or retrieve | ||
2088 | // the existing one). | ||
2089 | ChildT* child = nullptr; | ||
2090 |
2/2✓ Branch 0 taken 400627 times.
✓ Branch 1 taken 14087 times.
|
829428 | if (this->isChildMaskOff(n)) { |
2091 | // Replace the tile with a newly-created child that is initialized | ||
2092 | // with the tile's value and active state. | ||
2093 |
1/2✓ Branch 2 taken 146660 times.
✗ Branch 3 not taken.
|
801254 | child = new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)}; |
2094 | 801254 | this->setChildNode(n, child); | |
2095 | } else { | ||
2096 | child = mNodes[n].getChild(); | ||
2097 | } | ||
2098 | |||
2099 | // Forward the fill request to the child. | ||
2100 |
1/2✓ Branch 0 taken 414714 times.
✗ Branch 1 not taken.
|
829428 | if (child) { |
2101 | 829428 | const Coord tmp = Coord::minComponent(clippedBBox.max(), tileMax); | |
2102 | 829428 | child->fill(CoordBBox(xyz, tmp), value, active); | |
2103 | } | ||
2104 | |||
2105 | } else { | ||
2106 | // If the box given by (xyz, clippedBBox.max()) completely encloses | ||
2107 | // the tile to which xyz belongs, create the tile (if it | ||
2108 | // doesn't already exist) and give it the fill value. | ||
2109 | 7490764 | this->makeChildNodeEmpty(n, value); | |
2110 |
2/2✓ Branch 0 taken 3019088 times.
✓ Branch 1 taken 726294 times.
|
7490764 | mValueMask.set(n, active); |
2111 | } | ||
2112 | } | ||
2113 | } | ||
2114 | } | ||
2115 | } | ||
2116 | |||
2117 | |||
2118 | template<typename ChildT, Index Log2Dim> | ||
2119 | inline void | ||
2120 | 416 | InternalNode<ChildT, Log2Dim>::denseFill(const CoordBBox& bbox, const ValueType& value, bool active) | |
2121 | { | ||
2122 | 416 | auto clippedBBox = this->getNodeBoundingBox(); | |
2123 | 416 | clippedBBox.intersect(bbox); | |
2124 | ✗ | if (!clippedBBox) return; | |
2125 | |||
2126 | // Iterate over the fill region in axis-aligned, tile-sized chunks. | ||
2127 | // (The first and last chunks along each axis might be smaller than a tile.) | ||
2128 | Coord xyz, tileMin, tileMax; | ||
2129 |
2/2✓ Branch 0 taken 1012 times.
✓ Branch 1 taken 408 times.
|
1440 | for (int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.x() + 1) { |
2130 | xyz.setX(x); | ||
2131 |
2/2✓ Branch 0 taken 3224 times.
✓ Branch 1 taken 1012 times.
|
4272 | for (int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.y() + 1) { |
2132 | xyz.setY(y); | ||
2133 |
2/2✓ Branch 0 taken 11924 times.
✓ Branch 1 taken 3224 times.
|
15256 | for (int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.z() + 1) { |
2134 | xyz.setZ(z); | ||
2135 | |||
2136 | // Get the table index of the tile that contains voxel (x, y, z). | ||
2137 | const auto n = this->coordToOffset(xyz); | ||
2138 | |||
2139 | // Retrieve the child node at index n, or replace the tile at index n with a child. | ||
2140 | ChildT* child = nullptr; | ||
2141 |
2/2✓ Branch 0 taken 66 times.
✓ Branch 1 taken 11858 times.
|
12008 | if (this->isChildMaskOn(n)) { |
2142 | child = mNodes[n].getChild(); | ||
2143 | } else { | ||
2144 | // Replace the tile with a newly-created child that is filled | ||
2145 | // with the tile's value and active state. | ||
2146 |
1/2✓ Branch 2 taken 11858 times.
✗ Branch 3 not taken.
|
11876 | child = new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)}; |
2147 | 11876 | this->setChildNode(n, child); | |
2148 | } | ||
2149 | |||
2150 | // Get the bounds of the tile that contains voxel (x, y, z). | ||
2151 | 12008 | tileMin = this->offsetToGlobalCoord(n); | |
2152 | 12008 | tileMax = tileMin.offsetBy(ChildT::DIM - 1); | |
2153 | |||
2154 | // Forward the fill request to the child. | ||
2155 | 12008 | child->denseFill(CoordBBox{xyz, clippedBBox.max()}, value, active); | |
2156 | } | ||
2157 | } | ||
2158 | } | ||
2159 | } | ||
2160 | |||
2161 | |||
2162 | //////////////////////////////////////// | ||
2163 | |||
2164 | |||
2165 | template<typename ChildT, Index Log2Dim> | ||
2166 | template<typename DenseT> | ||
2167 | inline void | ||
2168 | 4956 | InternalNode<ChildT, Log2Dim>::copyToDense(const CoordBBox& bbox, DenseT& dense) const | |
2169 | { | ||
2170 | using DenseValueType = typename DenseT::ValueType; | ||
2171 | |||
2172 | const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride(); | ||
2173 | const Coord& min = dense.bbox().min(); | ||
2174 |
2/2✓ Branch 0 taken 3040 times.
✓ Branch 1 taken 2478 times.
|
11036 | for (Coord xyz = bbox.min(), max; xyz[0] <= bbox.max()[0]; xyz[0] = max[0] + 1) { |
2175 |
2/2✓ Branch 0 taken 4137 times.
✓ Branch 1 taken 3040 times.
|
14354 | for (xyz[1] = bbox.min()[1]; xyz[1] <= bbox.max()[1]; xyz[1] = max[1] + 1) { |
2176 |
2/2✓ Branch 0 taken 5443 times.
✓ Branch 1 taken 4137 times.
|
19160 | for (xyz[2] = bbox.min()[2]; xyz[2] <= bbox.max()[2]; xyz[2] = max[2] + 1) { |
2177 | const Index n = this->coordToOffset(xyz); | ||
2178 | // Get max coordinates of the child node that contains voxel xyz. | ||
2179 | 10886 | max = this->offsetToGlobalCoord(n).offsetBy(ChildT::DIM-1); | |
2180 | |||
2181 | // Get the bbox of the interection of bbox and the child node | ||
2182 | 10886 | CoordBBox sub(xyz, Coord::minComponent(bbox.max(), max)); | |
2183 | |||
2184 |
2/2✓ Branch 0 taken 4306 times.
✓ Branch 1 taken 1137 times.
|
10886 | if (this->isChildMaskOn(n)) {//is a child |
2185 | 8612 | mNodes[n].getChild()->copyToDense(sub, dense); | |
2186 | } else {//a tile value | ||
2187 | 2274 | const ValueType value = mNodes[n].getValue(); | |
2188 | sub.translate(-min); | ||
2189 | 2274 | DenseValueType* a0 = dense.data() + zStride*sub.min()[2]; | |
2190 |
2/2✓ Branch 0 taken 4023 times.
✓ Branch 1 taken 1137 times.
|
10320 | for (Int32 x=sub.min()[0], ex=sub.max()[0]+1; x<ex; ++x) { |
2191 | 8046 | DenseValueType* a1 = a0 + x*xStride; | |
2192 |
2/2✓ Branch 0 taken 14253 times.
✓ Branch 1 taken 4023 times.
|
36552 | for (Int32 y=sub.min()[1], ey=sub.max()[1]+1; y<ey; ++y) { |
2193 | 28506 | DenseValueType* a2 = a1 + y*yStride; | |
2194 | 28506 | for (Int32 z = sub.min()[2], ez = sub.max()[2]+1; | |
2195 |
2/2✓ Branch 0 taken 42274 times.
✓ Branch 1 taken 14253 times.
|
113054 | z < ez; ++z, a2 += zStride) |
2196 | { | ||
2197 | 84548 | *a2 = DenseValueType(value); | |
2198 | } | ||
2199 | } | ||
2200 | } | ||
2201 | } | ||
2202 | } | ||
2203 | } | ||
2204 | } | ||
2205 | 4956 | } | |
2206 | |||
2207 | |||
2208 | //////////////////////////////////////// | ||
2209 | |||
2210 | |||
2211 | template<typename ChildT, Index Log2Dim> | ||
2212 | inline void | ||
2213 | 1012 | InternalNode<ChildT, Log2Dim>::writeTopology(std::ostream& os, bool toHalf) const | |
2214 | { | ||
2215 | mChildMask.save(os); | ||
2216 | mValueMask.save(os); | ||
2217 | |||
2218 | { | ||
2219 | // Copy all of this node's values into an array. | ||
2220 |
2/2✓ Branch 1 taken 1806336 times.
✓ Branch 2 taken 98 times.
|
3613684 | std::unique_ptr<ValueType[]> valuePtr(new ValueType[NUM_VALUES]); |
2221 | ValueType* values = valuePtr.get(); | ||
2222 | 196 | const ValueType zero = zeroVal<ValueType>(); | |
2223 |
2/2✓ Branch 0 taken 9226240 times.
✓ Branch 1 taken 506 times.
|
18453492 | for (Index i = 0; i < NUM_VALUES; ++i) { |
2224 |
2/4✓ Branch 1 taken 9198097 times.
✓ Branch 2 taken 28143 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
22056398 | values[i] = (mChildMask.isOff(i) ? mNodes[i].getValue() : zero); |
2225 | } | ||
2226 | // Compress (optionally) and write out the contents of the array. | ||
2227 |
1/2✓ Branch 1 taken 506 times.
✗ Branch 2 not taken.
|
1012 | io::writeCompressedValues(os, values, NUM_VALUES, mValueMask, mChildMask, toHalf); |
2228 | } | ||
2229 | // Write out the child nodes in order. | ||
2230 |
2/2✓ Branch 0 taken 28143 times.
✓ Branch 1 taken 506 times.
|
57298 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { |
2231 | 512 | iter->writeTopology(os, toHalf); | |
2232 | } | ||
2233 | } | ||
2234 | |||
2235 | |||
2236 | template<typename ChildT, Index Log2Dim> | ||
2237 | inline void | ||
2238 | 1010 | InternalNode<ChildT, Log2Dim>::readTopology(std::istream& is, bool fromHalf) | |
2239 | { | ||
2240 |
2/2✓ Branch 1 taken 303 times.
✓ Branch 2 taken 202 times.
|
2020 | const ValueType background = (!io::getGridBackgroundValuePtr(is) ? zeroVal<ValueType>() |
2241 | 1010 | : *static_cast<const ValueType*>(io::getGridBackgroundValuePtr(is))); | |
2242 | |||
2243 | mChildMask.load(is); | ||
2244 | mValueMask.load(is); | ||
2245 | |||
2246 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 505 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
1010 | if (io::getFormatVersion(is) < OPENVDB_FILE_VERSION_INTERNALNODE_COMPRESSION) { |
2247 | ✗ | for (Index i = 0; i < NUM_VALUES; ++i) { | |
2248 | ✗ | if (this->isChildMaskOn(i)) { | |
2249 | ✗ | ChildNodeType* child = | |
2250 | ✗ | new ChildNodeType(PartialCreate(), offsetToGlobalCoord(i), background); | |
2251 | mNodes[i].setChild(child); | ||
2252 | ✗ | child->readTopology(is); | |
2253 | } else { | ||
2254 | ✗ | ValueType value; | |
2255 | ✗ | is.read(reinterpret_cast<char*>(&value), sizeof(ValueType)); | |
2256 | mNodes[i].setValue(value); | ||
2257 | } | ||
2258 | } | ||
2259 | } else { | ||
2260 | const bool oldVersion = | ||
2261 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
1010 | (io::getFormatVersion(is) < OPENVDB_FILE_VERSION_NODE_MASK_COMPRESSION); |
2262 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 505 times.
|
1010 | const Index numValues = (oldVersion ? mChildMask.countOff() : NUM_VALUES); |
2263 | { | ||
2264 | // Read in (and uncompress, if necessary) all of this node's values | ||
2265 | // into a contiguous array. | ||
2266 |
2/4✓ Branch 1 taken 3723264 times.
✓ Branch 2 taken 202 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
7447538 | std::unique_ptr<ValueType[]> valuePtr(new ValueType[numValues]); |
2267 | ValueType* values = valuePtr.get(); | ||
2268 |
1/2✓ Branch 1 taken 505 times.
✗ Branch 2 not taken.
|
1010 | io::readCompressedValues(is, values, numValues, mValueMask, fromHalf); |
2269 | |||
2270 | // Copy values from the array into this node's table. | ||
2271 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 505 times.
|
1010 | if (oldVersion) { |
2272 | Index n = 0; | ||
2273 | ✗ | for (ValueAllIter iter = this->beginValueAll(); iter; ++iter) { | |
2274 | ✗ | mNodes[iter.pos()].setValue(values[n++]); | |
2275 | } | ||
2276 | ✗ | assert(n == numValues); | |
2277 | } else { | ||
2278 |
2/2✓ Branch 0 taken 9198703 times.
✓ Branch 1 taken 505 times.
|
18398416 | for (ValueAllIter iter = this->beginValueAll(); iter; ++iter) { |
2279 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
18397406 | mNodes[iter.pos()].setValue(values[iter.pos()]); |
2280 | } | ||
2281 | } | ||
2282 | } | ||
2283 | // Read in all child nodes and insert them into the table at their proper locations. | ||
2284 |
2/2✓ Branch 0 taken 23441 times.
✓ Branch 1 taken 505 times.
|
47892 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
2285 |
3/9✓ Branch 1 taken 23441 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23441 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10219 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
46894 | ChildNodeType* child = new ChildNodeType(PartialCreate(), iter.getCoord(), background); |
2286 | mNodes[iter.pos()].setChild(child); | ||
2287 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
510 | child->readTopology(is, fromHalf); |
2288 | } | ||
2289 | } | ||
2290 | } | ||
2291 | |||
2292 | |||
2293 | //////////////////////////////////////// | ||
2294 | |||
2295 | |||
2296 | template<typename ChildT, Index Log2Dim> | ||
2297 | inline const typename ChildT::ValueType& | ||
2298 | 1554 | InternalNode<ChildT, Log2Dim>::getFirstValue() const | |
2299 | { | ||
2300 |
2/2✓ Branch 0 taken 34 times.
✓ Branch 1 taken 743 times.
|
1554 | return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].getValue()); |
2301 | } | ||
2302 | |||
2303 | |||
2304 | template<typename ChildT, Index Log2Dim> | ||
2305 | inline const typename ChildT::ValueType& | ||
2306 | 4295 | InternalNode<ChildT, Log2Dim>::getLastValue() const | |
2307 | { | ||
2308 | const Index n = NUM_VALUES - 1; | ||
2309 |
2/2✓ Branch 0 taken 70 times.
✓ Branch 1 taken 2078 times.
|
4295 | return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].getValue()); |
2310 | } | ||
2311 | |||
2312 | |||
2313 | //////////////////////////////////////// | ||
2314 | |||
2315 | |||
2316 | template<typename ChildT, Index Log2Dim> | ||
2317 | inline void | ||
2318 | 7 | InternalNode<ChildT, Log2Dim>::negate() | |
2319 | { | ||
2320 |
2/2✓ Branch 0 taken 102400 times.
✓ Branch 1 taken 4 times.
|
200711 | for (Index i = 0; i < NUM_VALUES; ++i) { |
2321 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 102400 times.
|
200704 | if (this->isChildMaskOn(i)) { |
2322 | ✗ | mNodes[i].getChild()->negate(); | |
2323 | } else { | ||
2324 | mNodes[i].setValue(math::negative(mNodes[i].getValue())); | ||
2325 | } | ||
2326 | } | ||
2327 | |||
2328 | 7 | } | |
2329 | |||
2330 | |||
2331 | //////////////////////////////////////// | ||
2332 | |||
2333 | |||
2334 | template<typename ChildT, Index Log2Dim> | ||
2335 | struct InternalNode<ChildT, Log2Dim>::VoxelizeActiveTiles | ||
2336 | { | ||
2337 | 32326 | VoxelizeActiveTiles(InternalNode &node) : mNode(&node) { | |
2338 | //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//single thread for debugging | ||
2339 | 32326 | tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this); | |
2340 | |||
2341 | node.mChildMask |= node.mValueMask; | ||
2342 | node.mValueMask.setOff(); | ||
2343 | 32160 | } | |
2344 | 4626874 | void operator()(const tbb::blocked_range<Index> &r) const | |
2345 | { | ||
2346 |
2/2✓ Branch 0 taken 219318656 times.
✓ Branch 1 taken 2313437 times.
|
443264186 | for (Index i = r.begin(), end=r.end(); i!=end; ++i) { |
2347 |
2/2✓ Branch 1 taken 43559920 times.
✓ Branch 2 taken 175758736 times.
|
438637312 | if (mNode->mChildMask.isOn(i)) {// Loop over node's child nodes |
2348 | 12754 | mNode->mNodes[i].getChild()->voxelizeActiveTiles(true); | |
2349 |
2/2✓ Branch 1 taken 20730988 times.
✓ Branch 2 taken 198236082 times.
|
437934140 | } else if (mNode->mValueMask.isOn(i)) {// Loop over node's active tiles |
2350 | 41461976 | const Coord &ijk = mNode->offsetToGlobalCoord(i); | |
2351 |
1/2✓ Branch 2 taken 574236 times.
✗ Branch 3 not taken.
|
41461976 | ChildNodeType *child = new ChildNodeType(ijk, mNode->mNodes[i].getValue(), true); |
2352 | 8992 | child->voxelizeActiveTiles(true); | |
2353 | 41461976 | mNode->mNodes[i].setChild(child); | |
2354 | } | ||
2355 | } | ||
2356 | 4626874 | } | |
2357 | InternalNode* mNode; | ||
2358 | };// VoxelizeActiveTiles | ||
2359 | |||
2360 | template<typename ChildT, Index Log2Dim> | ||
2361 | inline void | ||
2362 | 32800 | InternalNode<ChildT, Log2Dim>::voxelizeActiveTiles(bool threaded) | |
2363 | { | ||
2364 |
2/2✓ Branch 0 taken 16258 times.
✓ Branch 1 taken 142 times.
|
32800 | if (threaded) { |
2365 | 32184 | VoxelizeActiveTiles tmp(*this); | |
2366 | } else { | ||
2367 |
2/2✓ Branch 0 taken 8452 times.
✓ Branch 1 taken 142 times.
|
17188 | for (ValueOnIter iter = this->beginValueOn(); iter; ++iter) { |
2368 | 16904 | this->setChildNode(iter.pos(), | |
2369 |
1/2✓ Branch 3 taken 8322 times.
✗ Branch 4 not taken.
|
50712 | new ChildNodeType(iter.getCoord(), iter.getValue(), true)); |
2370 | } | ||
2371 |
2/2✓ Branch 0 taken 8458 times.
✓ Branch 1 taken 142 times.
|
17200 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) |
2372 | 268 | iter->voxelizeActiveTiles(false); | |
2373 | } | ||
2374 | 32800 | } | |
2375 | |||
2376 | |||
2377 | //////////////////////////////////////// | ||
2378 | |||
2379 | |||
2380 | template<typename ChildT, Index Log2Dim> | ||
2381 | template<MergePolicy Policy> | ||
2382 | inline void | ||
2383 | 170264 | InternalNode<ChildT, Log2Dim>::merge(InternalNode& other, | |
2384 | const ValueType& background, const ValueType& otherBackground) | ||
2385 | { | ||
2386 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
2387 | |||
2388 | switch (Policy) { | ||
2389 | |||
2390 | case MERGE_ACTIVE_STATES: | ||
2391 | default: | ||
2392 | { | ||
2393 |
2/2✓ Branch 0 taken 212294 times.
✓ Branch 1 taken 85108 times.
|
594804 | for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) { |
2394 | const Index n = iter.pos(); | ||
2395 |
2/2✓ Branch 1 taken 129694 times.
✓ Branch 2 taken 82600 times.
|
424588 | if (mChildMask.isOn(n)) { |
2396 | // Merge this node's child with the other node's child. | ||
2397 | 88452 | mNodes[n].getChild()->template merge<MERGE_ACTIVE_STATES>(*iter, | |
2398 | background, otherBackground); | ||
2399 |
2/2✓ Branch 1 taken 82403 times.
✓ Branch 2 taken 197 times.
|
165200 | } else if (mValueMask.isOff(n)) { |
2400 | // Replace this node's inactive tile with the other node's child | ||
2401 | // and replace the other node's child with a tile of undefined value | ||
2402 | // (which is okay since the other tree is assumed to be cannibalized | ||
2403 | // in the process of merging). | ||
2404 | ChildNodeType* child = other.mNodes[n].getChild(); | ||
2405 | 164806 | other.mChildMask.setOff(n); | |
2406 | 35174 | child->resetBackground(otherBackground, background); | |
2407 | 164806 | this->setChildNode(n, child); | |
2408 | } | ||
2409 | } | ||
2410 | |||
2411 | // Copy active tile values. | ||
2412 |
2/2✓ Branch 0 taken 5799 times.
✓ Branch 1 taken 85108 times.
|
181814 | for (ValueOnCIter iter = other.cbeginValueOn(); iter; ++iter) { |
2413 | const Index n = iter.pos(); | ||
2414 |
2/2✓ Branch 1 taken 1539 times.
✓ Branch 2 taken 4260 times.
|
11598 | if (mValueMask.isOff(n)) { |
2415 | // Replace this node's child or inactive tile with the other node's active tile. | ||
2416 | 3078 | this->makeChildNodeEmpty(n, iter.getValue()); | |
2417 | 3078 | mValueMask.setOn(n); | |
2418 | } | ||
2419 | } | ||
2420 | break; | ||
2421 | } | ||
2422 | |||
2423 | case MERGE_NODES: | ||
2424 | { | ||
2425 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 8 times.
|
28 | for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) { |
2426 | const Index n = iter.pos(); | ||
2427 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
12 | if (mChildMask.isOn(n)) { |
2428 | // Merge this node's child with the other node's child. | ||
2429 | 8 | mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground); | |
2430 | } else { | ||
2431 | // Replace this node's tile (regardless of its active state) with | ||
2432 | // the other node's child and replace the other node's child with | ||
2433 | // a tile of undefined value (which is okay since the other tree | ||
2434 | // is assumed to be cannibalized in the process of merging). | ||
2435 | ChildNodeType* child = other.mNodes[n].getChild(); | ||
2436 | ✗ | other.mChildMask.setOff(n); | |
2437 | ✗ | child->resetBackground(otherBackground, background); | |
2438 | ✗ | this->setChildNode(n, child); | |
2439 | } | ||
2440 | } | ||
2441 | break; | ||
2442 | } | ||
2443 | |||
2444 | case MERGE_ACTIVE_STATES_AND_NODES: | ||
2445 | { | ||
2446 | // Transfer children from the other tree to this tree. | ||
2447 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 16 times.
|
118 | for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) { |
2448 | const Index n = iter.pos(); | ||
2449 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 33 times.
|
86 | if (mChildMask.isOn(n)) { |
2450 | // Merge this node's child with the other node's child. | ||
2451 | 18 | mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground); | |
2452 | } else { | ||
2453 | // Replace this node's tile with the other node's child, leaving the other | ||
2454 | // node with an inactive tile of undefined value (which is okay since | ||
2455 | // the other tree is assumed to be cannibalized in the process of merging). | ||
2456 | ChildNodeType* child = other.mNodes[n].getChild(); | ||
2457 | 66 | other.mChildMask.setOff(n); | |
2458 | 66 | child->resetBackground(otherBackground, background); | |
2459 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
|
66 | if (mValueMask.isOn(n)) { |
2460 | // Merge the child with this node's active tile. | ||
2461 | ✗ | child->template merge<Policy>(mNodes[n].getValue(), /*on=*/true); | |
2462 | ✗ | mValueMask.setOff(n); | |
2463 | } | ||
2464 | 66 | mChildMask.setOn(n); | |
2465 | mNodes[n].setChild(child); | ||
2466 | } | ||
2467 | } | ||
2468 | |||
2469 | // Merge active tiles into this tree. | ||
2470 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16 times.
|
36 | for (ValueOnCIter iter = other.cbeginValueOn(); iter; ++iter) { |
2471 | const Index n = iter.pos(); | ||
2472 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
4 | if (mChildMask.isOn(n)) { |
2473 | // Merge the other node's active tile into this node's child. | ||
2474 |
0/2✗ Branch 0 not taken.
✗ Branch 1 not taken.
|
4 | mNodes[n].getChild()->template merge<Policy>(iter.getValue(), /*on=*/true); |
2475 | ✗ | } else if (mValueMask.isOff(n)) { | |
2476 | // Replace this node's inactive tile with the other node's active tile. | ||
2477 | mNodes[n].setValue(iter.getValue()); | ||
2478 | ✗ | mValueMask.setOn(n); | |
2479 | } | ||
2480 | } | ||
2481 | break; | ||
2482 | } | ||
2483 | |||
2484 | } | ||
2485 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
2486 | } | ||
2487 | |||
2488 | |||
2489 | template<typename ChildT, Index Log2Dim> | ||
2490 | template<MergePolicy Policy> | ||
2491 | inline void | ||
2492 | ✗ | InternalNode<ChildT, Log2Dim>::merge(const ValueType& tileValue, bool tileActive) | |
2493 | { | ||
2494 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
2495 | |||
2496 | if (Policy != MERGE_ACTIVE_STATES_AND_NODES) return; | ||
2497 | |||
2498 | // For MERGE_ACTIVE_STATES_AND_NODES, inactive tiles in the other tree are ignored. | ||
2499 | ✗ | if (!tileActive) return; | |
2500 | |||
2501 | // Iterate over this node's children and inactive tiles. | ||
2502 | ✗ | for (ValueOffIter iter = this->beginValueOff(); iter; ++iter) { | |
2503 | const Index n = iter.pos(); | ||
2504 | ✗ | if (mChildMask.isOn(n)) { | |
2505 | // Merge the other node's active tile into this node's child. | ||
2506 | ✗ | mNodes[n].getChild()->template merge<Policy>(tileValue, /*on=*/true); | |
2507 | } else { | ||
2508 | // Replace this node's inactive tile with the other node's active tile. | ||
2509 | iter.setValue(tileValue); | ||
2510 | ✗ | mValueMask.setOn(n); | |
2511 | } | ||
2512 | } | ||
2513 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
2514 | } | ||
2515 | |||
2516 | |||
2517 | //////////////////////////////////////// | ||
2518 | |||
2519 | |||
2520 | template<typename ChildT, Index Log2Dim> | ||
2521 | template<typename OtherInternalNode> | ||
2522 | struct InternalNode<ChildT, Log2Dim>::TopologyUnion | ||
2523 | { | ||
2524 | using W = typename NodeMaskType::Word; | ||
2525 | struct A { inline void operator()(W &tV, const W& sV, const W& tC) const | ||
2526 | 3997568 | { tV = (tV | sV) & ~tC; } | |
2527 | }; | ||
2528 | 29752 | TopologyUnion(const OtherInternalNode* source, InternalNode* target, const bool preserveTiles) | |
2529 | 29752 | : s(source), t(target), mPreserveTiles(preserveTiles) { | |
2530 | //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//single thread for debugging | ||
2531 | 29752 | tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this); | |
2532 | |||
2533 | // Bit processing is done in a single thread! | ||
2534 |
2/2✓ Branch 0 taken 9609 times.
✓ Branch 1 taken 5267 times.
|
29752 | if (!mPreserveTiles) t->mChildMask |= s->mChildMask;//serial but very fast bitwise post-process |
2535 | 42136 | else t->mChildMask |= (s->mChildMask & !t->mValueMask); | |
2536 | |||
2537 | A op; | ||
2538 | 29752 | t->mValueMask.foreach(s->mValueMask, t->mChildMask, op); | |
2539 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14876 times.
|
59504 | assert((t->mValueMask & t->mChildMask).isOff());//no overlapping active tiles or child nodes |
2540 | 29752 | } | |
2541 | 4363708 | void operator()(const tbb::blocked_range<Index> &r) const { | |
2542 |
2/2✓ Branch 0 taken 255844352 times.
✓ Branch 1 taken 2181854 times.
|
516052412 | for (Index i = r.begin(), end=r.end(); i!=end; ++i) { |
2543 |
2/2✓ Branch 1 taken 68381 times.
✓ Branch 2 taken 255775971 times.
|
511688704 | if (s->mChildMask.isOn(i)) {// Loop over other node's child nodes |
2544 | const typename OtherInternalNode::ChildNodeType& other = *(s->mNodes[i].getChild()); | ||
2545 |
2/2✓ Branch 1 taken 37219 times.
✓ Branch 2 taken 31162 times.
|
136762 | if (t->mChildMask.isOn(i)) {//this has a child node |
2546 | 16156 | t->mNodes[i].getChild()->topologyUnion(other, mPreserveTiles); | |
2547 | } else {// this is a tile so replace it with a child branch with identical topology | ||
2548 |
4/4✓ Branch 0 taken 3265 times.
✓ Branch 1 taken 27897 times.
✓ Branch 3 taken 3232 times.
✓ Branch 4 taken 33 times.
|
62324 | if (!mPreserveTiles || t->mValueMask.isOff(i)) { // force child topology |
2549 |
2/4✓ Branch 1 taken 6915 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1698 times.
✗ Branch 5 not taken.
|
62258 | ChildT* child = new ChildT(other, t->mNodes[i].getValue(), TopologyCopy()); |
2550 |
2/2✓ Branch 1 taken 91 times.
✓ Branch 2 taken 31038 times.
|
62258 | if (t->mValueMask.isOn(i)) child->setValuesOn();//activate all values |
2551 | 62258 | t->mNodes[i].setChild(child); | |
2552 | } | ||
2553 | } | ||
2554 |
4/4✓ Branch 1 taken 41175 times.
✓ Branch 2 taken 255734796 times.
✓ Branch 4 taken 178 times.
✓ Branch 5 taken 40997 times.
|
511551942 | } else if (s->mValueMask.isOn(i) && t->mChildMask.isOn(i)) { |
2555 | 2 | t->mNodes[i].getChild()->setValuesOn(); | |
2556 | } | ||
2557 | } | ||
2558 | 4363708 | } | |
2559 | const OtherInternalNode* s; | ||
2560 | InternalNode* t; | ||
2561 | const bool mPreserveTiles; | ||
2562 | };// TopologyUnion | ||
2563 | |||
2564 | template<typename ChildT, Index Log2Dim> | ||
2565 | template<typename OtherChildT> | ||
2566 | inline void | ||
2567 | InternalNode<ChildT, Log2Dim>::topologyUnion(const InternalNode<OtherChildT, Log2Dim>& other, const bool preserveTiles) | ||
2568 | { | ||
2569 |
27/68✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 21 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 250 times.
✓ Branch 10 taken 623 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2619 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 14 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 45 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 75 times.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✓ Branch 29 taken 69 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 65 times.
✗ Branch 33 not taken.
✓ Branch 35 taken 69 times.
✗ Branch 36 not taken.
✓ Branch 38 taken 66 times.
✗ Branch 39 not taken.
✓ Branch 41 taken 66 times.
✗ Branch 42 not taken.
✓ Branch 44 taken 69 times.
✗ Branch 45 not taken.
✓ Branch 47 taken 75 times.
✗ Branch 48 not taken.
✓ Branch 50 taken 116 times.
✗ Branch 51 not taken.
✓ Branch 53 taken 130 times.
✗ Branch 54 not taken.
✓ Branch 56 taken 49 times.
✗ Branch 57 not taken.
✓ Branch 59 taken 49 times.
✗ Branch 60 not taken.
✓ Branch 62 taken 67 times.
✗ Branch 63 not taken.
✓ Branch 65 taken 449 times.
✗ Branch 66 not taken.
✓ Branch 68 taken 34 times.
✗ Branch 69 not taken.
✓ Branch 71 taken 286 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 99 times.
✗ Branch 75 not taken.
✓ Branch 77 taken 273 times.
✗ Branch 78 not taken.
✓ Branch 80 taken 398 times.
✗ Branch 81 not taken.
✓ Branch 83 taken 720 times.
✗ Branch 84 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
|
14876 | TopologyUnion<InternalNode<OtherChildT, Log2Dim> > tmp(&other, this, preserveTiles); |
2570 | 14876 | } | |
2571 | |||
2572 | template<typename ChildT, Index Log2Dim> | ||
2573 | template<typename OtherInternalNode> | ||
2574 | struct InternalNode<ChildT, Log2Dim>::TopologyIntersection | ||
2575 | { | ||
2576 | using W = typename NodeMaskType::Word; | ||
2577 | struct A { inline void operator()(W &tC, const W& sC, const W& sV, const W& tV) const | ||
2578 | 214912 | { tC = (tC & (sC | sV)) | (tV & sC); } | |
2579 | }; | ||
2580 | 1494 | TopologyIntersection(const OtherInternalNode* source, InternalNode* target, | |
2581 | 1494 | const ValueType& background) : s(source), t(target), b(background) { | |
2582 | //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//single thread for debugging | ||
2583 | 1494 | tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this); | |
2584 | |||
2585 | // Bit processing is done in a single thread! | ||
2586 | A op; | ||
2587 | 1494 | t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op); | |
2588 | |||
2589 | 1494 | t->mValueMask &= s->mValueMask; | |
2590 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 747 times.
|
2988 | assert((t->mValueMask & t->mChildMask).isOff());//no overlapping active tiles or child nodes |
2591 | 1494 | } | |
2592 | 216068 | void operator()(const tbb::blocked_range<Index> &r) const { | |
2593 |
2/2✓ Branch 0 taken 13754368 times.
✓ Branch 1 taken 108034 times.
|
27724804 | for (Index i = r.begin(), end=r.end(); i!=end; ++i) { |
2594 |
2/2✓ Branch 1 taken 13761 times.
✓ Branch 2 taken 13740607 times.
|
27508736 | if (t->mChildMask.isOn(i)) {// Loop over this node's child nodes |
2595 | ChildT* child = t->mNodes[i].getChild(); | ||
2596 |
2/2✓ Branch 1 taken 8426 times.
✓ Branch 2 taken 5335 times.
|
27522 | if (s->mChildMask.isOn(i)) {//other also has a child node |
2597 | 748 | child->topologyIntersection(*(s->mNodes[i].getChild()), b); | |
2598 |
2/2✓ Branch 1 taken 4884 times.
✓ Branch 2 taken 451 times.
|
10670 | } else if (s->mValueMask.isOff(i)) {//other is an inactive tile |
2599 |
1/2✓ Branch 0 taken 4884 times.
✗ Branch 1 not taken.
|
15856 | delete child;//convert child to an inactive tile |
2600 | 9768 | t->mNodes[i].setValue(b); | |
2601 | } | ||
2602 |
4/4✓ Branch 1 taken 3438 times.
✓ Branch 2 taken 13737169 times.
✓ Branch 4 taken 50 times.
✓ Branch 5 taken 3388 times.
|
27481214 | } else if (t->mValueMask.isOn(i) && s->mChildMask.isOn(i)) {//active tile -> a branch |
2603 |
1/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
100 | t->mNodes[i].setChild(new ChildT(*(s->mNodes[i].getChild()), |
2604 | t->mNodes[i].getValue(), TopologyCopy())); | ||
2605 | } | ||
2606 | } | ||
2607 | 216068 | } | |
2608 | const OtherInternalNode* s; | ||
2609 | InternalNode* t; | ||
2610 | const ValueType& b; | ||
2611 | };// TopologyIntersection | ||
2612 | |||
2613 | template<typename ChildT, Index Log2Dim> | ||
2614 | template<typename OtherChildT> | ||
2615 | inline void | ||
2616 | InternalNode<ChildT, Log2Dim>::topologyIntersection( | ||
2617 | const InternalNode<OtherChildT, Log2Dim>& other, const ValueType& background) | ||
2618 | { | ||
2619 |
8/47✓ Branch 2 taken 279 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 40 times.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 20 taken 8 times.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✓ Branch 23 taken 9 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 21 times.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
|
747 | TopologyIntersection<InternalNode<OtherChildT, Log2Dim> > tmp(&other, this, background); |
2620 | 747 | } | |
2621 | |||
2622 | template<typename ChildT, Index Log2Dim> | ||
2623 | template<typename OtherInternalNode> | ||
2624 | struct InternalNode<ChildT, Log2Dim>::TopologyDifference | ||
2625 | { | ||
2626 | using W = typename NodeMaskType::Word; | ||
2627 | struct A {inline void operator()(W &tC, const W& sC, const W& sV, const W& tV) const | ||
2628 | 102912 | { tC = (tC & (sC | ~sV)) | (tV & sC); } | |
2629 | }; | ||
2630 | struct B {inline void operator()(W &tV, const W& sC, const W& sV, const W& tC) const | ||
2631 | 102912 | { tV &= ~((tC & sV) | (sC | sV)); } | |
2632 | }; | ||
2633 | 724 | TopologyDifference(const OtherInternalNode* source, InternalNode* target, | |
2634 | 724 | const ValueType& background) : s(source), t(target), b(background) { | |
2635 | //(*this)(tbb::blocked_range<Index>(0, NUM_VALUES));//single thread for debugging | ||
2636 | 724 | tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *this); | |
2637 | |||
2638 | // Bit processing is done in a single thread! | ||
2639 | 724 | const NodeMaskType oldChildMask(t->mChildMask);//important to avoid cross pollution | |
2640 | A op1; | ||
2641 | 724 | t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op1); | |
2642 | |||
2643 | B op2; | ||
2644 | 724 | t->mValueMask.foreach(t->mChildMask, s->mValueMask, oldChildMask, op2); | |
2645 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 362 times.
|
1448 | assert((t->mValueMask & t->mChildMask).isOff());//no overlapping active tiles or child nodes |
2646 | 724 | } | |
2647 | 109050 | void operator()(const tbb::blocked_range<Index> &r) const { | |
2648 |
2/2✓ Branch 0 taken 6586368 times.
✓ Branch 1 taken 54525 times.
|
13281786 | for (Index i = r.begin(), end=r.end(); i!=end; ++i) { |
2649 |
2/2✓ Branch 1 taken 18267 times.
✓ Branch 2 taken 6568101 times.
|
13172736 | if (t->mChildMask.isOn(i)) {// Loop over this node's child nodes |
2650 | ChildT* child = t->mNodes[i].getChild(); | ||
2651 |
2/2✓ Branch 1 taken 12108 times.
✓ Branch 2 taken 6159 times.
|
36534 | if (s->mChildMask.isOn(i)) { |
2652 | 24216 | child->topologyDifference(*(s->mNodes[i].getChild()), b); | |
2653 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6159 times.
|
12318 | } else if (s->mValueMask.isOn(i)) { |
2654 | ✗ | delete child;//convert child to an inactive tile | |
2655 | ✗ | t->mNodes[i].setValue(b); | |
2656 | } | ||
2657 |
2/2✓ Branch 1 taken 42765 times.
✓ Branch 2 taken 6525336 times.
|
13136202 | } else if (t->mValueMask.isOn(i)) {//this is an active tile |
2658 |
2/2✓ Branch 1 taken 40 times.
✓ Branch 2 taken 42725 times.
|
85530 | if (s->mChildMask.isOn(i)) { |
2659 | const typename OtherInternalNode::ChildNodeType& other = | ||
2660 | *(s->mNodes[i].getChild()); | ||
2661 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
80 | ChildT* child = new ChildT(other.origin(), t->mNodes[i].getValue(), true); |
2662 | 80 | child->topologyDifference(other, b); | |
2663 | 80 | t->mNodes[i].setChild(child);//replace the active tile with a child branch | |
2664 | } | ||
2665 | } | ||
2666 | } | ||
2667 | 109050 | } | |
2668 | const OtherInternalNode* s; | ||
2669 | InternalNode* t; | ||
2670 | const ValueType& b; | ||
2671 | };// TopologyDifference | ||
2672 | |||
2673 | template<typename ChildT, Index Log2Dim> | ||
2674 | template<typename OtherChildT> | ||
2675 | inline void | ||
2676 | InternalNode<ChildT, Log2Dim>::topologyDifference(const InternalNode<OtherChildT, Log2Dim>& other, | ||
2677 | const ValueType& background) | ||
2678 | { | ||
2679 |
3/11✓ Branch 3 taken 113 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 11 taken 64 times.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
362 | TopologyDifference<InternalNode<OtherChildT, Log2Dim> > tmp(&other, this, background); |
2680 | 359 | } | |
2681 | |||
2682 | |||
2683 | //////////////////////////////////////// | ||
2684 | |||
2685 | |||
2686 | template<typename ChildT, Index Log2Dim> | ||
2687 | template<typename CombineOp> | ||
2688 | inline void | ||
2689 | 148 | InternalNode<ChildT, Log2Dim>::combine(InternalNode& other, CombineOp& op) | |
2690 | { | ||
2691 | 76 | const ValueType zero = zeroVal<ValueType>(); | |
2692 | |||
2693 | CombineArgs<ValueType> args; | ||
2694 | |||
2695 |
2/2✓ Branch 0 taken 1363968 times.
✓ Branch 1 taken 74 times.
|
2728084 | for (Index i = 0; i < NUM_VALUES; ++i) { |
2696 |
4/4✓ Branch 0 taken 1363566 times.
✓ Branch 1 taken 402 times.
✓ Branch 2 taken 1363208 times.
✓ Branch 3 taken 358 times.
|
5455068 | if (this->isChildMaskOff(i) && other.isChildMaskOff(i)) { |
2697 | // Both this node and the other node have constant values (tiles). | ||
2698 | // Combine the two values and store the result as this node's new tile value. | ||
2699 | 2431520 | op(args.setARef(mNodes[i].getValue()) | |
2700 | .setAIsActive(isValueMaskOn(i)) | ||
2701 | .setBRef(other.mNodes[i].getValue()) | ||
2702 | .setBIsActive(other.isValueMaskOn(i))); | ||
2703 | mNodes[i].setValue(args.result()); | ||
2704 | mValueMask.set(i, args.resultIsActive()); | ||
2705 |
4/4✓ Branch 0 taken 402 times.
✓ Branch 1 taken 358 times.
✓ Branch 2 taken 99 times.
✓ Branch 3 taken 303 times.
|
2324 | } else if (this->isChildMaskOn(i) && other.isChildMaskOff(i)) { |
2706 | // Combine this node's child with the other node's constant value. | ||
2707 | ChildNodeType* child = mNodes[i].getChild(); | ||
2708 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
606 | assert(child); |
2709 | if (child) { | ||
2710 | 606 | child->combine(other.mNodes[i].getValue(), other.isValueMaskOn(i), op); | |
2711 | } | ||
2712 |
3/4✓ Branch 0 taken 358 times.
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 358 times.
|
1630 | } else if (this->isChildMaskOff(i) && other.isChildMaskOn(i)) { |
2713 | // Combine this node's constant value with the other node's child. | ||
2714 | ChildNodeType* child = other.mNodes[i].getChild(); | ||
2715 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 358 times.
|
716 | assert(child); |
2716 | if (child) { | ||
2717 | // Combine this node's constant value with the other node's child, | ||
2718 | // but use a new functor in which the A and B values are swapped, | ||
2719 | // since the constant value is the A value, not the B value. | ||
2720 | SwappedCombineOp<ValueType, CombineOp> swappedOp(op); | ||
2721 | 716 | child->combine(mNodes[i].getValue(), isValueMaskOn(i), swappedOp); | |
2722 | |||
2723 | // Steal the other node's child. | ||
2724 | 716 | other.mChildMask.setOff(i); | |
2725 | other.mNodes[i].setValue(zero); | ||
2726 | 716 | this->setChildNode(i, child); | |
2727 | } | ||
2728 | |||
2729 | } else /*if (isChildMaskOn(i) && other.isChildMaskOn(i))*/ { | ||
2730 | // Combine this node's child with the other node's child. | ||
2731 | ChildNodeType | ||
2732 | *child = mNodes[i].getChild(), | ||
2733 | *otherChild = other.mNodes[i].getChild(); | ||
2734 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
|
198 | assert(child); |
2735 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 99 times.
|
198 | assert(otherChild); |
2736 | if (child && otherChild) { | ||
2737 | 198 | child->combine(*otherChild, op); | |
2738 | } | ||
2739 | } | ||
2740 | } | ||
2741 | 148 | } | |
2742 | |||
2743 | |||
2744 | template<typename ChildT, Index Log2Dim> | ||
2745 | template<typename CombineOp> | ||
2746 | inline void | ||
2747 | 12 | InternalNode<ChildT, Log2Dim>::combine(const ValueType& value, bool valueIsActive, CombineOp& op) | |
2748 | { | ||
2749 | CombineArgs<ValueType> args; | ||
2750 | |||
2751 |
2/2✓ Branch 0 taken 110592 times.
✓ Branch 1 taken 6 times.
|
221196 | for (Index i = 0; i < NUM_VALUES; ++i) { |
2752 |
2/2✓ Branch 0 taken 110577 times.
✓ Branch 1 taken 15 times.
|
221184 | if (this->isChildMaskOff(i)) { |
2753 | // Combine this node's constant value with the given constant value. | ||
2754 | 221154 | op(args.setARef(mNodes[i].getValue()) | |
2755 | .setAIsActive(isValueMaskOn(i)) | ||
2756 | .setBRef(value) | ||
2757 | .setBIsActive(valueIsActive)); | ||
2758 | mNodes[i].setValue(args.result()); | ||
2759 | mValueMask.set(i, args.resultIsActive()); | ||
2760 | } else /*if (isChildMaskOn(i))*/ { | ||
2761 | // Combine this node's child with the given constant value. | ||
2762 | ChildNodeType* child = mNodes[i].getChild(); | ||
2763 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
30 | assert(child); |
2764 | 30 | if (child) child->combine(value, valueIsActive, op); | |
2765 | } | ||
2766 | } | ||
2767 | } | ||
2768 | |||
2769 | |||
2770 | //////////////////////////////////////// | ||
2771 | |||
2772 | |||
2773 | template<typename ChildT, Index Log2Dim> | ||
2774 | template<typename CombineOp, typename OtherNodeType> | ||
2775 | inline void | ||
2776 | 16 | InternalNode<ChildT, Log2Dim>::combine2(const InternalNode& other0, const OtherNodeType& other1, | |
2777 | CombineOp& op) | ||
2778 | { | ||
2779 | CombineArgs<ValueType, typename OtherNodeType::ValueType> args; | ||
2780 | |||
2781 |
2/2✓ Branch 0 taken 147456 times.
✓ Branch 1 taken 8 times.
|
294928 | for (Index i = 0; i < NUM_VALUES; ++i) { |
2782 |
3/4✓ Branch 0 taken 147448 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 147448 times.
✗ Branch 3 not taken.
|
589808 | if (other0.isChildMaskOff(i) && other1.isChildMaskOff(i)) { |
2783 | op(args.setARef(other0.mNodes[i].getValue()) | ||
2784 | .setAIsActive(other0.isValueMaskOn(i)) | ||
2785 | .setBRef(other1.mNodes[i].getValue()) | ||
2786 | .setBIsActive(other1.isValueMaskOn(i))); | ||
2787 | // Replace child i with a constant value. | ||
2788 | 294896 | this->makeChildNodeEmpty(i, args.result()); | |
2789 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 147448 times.
|
294896 | mValueMask.set(i, args.resultIsActive()); |
2790 | } else { | ||
2791 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
16 | if (this->isChildMaskOff(i)) { |
2792 | // Add a new child with the same coordinates, etc. as the other node's child. | ||
2793 | const Coord& childOrigin = other0.isChildMaskOn(i) | ||
2794 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
16 | ? other0.mNodes[i].getChild()->origin() |
2795 | : other1.mNodes[i].getChild()->origin(); | ||
2796 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
16 | this->setChildNode(i, new ChildNodeType(childOrigin, mNodes[i].getValue())); |
2797 | } | ||
2798 | |||
2799 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
16 | if (other0.isChildMaskOff(i)) { |
2800 | // Combine node1's child with node0's constant value | ||
2801 | // and write the result into child i. | ||
2802 | ✗ | mNodes[i].getChild()->combine2(other0.mNodes[i].getValue(), | |
2803 | *other1.mNodes[i].getChild(), other0.isValueMaskOn(i), op); | ||
2804 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
16 | } else if (other1.isChildMaskOff(i)) { |
2805 | // Combine node0's child with node1's constant value | ||
2806 | // and write the result into child i. | ||
2807 | ✗ | mNodes[i].getChild()->combine2(*other0.mNodes[i].getChild(), | |
2808 | other1.mNodes[i].getValue(), other1.isValueMaskOn(i), op); | ||
2809 | } else { | ||
2810 | // Combine node0's child with node1's child | ||
2811 | // and write the result into child i. | ||
2812 | 16 | mNodes[i].getChild()->combine2(*other0.mNodes[i].getChild(), | |
2813 | *other1.mNodes[i].getChild(), op); | ||
2814 | } | ||
2815 | } | ||
2816 | } | ||
2817 | 16 | } | |
2818 | |||
2819 | |||
2820 | template<typename ChildT, Index Log2Dim> | ||
2821 | template<typename CombineOp, typename OtherNodeType> | ||
2822 | inline void | ||
2823 | ✗ | InternalNode<ChildT, Log2Dim>::combine2(const ValueType& value, const OtherNodeType& other, | |
2824 | bool valueIsActive, CombineOp& op) | ||
2825 | { | ||
2826 | CombineArgs<ValueType, typename OtherNodeType::ValueType> args; | ||
2827 | |||
2828 | ✗ | for (Index i = 0; i < NUM_VALUES; ++i) { | |
2829 | ✗ | if (other.isChildMaskOff(i)) { | |
2830 | op(args.setARef(value) | ||
2831 | .setAIsActive(valueIsActive) | ||
2832 | .setBRef(other.mNodes[i].getValue()) | ||
2833 | .setBIsActive(other.isValueMaskOn(i))); | ||
2834 | // Replace child i with a constant value. | ||
2835 | ✗ | this->makeChildNodeEmpty(i, args.result()); | |
2836 | ✗ | mValueMask.set(i, args.resultIsActive()); | |
2837 | } else { | ||
2838 | typename OtherNodeType::ChildNodeType* otherChild = other.mNodes[i].getChild(); | ||
2839 | ✗ | assert(otherChild); | |
2840 | ✗ | if (this->isChildMaskOff(i)) { | |
2841 | // Add a new child with the same coordinates, etc. | ||
2842 | // as the other node's child. | ||
2843 | ✗ | this->setChildNode(i, new ChildNodeType(*otherChild)); | |
2844 | } | ||
2845 | // Combine the other node's child with a constant value | ||
2846 | // and write the result into child i. | ||
2847 | ✗ | mNodes[i].getChild()->combine2(value, *otherChild, valueIsActive, op); | |
2848 | } | ||
2849 | } | ||
2850 | } | ||
2851 | |||
2852 | |||
2853 | template<typename ChildT, Index Log2Dim> | ||
2854 | template<typename CombineOp, typename OtherValueType> | ||
2855 | inline void | ||
2856 | ✗ | InternalNode<ChildT, Log2Dim>::combine2(const InternalNode& other, const OtherValueType& value, | |
2857 | bool valueIsActive, CombineOp& op) | ||
2858 | { | ||
2859 | CombineArgs<ValueType, OtherValueType> args; | ||
2860 | |||
2861 | ✗ | for (Index i = 0; i < NUM_VALUES; ++i) { | |
2862 | ✗ | if (other.isChildMaskOff(i)) { | |
2863 | op(args.setARef(other.mNodes[i].getValue()) | ||
2864 | .setAIsActive(other.isValueMaskOn(i)) | ||
2865 | .setBRef(value) | ||
2866 | .setBIsActive(valueIsActive)); | ||
2867 | // Replace child i with a constant value. | ||
2868 | ✗ | this->makeChildNodeEmpty(i, args.result()); | |
2869 | ✗ | mValueMask.set(i, args.resultIsActive()); | |
2870 | } else { | ||
2871 | ChildNodeType* otherChild = other.mNodes[i].getChild(); | ||
2872 | ✗ | assert(otherChild); | |
2873 | ✗ | if (this->isChildMaskOff(i)) { | |
2874 | // Add a new child with the same coordinates, etc. as the other node's child. | ||
2875 | ✗ | this->setChildNode(i, | |
2876 | ✗ | new ChildNodeType(otherChild->origin(), mNodes[i].getValue())); | |
2877 | } | ||
2878 | // Combine the other node's child with a constant value | ||
2879 | // and write the result into child i. | ||
2880 | ✗ | mNodes[i].getChild()->combine2(*otherChild, value, valueIsActive, op); | |
2881 | } | ||
2882 | } | ||
2883 | } | ||
2884 | |||
2885 | |||
2886 | //////////////////////////////////////// | ||
2887 | |||
2888 | |||
2889 | template<typename ChildT, Index Log2Dim> | ||
2890 | template<typename BBoxOp> | ||
2891 | inline void | ||
2892 | 20 | InternalNode<ChildT, Log2Dim>::visitActiveBBox(BBoxOp& op) const | |
2893 | { | ||
2894 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 10 times.
|
28 | for (ValueOnCIter i = this->cbeginValueOn(); i; ++i) { |
2895 | 16 | op.template operator()<LEVEL>(CoordBBox::createCube(i.getCoord(), ChildNodeType::DIM)); | |
2896 | } | ||
2897 | if (op.template descent<LEVEL>()) { | ||
2898 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 10 times.
|
44 | for (ChildOnCIter i = this->cbeginChildOn(); i; ++i) i->visitActiveBBox(op); |
2899 | } else { | ||
2900 | for (ChildOnCIter i = this->cbeginChildOn(); i; ++i) { | ||
2901 | op.template operator()<LEVEL>(i->getNodeBoundingBox()); | ||
2902 | } | ||
2903 | } | ||
2904 | 20 | } | |
2905 | |||
2906 | |||
2907 | template<typename ChildT, Index Log2Dim> | ||
2908 | template<typename VisitorOp> | ||
2909 | inline void | ||
2910 | InternalNode<ChildT, Log2Dim>::visit(VisitorOp& op) | ||
2911 | { | ||
2912 |
10/20✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 8 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
|
45 | doVisit<InternalNode, VisitorOp, ChildAllIter>(*this, op); |
2913 | 45 | } | |
2914 | |||
2915 | |||
2916 | template<typename ChildT, Index Log2Dim> | ||
2917 | template<typename VisitorOp> | ||
2918 | inline void | ||
2919 | InternalNode<ChildT, Log2Dim>::visit(VisitorOp& op) const | ||
2920 | { | ||
2921 |
10/20✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 16 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 16 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 2 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 2 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 2 times.
✗ Branch 29 not taken.
|
90 | doVisit<const InternalNode, VisitorOp, ChildAllCIter>(*this, op); |
2922 | 90 | } | |
2923 | |||
2924 | |||
2925 | template<typename ChildT, Index Log2Dim> | ||
2926 | template<typename NodeT, typename VisitorOp, typename ChildAllIterT> | ||
2927 | inline void | ||
2928 | 270 | InternalNode<ChildT, Log2Dim>::doVisit(NodeT& self, VisitorOp& op) | |
2929 | { | ||
2930 | typename NodeT::ValueType val; | ||
2931 |
3/3✓ Branch 0 taken 655360 times.
✓ Branch 1 taken 327770 times.
✓ Branch 2 taken 45 times.
|
1966440 | for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) { |
2932 |
3/4✓ Branch 1 taken 983040 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 163840 times.
✓ Branch 4 taken 819200 times.
|
1966080 | if (op(iter)) continue; |
2933 |
2/2✓ Branch 0 taken 200 times.
✓ Branch 1 taken 819000 times.
|
1638400 | if (typename ChildAllIterT::ChildNodeType* child = iter.probeChild(val)) { |
2934 | child->visit(op); | ||
2935 | } | ||
2936 | } | ||
2937 | 270 | } | |
2938 | |||
2939 | |||
2940 | //////////////////////////////////////// | ||
2941 | |||
2942 | |||
2943 | template<typename ChildT, Index Log2Dim> | ||
2944 | template<typename OtherNodeType, typename VisitorOp> | ||
2945 | inline void | ||
2946 | InternalNode<ChildT, Log2Dim>::visit2Node(OtherNodeType& other, VisitorOp& op) | ||
2947 | { | ||
2948 | doVisit2Node<InternalNode, OtherNodeType, VisitorOp, ChildAllIter, | ||
2949 |
2/4✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
45 | typename OtherNodeType::ChildAllIter>(*this, other, op); |
2950 | 45 | } | |
2951 | |||
2952 | |||
2953 | template<typename ChildT, Index Log2Dim> | ||
2954 | template<typename OtherNodeType, typename VisitorOp> | ||
2955 | inline void | ||
2956 | InternalNode<ChildT, Log2Dim>::visit2Node(OtherNodeType& other, VisitorOp& op) const | ||
2957 | { | ||
2958 | doVisit2Node<const InternalNode, OtherNodeType, VisitorOp, ChildAllCIter, | ||
2959 | typename OtherNodeType::ChildAllCIter>(*this, other, op); | ||
2960 | } | ||
2961 | |||
2962 | |||
2963 | template<typename ChildT, Index Log2Dim> | ||
2964 | template< | ||
2965 | typename NodeT, | ||
2966 | typename OtherNodeT, | ||
2967 | typename VisitorOp, | ||
2968 | typename ChildAllIterT, | ||
2969 | typename OtherChildAllIterT> | ||
2970 | inline void | ||
2971 | 90 | InternalNode<ChildT, Log2Dim>::doVisit2Node(NodeT& self, OtherNodeT& other, VisitorOp& op) | |
2972 | { | ||
2973 | // Allow the two nodes to have different ValueTypes, but not different dimensions. | ||
2974 | static_assert(OtherNodeT::NUM_VALUES == NodeT::NUM_VALUES, | ||
2975 | "visit2() requires nodes to have the same dimensions"); | ||
2976 | static_assert(OtherNodeT::LEVEL == NodeT::LEVEL, | ||
2977 | "visit2() requires nodes to be at the same tree level"); | ||
2978 | |||
2979 | typename NodeT::ValueType val; | ||
2980 | typename OtherNodeT::ValueType otherVal; | ||
2981 | |||
2982 | 90 | ChildAllIterT iter = self.beginChildAll(); | |
2983 | 90 | OtherChildAllIterT otherIter = other.beginChildAll(); | |
2984 | |||
2985 |
3/4✓ Branch 0 taken 327680 times.
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 327680 times.
✗ Branch 3 not taken.
|
1310810 | for ( ; iter && otherIter; ++iter, ++otherIter) |
2986 | { | ||
2987 | 655360 | const size_t skipBranch = static_cast<size_t>(op(iter, otherIter)); | |
2988 | |||
2989 | typename ChildAllIterT::ChildNodeType* child = | ||
2990 |
2/2✓ Branch 0 taken 294912 times.
✓ Branch 1 taken 32768 times.
|
655360 | (skipBranch & 1U) ? nullptr : iter.probeChild(val); |
2991 | typename OtherChildAllIterT::ChildNodeType* otherChild = | ||
2992 |
2/2✓ Branch 0 taken 294912 times.
✓ Branch 1 taken 32768 times.
|
655360 | (skipBranch & 2U) ? nullptr : otherIter.probeChild(otherVal); |
2993 | |||
2994 |
2/2✓ Branch 0 taken 64 times.
✓ Branch 1 taken 327616 times.
|
655360 | if (child != nullptr && otherChild != nullptr) { |
2995 | child->visit2Node(*otherChild, op); | ||
2996 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 327608 times.
|
655232 | } else if (child != nullptr) { |
2997 | child->visit2(otherIter, op); | ||
2998 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 327600 times.
|
655216 | } else if (otherChild != nullptr) { |
2999 | otherChild->visit2(iter, op, /*otherIsLHS=*/true); | ||
3000 | } | ||
3001 | } | ||
3002 | 90 | } | |
3003 | |||
3004 | |||
3005 | //////////////////////////////////////// | ||
3006 | |||
3007 | |||
3008 | template<typename ChildT, Index Log2Dim> | ||
3009 | template<typename OtherChildAllIterType, typename VisitorOp> | ||
3010 | inline void | ||
3011 | InternalNode<ChildT, Log2Dim>::visit2(OtherChildAllIterType& otherIter, | ||
3012 | VisitorOp& op, bool otherIsLHS) | ||
3013 | { | ||
3014 |
2/8✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
4 | doVisit2<InternalNode, VisitorOp, ChildAllIter, OtherChildAllIterType>( |
3015 | *this, otherIter, op, otherIsLHS); | ||
3016 | 8 | } | |
3017 | |||
3018 | |||
3019 | template<typename ChildT, Index Log2Dim> | ||
3020 | template<typename OtherChildAllIterType, typename VisitorOp> | ||
3021 | inline void | ||
3022 | InternalNode<ChildT, Log2Dim>::visit2(OtherChildAllIterType& otherIter, | ||
3023 | VisitorOp& op, bool otherIsLHS) const | ||
3024 | { | ||
3025 | doVisit2<const InternalNode, VisitorOp, ChildAllCIter, OtherChildAllIterType>( | ||
3026 | *this, otherIter, op, otherIsLHS); | ||
3027 | } | ||
3028 | |||
3029 | |||
3030 | template<typename ChildT, Index Log2Dim> | ||
3031 | template<typename NodeT, typename VisitorOp, typename ChildAllIterT, typename OtherChildAllIterT> | ||
3032 | inline void | ||
3033 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
16 | InternalNode<ChildT, Log2Dim>::doVisit2(NodeT& self, OtherChildAllIterT& otherIter, |
3034 | VisitorOp& op, bool otherIsLHS) | ||
3035 | { | ||
3036 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
16 | if (!otherIter) return; |
3037 | |||
3038 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
|
16 | const size_t skipBitMask = (otherIsLHS ? 2U : 1U); |
3039 | |||
3040 | typename NodeT::ValueType val; | ||
3041 |
2/2✓ Branch 1 taken 147456 times.
✓ Branch 2 taken 8 times.
|
294944 | for (ChildAllIterT iter = self.beginChildAll(); iter; ++iter) { |
3042 | const size_t skipBranch = static_cast<size_t>( | ||
3043 |
2/2✓ Branch 0 taken 110592 times.
✓ Branch 1 taken 36864 times.
|
294912 | otherIsLHS ? op(otherIter, iter) : op(iter, otherIter)); |
3044 | |||
3045 | typename ChildAllIterT::ChildNodeType* child = | ||
3046 |
2/2✓ Branch 0 taken 143360 times.
✓ Branch 1 taken 4096 times.
|
294912 | (skipBranch & skipBitMask) ? nullptr : iter.probeChild(val); |
3047 | |||
3048 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 143353 times.
|
286720 | if (child != nullptr) child->visit2(otherIter, op, otherIsLHS); |
3049 | } | ||
3050 | } | ||
3051 | |||
3052 | |||
3053 | //////////////////////////////////////// | ||
3054 | |||
3055 | |||
3056 | template<typename ChildT, Index Log2Dim> | ||
3057 | inline void | ||
3058 | 2168 | InternalNode<ChildT, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const | |
3059 | { | ||
3060 |
2/2✓ Branch 0 taken 91958 times.
✓ Branch 1 taken 1084 times.
|
186084 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { |
3061 | 183916 | iter->writeBuffers(os, toHalf); | |
3062 | } | ||
3063 | } | ||
3064 | |||
3065 | |||
3066 | template<typename ChildT, Index Log2Dim> | ||
3067 | inline void | ||
3068 | 3706 | InternalNode<ChildT, Log2Dim>::readBuffers(std::istream& is, bool fromHalf) | |
3069 | { | ||
3070 |
2/2✓ Branch 0 taken 131427 times.
✓ Branch 1 taken 1853 times.
|
266560 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
3071 | 262854 | iter->readBuffers(is, fromHalf); | |
3072 | } | ||
3073 | } | ||
3074 | |||
3075 | |||
3076 | template<typename ChildT, Index Log2Dim> | ||
3077 | inline void | ||
3078 | 100 | InternalNode<ChildT, Log2Dim>::readBuffers(std::istream& is, | |
3079 | const CoordBBox& clipBBox, bool fromHalf) | ||
3080 | { | ||
3081 |
2/2✓ Branch 0 taken 376 times.
✓ Branch 1 taken 50 times.
|
852 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
3082 | // Stream in the branch rooted at this child. | ||
3083 | // (We can't skip over children that lie outside the clipping region, | ||
3084 | // because buffers are serialized in depth-first order and need to be | ||
3085 | // unserialized in the same order.) | ||
3086 | 752 | iter->readBuffers(is, clipBBox, fromHalf); | |
3087 | } | ||
3088 | |||
3089 | // Get this tree's background value. | ||
3090 | 100 | ValueType background = zeroVal<ValueType>(); | |
3091 |
1/4✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
100 | if (const void* bgPtr = io::getGridBackgroundValuePtr(is)) { |
3092 | 100 | background = *static_cast<const ValueType*>(bgPtr); | |
3093 | } | ||
3094 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
100 | this->clip(clipBBox, background); |
3095 | } | ||
3096 | |||
3097 | |||
3098 | //////////////////////////////////////// | ||
3099 | |||
3100 | |||
3101 | template<typename ChildT, Index Log2Dim> | ||
3102 | void | ||
3103 | 146844 | InternalNode<ChildT, Log2Dim>::getNodeLog2Dims(std::vector<Index>& dims) | |
3104 | { | ||
3105 | 146844 | dims.push_back(Log2Dim); | |
3106 | 73422 | ChildNodeType::getNodeLog2Dims(dims); | |
3107 | 146844 | } | |
3108 | |||
3109 | |||
3110 | template<typename ChildT, Index Log2Dim> | ||
3111 | inline void | ||
3112 | 446148910 | InternalNode<ChildT, Log2Dim>::offsetToLocalCoord(Index n, Coord &xyz) | |
3113 | { | ||
3114 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 223074455 times.
|
446148910 | assert(n<(1<<3*Log2Dim)); |
3115 | 446148910 | xyz.setX(n >> 2*Log2Dim); | |
3116 | 446148910 | n &= ((1<<2*Log2Dim)-1); | |
3117 | 446148910 | xyz.setY(n >> Log2Dim); | |
3118 | 446148910 | xyz.setZ(n & ((1<<Log2Dim)-1)); | |
3119 | 446148910 | } | |
3120 | |||
3121 | |||
3122 | template<typename ChildT, Index Log2Dim> | ||
3123 | inline Index | ||
3124 | InternalNode<ChildT, Log2Dim>::coordToOffset(const Coord& xyz) | ||
3125 | { | ||
3126 | 7671356178 | return (((xyz[0] & (DIM-1u)) >> ChildNodeType::TOTAL) << 2*Log2Dim) | |
3127 | 7671356178 | + (((xyz[1] & (DIM-1u)) >> ChildNodeType::TOTAL) << Log2Dim) | |
3128 | 7671356178 | + ((xyz[2] & (DIM-1u)) >> ChildNodeType::TOTAL); | |
3129 | } | ||
3130 | |||
3131 | |||
3132 | template<typename ChildT, Index Log2Dim> | ||
3133 | inline Coord | ||
3134 | 446083374 | InternalNode<ChildT, Log2Dim>::offsetToGlobalCoord(Index n) const | |
3135 | { | ||
3136 | Coord local; | ||
3137 | 446083374 | this->offsetToLocalCoord(n, local); | |
3138 | local <<= ChildT::TOTAL; | ||
3139 | 446083374 | return local + this->origin(); | |
3140 | } | ||
3141 | |||
3142 | |||
3143 | //////////////////////////////////////// | ||
3144 | |||
3145 | |||
3146 | template<typename ChildT, Index Log2Dim> | ||
3147 | template<typename ArrayT> | ||
3148 | inline void | ||
3149 | 139918 | InternalNode<ChildT, Log2Dim>::getNodes(ArrayT& array) | |
3150 | { | ||
3151 | using T = typename ArrayT::value_type; | ||
3152 | static_assert(std::is_pointer<T>::value, "argument to getNodes() must be a pointer array"); | ||
3153 | using ArrayChildT = typename std::conditional< | ||
3154 | std::is_const<typename std::remove_pointer<T>::type>::value, const ChildT, ChildT>::type; | ||
3155 |
2/2✓ Branch 0 taken 182528 times.
✓ Branch 1 taken 77204 times.
|
488923 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
3156 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
3157 | if (std::is_same<T, ArrayChildT*>::value) { | ||
3158 | 346253 | array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild())); | |
3159 | } else { | ||
3160 | 2752 | iter->getNodes(array);//descent | |
3161 | } | ||
3162 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
3163 | } | ||
3164 | 139918 | } | |
3165 | |||
3166 | template<typename ChildT, Index Log2Dim> | ||
3167 | template<typename ArrayT> | ||
3168 | inline void | ||
3169 | 7110 | InternalNode<ChildT, Log2Dim>::getNodes(ArrayT& array) const | |
3170 | { | ||
3171 | using T = typename ArrayT::value_type; | ||
3172 | static_assert(std::is_pointer<T>::value, "argument to getNodes() must be a pointer array"); | ||
3173 | static_assert(std::is_const<typename std::remove_pointer<T>::type>::value, | ||
3174 | "argument to getNodes() must be an array of const node pointers"); | ||
3175 |
2/2✓ Branch 0 taken 26603 times.
✓ Branch 1 taken 3555 times.
|
60316 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { |
3176 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
3177 | if (std::is_same<T, const ChildT*>::value) { | ||
3178 | 52844 | array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild())); | |
3179 | } else { | ||
3180 | 362 | iter->getNodes(array);//descent | |
3181 | } | ||
3182 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
3183 | } | ||
3184 | 7110 | } | |
3185 | |||
3186 | |||
3187 | //////////////////////////////////////// | ||
3188 | |||
3189 | |||
3190 | template<typename ChildT, Index Log2Dim> | ||
3191 | template<typename ArrayT> | ||
3192 | inline void | ||
3193 | 441638 | InternalNode<ChildT, Log2Dim>::stealNodes(ArrayT& array, const ValueType& value, bool state) | |
3194 | { | ||
3195 | using T = typename ArrayT::value_type; | ||
3196 | static_assert(std::is_pointer<T>::value, "argument to stealNodes() must be a pointer array"); | ||
3197 | using ArrayChildT = typename std::conditional< | ||
3198 | std::is_const<typename std::remove_pointer<T>::type>::value, const ChildT, ChildT>::type; | ||
3199 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN | ||
3200 |
2/2✓ Branch 0 taken 24981846 times.
✓ Branch 1 taken 220819 times.
|
50405330 | for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) { |
3201 | const Index n = iter.pos(); | ||
3202 | if (std::is_same<T, ArrayChildT*>::value) { | ||
3203 | 49652608 | array.push_back(reinterpret_cast<T>(mNodes[n].getChild())); | |
3204 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24826304 times.
|
49652608 | mValueMask.set(n, state); |
3205 | mNodes[n].setValue(value); | ||
3206 | } else { | ||
3207 | 311084 | iter->stealNodes(array, value, state);//descent | |
3208 | } | ||
3209 | } | ||
3210 | if (std::is_same<T, ArrayChildT*>::value) mChildMask.setOff(); | ||
3211 | OPENVDB_NO_UNREACHABLE_CODE_WARNING_END | ||
3212 | 441638 | } | |
3213 | |||
3214 | |||
3215 | //////////////////////////////////////// | ||
3216 | |||
3217 | |||
3218 | template<typename ChildT, Index Log2Dim> | ||
3219 | inline void | ||
3220 |
2/2✓ Branch 0 taken 732 times.
✓ Branch 1 taken 5763 times.
|
12990 | InternalNode<ChildT, Log2Dim>::resetBackground(const ValueType& oldBackground, |
3221 | const ValueType& newBackground) | ||
3222 | { | ||
3223 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 5763 times.
|
11570 | if (math::isExactlyEqual(oldBackground, newBackground)) return; |
3224 |
2/2✓ Branch 0 taken 462848 times.
✓ Branch 1 taken 22 times.
|
925740 | for (Index i = 0; i < NUM_VALUES; ++i) { |
3225 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 462844 times.
|
925696 | if (this->isChildMaskOn(i)) { |
3226 | 8 | mNodes[i].getChild()->resetBackground(oldBackground, newBackground); | |
3227 |
2/2✓ Branch 0 taken 462843 times.
✓ Branch 1 taken 1 times.
|
925688 | } else if (this->isValueMaskOff(i)) { |
3228 |
2/2✓ Branch 0 taken 176123 times.
✓ Branch 1 taken 286720 times.
|
925686 | if (math::isApproxEqual(mNodes[i].getValue(), oldBackground)) { |
3229 | mNodes[i].setValue(newBackground); | ||
3230 |
2/2✓ Branch 0 taken 98304 times.
✓ Branch 1 taken 188416 times.
|
573440 | } else if (math::isApproxEqual(mNodes[i].getValue(), math::negative(oldBackground))) { |
3231 | ✗ | mNodes[i].setValue(math::negative(newBackground)); | |
3232 | } | ||
3233 | } | ||
3234 | } | ||
3235 | } | ||
3236 | |||
3237 | template<typename ChildT, Index Log2Dim> | ||
3238 | template<typename OtherChildNodeType, Index OtherLog2Dim> | ||
3239 | inline bool | ||
3240 | 14612 | InternalNode<ChildT, Log2Dim>::hasSameTopology( | |
3241 | const InternalNode<OtherChildNodeType, OtherLog2Dim>* other) const | ||
3242 | { | ||
3243 |
3/4✓ Branch 0 taken 7298 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 7298 times.
✗ Branch 3 not taken.
|
29208 | if (Log2Dim != OtherLog2Dim || mChildMask != other->mChildMask || |
3244 | mValueMask != other->mValueMask) return false; | ||
3245 |
2/2✓ Branch 0 taken 11843 times.
✓ Branch 1 taken 7298 times.
|
38282 | for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) { |
3246 |
2/3✗ Branch 0 not taken.
✓ Branch 1 taken 1440 times.
✓ Branch 2 taken 10403 times.
|
23686 | if (!iter->hasSameTopology(other->mNodes[iter.pos()].getChild())) return false; |
3247 | } | ||
3248 | 14596 | return true; | |
3249 | } | ||
3250 | |||
3251 | |||
3252 | template<typename ChildT, Index Log2Dim> | ||
3253 | inline void | ||
3254 | 151158 | InternalNode<ChildT, Log2Dim>::resetChildNode(Index i, ChildNodeType* child) | |
3255 | { | ||
3256 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75579 times.
|
151158 | assert(child); |
3257 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 75578 times.
|
151158 | if (this->isChildMaskOn(i)) { |
3258 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
4 | delete mNodes[i].getChild(); |
3259 | } else { | ||
3260 | 151156 | mChildMask.setOn(i); | |
3261 | 151156 | mValueMask.setOff(i); | |
3262 | } | ||
3263 | mNodes[i].setChild(child); | ||
3264 | 151158 | } | |
3265 | |||
3266 | template<typename ChildT, Index Log2Dim> | ||
3267 | inline void | ||
3268 | 6285596 | InternalNode<ChildT, Log2Dim>::setChildNode(Index i, ChildNodeType* child) | |
3269 | { | ||
3270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3142798 times.
|
6285596 | assert(child); |
3271 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3142798 times.
|
6285596 | assert(mChildMask.isOff(i)); |
3272 | 6285596 | mChildMask.setOn(i); | |
3273 | 6285596 | mValueMask.setOff(i); | |
3274 | mNodes[i].setChild(child); | ||
3275 | 6285596 | } | |
3276 | |||
3277 | |||
3278 | template<typename ChildT, Index Log2Dim> | ||
3279 | inline ChildT* | ||
3280 | 11810394 | InternalNode<ChildT, Log2Dim>::unsetChildNode(Index i, const ValueType& value) | |
3281 | { | ||
3282 |
2/2✓ Branch 0 taken 5868325 times.
✓ Branch 1 taken 36872 times.
|
11810394 | if (this->isChildMaskOff(i)) { |
3283 | mNodes[i].setValue(value); | ||
3284 | 11736650 | return nullptr; | |
3285 | } | ||
3286 | ChildNodeType* child = mNodes[i].getChild(); | ||
3287 | 73744 | mChildMask.setOff(i); | |
3288 | mNodes[i].setValue(value); | ||
3289 | 73744 | return child; | |
3290 | } | ||
3291 | |||
3292 | |||
3293 | template<typename ChildT, Index Log2Dim> | ||
3294 | inline void | ||
3295 | 11810394 | InternalNode<ChildT, Log2Dim>::makeChildNodeEmpty(Index n, const ValueType& value) | |
3296 | { | ||
3297 |
2/2✓ Branch 1 taken 36872 times.
✓ Branch 2 taken 5868325 times.
|
11869202 | delete this->unsetChildNode(n, value); |
3298 | 11810394 | } | |
3299 | |||
3300 | template<typename ChildT, Index Log2Dim> | ||
3301 | inline ChildT* | ||
3302 | 43990496 | InternalNode<ChildT, Log2Dim>::getChildNode(Index n) | |
3303 | { | ||
3304 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21905157 times.
|
43990496 | assert(this->isChildMaskOn(n)); |
3305 | 43990496 | return mNodes[n].getChild(); | |
3306 | } | ||
3307 | |||
3308 | |||
3309 | template<typename ChildT, Index Log2Dim> | ||
3310 | inline const ChildT* | ||
3311 | 46776752 | InternalNode<ChildT, Log2Dim>::getChildNode(Index n) const | |
3312 | { | ||
3313 | 46776752 | assert(this->isChildMaskOn(n)); | |
3314 | 46776752 | return mNodes[n].getChild(); | |
3315 | } | ||
3316 | |||
3317 | } // namespace tree | ||
3318 | } // namespace OPENVDB_VERSION_NAME | ||
3319 | } // namespace openvdb | ||
3320 | |||
3321 | #endif // OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED | ||
3322 |