OpenVDB: openvdb/tree/Tree.h Source File

OpenVDB 13.0.0

Loading...
Searching...
No Matches
Tree.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/// @file tree/Tree.h
5
6#ifndef OPENVDB_TREE_TREE_HAS_BEEN_INCLUDED
7#define OPENVDB_TREE_TREE_HAS_BEEN_INCLUDED
8
9#include <openvdb/Types.h>
10#include <openvdb/Metadata.h>
11#include <openvdb/math/Math.h>
12#include <openvdb/math/BBox.h>
13#include <openvdb/tools/Count.h> // tools::countActiveVoxels(), tools::memUsage(), tools::minMax()
14#include <openvdb/util/Formats.h>
15#include <openvdb/util/logging.h>
16#include <openvdb/util/Assert.h>
17#include <openvdb/Platform.h>
18#include "RootNode.h"
19#include "InternalNode.h"
20#include "LeafNode.h"
21#include "TreeIterator.h"
22#include "ValueAccessor.h"
23#include <tbb/concurrent_hash_map.h>
24#include <cstdint>
25#include <iostream>
26#include <mutex>
27#include <sstream>
28#include <vector>
29
30
31namespace openvdb {
32 OPENVDB_USE_VERSION_NAMESPACE
33namespace OPENVDB_VERSION_NAME {
34namespace tree {
35
36/// @brief Base class for typed trees
37 class OPENVDB_API TreeBase
38{
39public:
40 using Ptr = SharedPtr<TreeBase>;
41 using ConstPtr = SharedPtr<const TreeBase>;
42
43 TreeBase() = default;
44 TreeBase(const TreeBase&) = default;
45 TreeBase& operator=(const TreeBase&) = delete; // disallow assignment
46 virtual ~TreeBase() = default;
47
48 /// Return the name of this tree's type.
49 virtual const Name& type() const = 0;
50
51 /// Return the name of the type of a voxel's value (e.g., "float" or "vec3d").
52 virtual Name valueType() const = 0;
53
54 /// Return @c true if this tree is of the same type as the template parameter.
55 template<typename TreeType>
56 bool isType() const { return (this->type() == TreeType::treeType()); }
57
58 /// Return a pointer to a deep copy of this tree
59 virtual TreeBase::Ptr copy() const = 0;
60
61 //
62 // Tree methods
63 //
64 /// @brief Return this tree's background value wrapped as metadata.
65 /// @note Query the metadata object for the value's type.
66 virtual Metadata::Ptr getBackgroundValue() const { return Metadata::Ptr(); }
67
68 /// @brief Return in @a bbox the axis-aligned bounding box of all
69 /// active tiles and leaf nodes with active values.
70 /// @details This is faster than calling evalActiveVoxelBoundingBox,
71 /// which visits the individual active voxels, and hence
72 /// evalLeafBoundingBox produces a less tight, i.e. approximate, bbox.
73 /// @return @c false if the bounding box is empty (in which case
74 /// the bbox is set to its default value).
75 virtual bool evalLeafBoundingBox(CoordBBox& bbox) const = 0;
76
77 /// @brief Return in @a dim the dimensions of the axis-aligned bounding box
78 /// of all leaf nodes.
79 /// @return @c false if the bounding box is empty.
80 virtual bool evalLeafDim(Coord& dim) const = 0;
81
82 /// @brief Return in @a bbox the axis-aligned bounding box of all
83 /// active voxels and tiles.
84 /// @details This method produces a more accurate, i.e. tighter,
85 /// bounding box than evalLeafBoundingBox which is approximate but
86 /// faster.
87 /// @return @c false if the bounding box is empty (in which case
88 /// the bbox is set to its default value).
89 virtual bool evalActiveVoxelBoundingBox(CoordBBox& bbox) const = 0;
90
91 /// @brief Return in @a dim the dimensions of the axis-aligned bounding box of all
92 /// active voxels. This is a tighter bounding box than the leaf node bounding box.
93 /// @return @c false if the bounding box is empty.
94 virtual bool evalActiveVoxelDim(Coord& dim) const = 0;
95
96 virtual void getIndexRange(CoordBBox& bbox) const = 0;
97
98 /// @brief Replace with background tiles any nodes whose voxel buffers
99 /// have not yet been allocated.
100 /// @details Typically, unallocated nodes are leaf nodes whose voxel buffers
101 /// are not yet resident in memory because delayed loading is in effect.
102 /// @sa readNonresidentBuffers, io::File::open
103 virtual void clipUnallocatedNodes() = 0;
104 /// Return the total number of unallocated leaf nodes residing in this tree.
105#if OPENVDB_ABI_VERSION_NUMBER >= 12
106 virtual Index64 unallocatedLeafCount() const = 0;
107#else
108 virtual Index32 unallocatedLeafCount() const = 0;
109#endif
110
111
112 //
113 // Statistics
114 //
115 /// @brief Return the depth of this tree.
116 ///
117 /// A tree with only a root node and leaf nodes has depth 2, for example.
118 virtual Index treeDepth() const = 0;
119 /// Return the number of leaf nodes.
120#if OPENVDB_ABI_VERSION_NUMBER >= 12
121 virtual Index64 leafCount() const = 0;
122#else
123 virtual Index32 leafCount() const = 0;
124#endif
125 /// Return a vector with node counts. The number of nodes of type NodeType
126 /// is given as element NodeType::LEVEL in the return vector. Thus, the size
127 /// of this vector corresponds to the height (or depth) of this tree.
128#if OPENVDB_ABI_VERSION_NUMBER >= 12
129 virtual std::vector<Index64> nodeCount() const = 0;
130#else
131 virtual std::vector<Index32> nodeCount() const = 0;
132#endif
133 /// Return the number of non-leaf nodes.
134#if OPENVDB_ABI_VERSION_NUMBER >= 12
135 virtual Index64 nonLeafCount() const = 0;
136#else
137 virtual Index32 nonLeafCount() const = 0;
138#endif
139 /// Return the number of active voxels stored in leaf nodes.
140 virtual Index64 activeLeafVoxelCount() const = 0;
141 /// Return the number of inactive voxels stored in leaf nodes.
142 virtual Index64 inactiveLeafVoxelCount() const = 0;
143 /// Return the total number of active voxels.
144 virtual Index64 activeVoxelCount() const = 0;
145 /// Return the number of inactive voxels within the bounding box of all active voxels.
146 virtual Index64 inactiveVoxelCount() const = 0;
147 /// Return the total number of active tiles.
148 virtual Index64 activeTileCount() const = 0;
149
150 /// Return the total amount of memory in bytes occupied by this tree.
151 virtual Index64 memUsage() const { return 0; }
152
153
154 //
155 // I/O methods
156 //
157 /// @brief Read the tree topology from a stream.
158 ///
159 /// This will read the tree structure and tile values, but not voxel data.
160 virtual void readTopology(std::istream&, bool saveFloatAsHalf = false);
161 /// @brief Write the tree topology to a stream.
162 ///
163 /// This will write the tree structure and tile values, but not voxel data.
164 virtual void writeTopology(std::ostream&, bool saveFloatAsHalf = false) const;
165
166 /// Read all data buffers for this tree.
167 virtual void readBuffers(std::istream&, bool saveFloatAsHalf = false) = 0;
168 /// Read all of this tree's data buffers that intersect the given bounding box.
169 virtual void readBuffers(std::istream&, const CoordBBox&, bool saveFloatAsHalf = false) = 0;
170 /// @brief Read all of this tree's data buffers that are not yet resident in memory
171 /// (because delayed loading is in effect).
172 /// @details If this tree was read from a memory-mapped file, this operation
173 /// disconnects the tree from the file.
174 /// @sa clipUnallocatedNodes, io::File::open, io::MappedFile
175 virtual void readNonresidentBuffers() const = 0;
176 /// Write out all the data buffers for this tree.
177 virtual void writeBuffers(std::ostream&, bool saveFloatAsHalf = false) const = 0;
178
179 /// @brief Print statistics, memory usage and other information about this tree.
180 /// @param os a stream to which to write textual information
181 /// @param verboseLevel 1: print tree configuration only;
182 /// 2: include node and voxel statistics;
183 /// 3: include memory usage;
184 /// 4: include minimum and maximum voxel values
185 /// @warning @a verboseLevel 4 forces loading of any unallocated nodes.
186 virtual void print(std::ostream& os = std::cout, int verboseLevel = 1) const;
187};
188
189
190////////////////////////////////////////
191
192
193template<typename _RootNodeType>
194 class Tree: public TreeBase
195{
196public:
197 using Ptr = SharedPtr<Tree>;
198 using ConstPtr = SharedPtr<const Tree>;
199
200 using RootNodeType = _RootNodeType;
201 using ValueType = typename RootNodeType::ValueType;
202 using BuildType = typename RootNodeType::BuildType;
203 using LeafNodeType = typename RootNodeType::LeafNodeType;
204
205 static const Index DEPTH = RootNodeType::LEVEL + 1;
206
207 using Accessor = ValueAccessor<Tree, true>;
208 using ConstAccessor = ValueAccessor<const Tree, true>;
209 using UnsafeAccessor = ValueAccessor<Tree, false>;
210 using ConstUnsafeAccessor = ValueAccessor<const Tree, false>;
211
212 /// @brief ValueConverter<T>::Type is the type of a tree having the same
213 /// hierarchy as this tree but a different value type, T.
214 ///
215 /// For example, FloatTree::ValueConverter<double>::Type is equivalent to DoubleTree.
216 /// @note If the source tree type is a template argument, it might be necessary
217 /// to write "typename SourceTree::template ValueConverter<T>::Type".
218 template<typename OtherValueType>
219 struct ValueConverter {
220 using Type = Tree<typename RootNodeType::template ValueConverter<OtherValueType>::Type>;
221 };
222
223
224 Tree() {}
225
226 Tree& operator=(const Tree&) = delete; // disallow assignment
227
228 /// Deep copy constructor
229 Tree(const Tree& other): TreeBase(other), mRoot(other.mRoot)
230 {
231 }
232
233 /// @brief Value conversion deep copy constructor
234 ///
235 /// Deep copy a tree of the same configuration as this tree type but a different
236 /// ValueType, casting the other tree's values to this tree's ValueType.
237 /// @throw TypeError if the other tree's configuration doesn't match this tree's
238 /// or if this tree's ValueType is not constructible from the other tree's ValueType.
239 template<typename OtherRootType>
240 explicit Tree(const Tree<OtherRootType>& other): TreeBase(other), mRoot(other.root())
241 {
242 }
243
244 /// @brief Topology copy constructor from a tree of a different type
245 ///
246 /// Copy the structure, i.e., the active states of tiles and voxels, of another
247 /// tree of a possibly different type, but don't copy any tile or voxel values.
248 /// Instead, initialize tiles and voxels with the given active and inactive values.
249 /// @param other a tree having (possibly) a different ValueType
250 /// @param inactiveValue background value for this tree, and the value to which
251 /// all inactive tiles and voxels are initialized
252 /// @param activeValue value to which active tiles and voxels are initialized
253 /// @throw TypeError if the other tree's configuration doesn't match this tree's.
254 template<typename OtherTreeType>
255 Tree(const OtherTreeType& other,
256 const ValueType& inactiveValue,
257 const ValueType& activeValue,
258 TopologyCopy):
259 TreeBase(other),
260 mRoot(other.root(), inactiveValue, activeValue, TopologyCopy())
261 {
262 }
263
264 /// @brief Topology copy constructor from a tree of a different type
265 ///
266 /// @note This topology copy constructor is generally faster than
267 /// the one that takes both a foreground and a background value.
268 ///
269 /// Copy the structure, i.e., the active states of tiles and voxels, of another
270 /// tree of a possibly different type, but don't copy any tile or voxel values.
271 /// Instead, initialize tiles and voxels with the given background value.
272 /// @param other a tree having (possibly) a different ValueType
273 /// @param background the value to which tiles and voxels are initialized
274 /// @throw TypeError if the other tree's configuration doesn't match this tree's.
275 template<typename OtherTreeType>
276 Tree(const OtherTreeType& other, const ValueType& background, TopologyCopy):
277 TreeBase(other),
278 mRoot(other.root(), background, TopologyCopy())
279 {
280 }
281
282 /// Empty tree constructor
283 Tree(const ValueType& background): mRoot(background) {}
284
285 ~Tree() override { this->clear(); releaseAllAccessors(); }
286
287 /// Return a pointer to a deep copy of this tree
288 TreeBase::Ptr copy() const override { return TreeBase::Ptr(new Tree(*this)); }
289
290 /// Return the name of the type of a voxel's value (e.g., "float" or "vec3d")
291 Name valueType() const override { return typeNameAsString<ValueType>(); }
292
293 /// Return the name of this type of tree.
294 static const Name& treeType();
295 /// Return the name of this type of tree.
296 const Name& type() const override { return this->treeType(); }
297
298 bool operator==(const Tree&) const { OPENVDB_THROW(NotImplementedError, ""); }
299 bool operator!=(const Tree&) const { OPENVDB_THROW(NotImplementedError, ""); }
300
301 //@{
302 /// Return this tree's root node.
303 RootNodeType& root() { return mRoot; }
304 const RootNodeType& root() const { return mRoot; }
305 //@}
306
307
308 //
309 // Tree methods
310 //
311 /// @brief Return @c true if the given tree has the same node and active value
312 /// topology as this tree, whether or not it has the same @c ValueType.
313 template<typename OtherRootNodeType>
314 bool hasSameTopology(const Tree<OtherRootNodeType>& other) const;
315
316 bool evalLeafBoundingBox(CoordBBox& bbox) const override;
317 bool evalActiveVoxelBoundingBox(CoordBBox& bbox) const override;
318 bool evalActiveVoxelDim(Coord& dim) const override;
319 bool evalLeafDim(Coord& dim) const override;
320
321 /// @brief Traverse the type hierarchy of nodes, and return, in @a dims, a list
322 /// of the Log2Dims of nodes in order from RootNode to LeafNode.
323 /// @note Because RootNodes are resizable, the RootNode Log2Dim is 0 for all trees.
324 static void getNodeLog2Dims(std::vector<Index>& dims);
325
326
327 //
328 // I/O methods
329 //
330 /// @brief Read the tree topology from a stream.
331 ///
332 /// This will read the tree structure and tile values, but not voxel data.
333 void readTopology(std::istream&, bool saveFloatAsHalf = false) override;
334 /// @brief Write the tree topology to a stream.
335 ///
336 /// This will write the tree structure and tile values, but not voxel data.
337 void writeTopology(std::ostream&, bool saveFloatAsHalf = false) const override;
338 /// Read all data buffers for this tree.
339 void readBuffers(std::istream&, bool saveFloatAsHalf = false) override;
340 /// Read all of this tree's data buffers that intersect the given bounding box.
341 void readBuffers(std::istream&, const CoordBBox&, bool saveFloatAsHalf = false) override;
342 /// @brief Read all of this tree's data buffers that are not yet resident in memory
343 /// (because delayed loading is in effect).
344 /// @details If this tree was read from a memory-mapped file, this operation
345 /// disconnects the tree from the file.
346 /// @sa clipUnallocatedNodes, io::File::open, io::MappedFile
347 void readNonresidentBuffers() const override;
348 /// Write out all data buffers for this tree.
349 void writeBuffers(std::ostream&, bool saveFloatAsHalf = false) const override;
350
351 void print(std::ostream& os = std::cout, int verboseLevel = 1) const override;
352
353
354 //
355 // Statistics
356 //
357 /// @brief Return the depth of this tree.
358 ///
359 /// A tree with only a root node and leaf nodes has depth 2, for example.
360 Index treeDepth() const override { return DEPTH; }
361 /// Return the number of leaf nodes.
362#if OPENVDB_ABI_VERSION_NUMBER >= 12
363 Index64 leafCount() const override { return mRoot.leafCount(); }
364#else
365 Index32 leafCount() const override { return static_cast<Index32>(mRoot.leafCount()); }
366#endif
367 /// Return a vector with node counts. The number of nodes of type NodeType
368 /// is given as element NodeType::LEVEL in the return vector. Thus, the size
369 /// of this vector corresponds to the height (or depth) of this tree.
370#if OPENVDB_ABI_VERSION_NUMBER >= 12
371 std::vector<Index64> nodeCount() const override
372 {
373 std::vector<Index64> vec(DEPTH, 0);
374 mRoot.nodeCount( vec );
375 return vec;// Named Return Value Optimization
376 }
377#else
378 std::vector<Index32> nodeCount() const override
379 {
380 std::vector<Index32> vec(DEPTH, 0);
381 OPENVDB_NO_DEPRECATION_WARNING_BEGIN
382 mRoot.nodeCount( vec );
383 OPENVDB_NO_DEPRECATION_WARNING_END
384 return vec;// Named Return Value Optimization
385 }
386#endif
387 /// Return the number of non-leaf nodes.
388#if OPENVDB_ABI_VERSION_NUMBER >= 12
389 Index64 nonLeafCount() const override { return mRoot.nonLeafCount(); }
390#else
391 Index32 nonLeafCount() const override { return static_cast<Index32>(mRoot.nonLeafCount()); }
392#endif
393 /// Return the number of active voxels stored in leaf nodes.
394 Index64 activeLeafVoxelCount() const override { return tools::countActiveLeafVoxels(*this); }
395 /// Return the number of inactive voxels stored in leaf nodes.
396 Index64 inactiveLeafVoxelCount() const override { return tools::countInactiveLeafVoxels(*this); }
397 /// Return the total number of active voxels.
398 Index64 activeVoxelCount() const override { return tools::countActiveVoxels(*this); }
399 /// Return the number of inactive voxels within the bounding box of all active voxels.
400 Index64 inactiveVoxelCount() const override { return tools::countInactiveVoxels(*this); }
401 /// Return the total number of active tiles.
402 Index64 activeTileCount() const override { return tools::countActiveTiles(*this); }
403
404 Index64 memUsage() const override { return tools::memUsage(*this); }
405
406
407 //
408 // Voxel access methods (using signed indexing)
409 //
410 /// Return the value of the voxel at the given coordinates.
411 const ValueType& getValue(const Coord& xyz) const;
412 /// @brief Return the value of the voxel at the given coordinates
413 /// and update the given accessor's node cache.
414 template<typename AccessT> const ValueType& getValue(const Coord& xyz, AccessT&) const;
415
416 /// @brief Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides.
417 /// @details If (x, y, z) isn't explicitly represented in the tree (i.e., it is
418 /// implicitly a background voxel), return -1.
419 int getValueDepth(const Coord& xyz) const;
420
421 /// Set the active state of the voxel at the given coordinates but don't change its value.
422 void setActiveState(const Coord& xyz, bool on);
423 /// Set the value of the voxel at the given coordinates but don't change its active state.
424 void setValueOnly(const Coord& xyz, const ValueType& value);
425 /// Mark the voxel at the given coordinates as active but don't change its value.
426 void setValueOn(const Coord& xyz);
427 /// Set the value of the voxel at the given coordinates and mark the voxel as active.
428 void setValueOn(const Coord& xyz, const ValueType& value);
429 /// Set the value of the voxel at the given coordinates and mark the voxel as active.
430 void setValue(const Coord& xyz, const ValueType& value);
431 /// @brief Set the value of the voxel at the given coordinates, mark the voxel as active,
432 /// and update the given accessor's node cache.
433 template<typename AccessT> void setValue(const Coord& xyz, const ValueType& value, AccessT&);
434 /// Mark the voxel at the given coordinates as inactive but don't change its value.
435 void setValueOff(const Coord& xyz);
436 /// Set the value of the voxel at the given coordinates and mark the voxel as inactive.
437 void setValueOff(const Coord& xyz, const ValueType& value);
438
439 /// @brief Apply a functor to the value of the voxel at the given coordinates
440 /// and mark the voxel as active.
441 /// @details Provided that the functor can be inlined, this is typically
442 /// significantly faster than calling getValue() followed by setValueOn().
443 /// @param xyz the coordinates of a voxel whose value is to be modified
444 /// @param op a functor of the form <tt>void op(ValueType&) const</tt> that modifies
445 /// its argument in place
446 /// @par Example:
447 /// @code
448 /// Coord xyz(1, 0, -2);
449 /// // Multiply the value of a voxel by a constant and mark the voxel as active.
450 /// floatTree.modifyValue(xyz, [](float& f) { f *= 0.25; }); // C++11
451 /// // Set the value of a voxel to the maximum of its current value and 0.25,
452 /// // and mark the voxel as active.
453 /// floatTree.modifyValue(xyz, [](float& f) { f = std::max(f, 0.25f); }); // C++11
454 /// @endcode
455 /// @note The functor is not guaranteed to be called only once.
456 /// @see tools::foreach()
457 template<typename ModifyOp>
458 void modifyValue(const Coord& xyz, const ModifyOp& op);
459
460 /// @brief Apply a functor to the voxel at the given coordinates.
461 /// @details Provided that the functor can be inlined, this is typically
462 /// significantly faster than calling getValue() followed by setValue().
463 /// @param xyz the coordinates of a voxel to be modified
464 /// @param op a functor of the form <tt>void op(ValueType&, bool&) const</tt> that
465 /// modifies its arguments, a voxel's value and active state, in place
466 /// @par Example:
467 /// @code
468 /// Coord xyz(1, 0, -2);
469 /// // Multiply the value of a voxel by a constant and mark the voxel as inactive.
470 /// floatTree.modifyValueAndActiveState(xyz,
471 /// [](float& f, bool& b) { f *= 0.25; b = false; }); // C++11
472 /// // Set the value of a voxel to the maximum of its current value and 0.25,
473 /// // but don't change the voxel's active state.
474 /// floatTree.modifyValueAndActiveState(xyz,
475 /// [](float& f, bool&) { f = std::max(f, 0.25f); }); // C++11
476 /// @endcode
477 /// @note The functor is not guaranteed to be called only once.
478 /// @see tools::foreach()
479 template<typename ModifyOp>
480 void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op);
481
482 /// @brief Get the value of the voxel at the given coordinates.
483 /// @return @c true if the value is active.
484 bool probeValue(const Coord& xyz, ValueType& value) const;
485
486 /// Return @c true if the value at the given coordinates is active.
487 bool isValueOn(const Coord& xyz) const { return mRoot.isValueOn(xyz); }
488 /// Return @c true if the value at the given coordinates is inactive.
489 bool isValueOff(const Coord& xyz) const { return !this->isValueOn(xyz); }
490 /// Return @c true if this tree has any active tiles.
491 bool hasActiveTiles() const { return mRoot.hasActiveTiles(); }
492
493 /// Set all voxels that lie outside the given axis-aligned box to the background.
494 void clip(const CoordBBox&);
495 /// @brief Replace with background tiles any nodes whose voxel buffers
496 /// have not yet been allocated.
497 /// @details Typically, unallocated nodes are leaf nodes whose voxel buffers
498 /// are not yet resident in memory because delayed loading is in effect.
499 /// @sa readNonresidentBuffers, io::File::open
500 void clipUnallocatedNodes() override;
501
502 /// Return the total number of unallocated leaf nodes residing in this tree.
503#if OPENVDB_ABI_VERSION_NUMBER >= 12
504 Index64 unallocatedLeafCount() const override;
505#else
506 Index32 unallocatedLeafCount() const override;
507#endif
508
509 //@{
510 /// @brief Set all voxels within a given axis-aligned box to a constant value.
511 /// @param bbox inclusive coordinates of opposite corners of an axis-aligned box
512 /// @param value the value to which to set voxels within the box
513 /// @param active if true, mark voxels within the box as active,
514 /// otherwise mark them as inactive
515 /// @note This operation generates a sparse, but not always optimally sparse,
516 /// representation of the filled box. Follow fill operations with a prune()
517 /// operation for optimal sparseness.
518 void sparseFill(const CoordBBox& bbox, const ValueType& value, bool active = true);
519 void fill(const CoordBBox& bbox, const ValueType& value, bool active = true)
520 {
521 this->sparseFill(bbox, value, active);
522 }
523 //@}
524
525 /// @brief Set all voxels within a given axis-aligned box to a constant value
526 /// and ensure that those voxels are all represented at the leaf level.
527 /// @param bbox inclusive coordinates of opposite corners of an axis-aligned box.
528 /// @param value the value to which to set voxels within the box.
529 /// @param active if true, mark voxels within the box as active,
530 /// otherwise mark them as inactive.
531 /// @sa voxelizeActiveTiles()
532 void denseFill(const CoordBBox& bbox, const ValueType& value, bool active = true);
533
534 /// @brief Densify active tiles, i.e., replace them with leaf-level active voxels.
535 ///
536 /// @param threaded if true, this operation is multi-threaded (over the internal nodes).
537 ///
538 /// @warning This method can explode the tree's memory footprint, especially if it
539 /// contains active tiles at the upper levels (in particular the root level)!
540 ///
541 /// @sa denseFill()
542 void voxelizeActiveTiles(bool threaded = true);
543
544 /// @brief Reduce the memory footprint of this tree by replacing with tiles
545 /// any nodes whose values are all the same (optionally to within a tolerance)
546 /// and have the same active state.
547 /// @warning Will soon be deprecated!
548 void prune(const ValueType& tolerance = zeroVal<ValueType>())
549 {
550 this->clearAllAccessors();
551 mRoot.prune(tolerance);
552 }
553
554 /// @brief Add the given leaf node to this tree, creating a new branch if necessary.
555 /// If a leaf node with the same origin already exists, replace it.
556 ///
557 /// @warning Ownership of the leaf is transferred to the tree so
558 /// the client code should not attempt to delete the leaf pointer!
559 void addLeaf(LeafNodeType* leaf) { OPENVDB_ASSERT(leaf); mRoot.addLeaf(leaf); }
560
561 /// @brief Add a tile containing voxel (x, y, z) at the specified tree level,
562 /// creating a new branch if necessary. Delete any existing lower-level nodes
563 /// that contain (x, y, z).
564 /// @note @a level must be less than this tree's depth.
565 void addTile(Index level, const Coord& xyz, const ValueType& value, bool active);
566
567 /// @brief Return a pointer to the node of type @c NodeT that contains voxel (x, y, z)
568 /// and replace it with a tile of the specified value and state.
569 /// If no such node exists, leave the tree unchanged and return @c nullptr.
570 /// @note The caller takes ownership of the node and is responsible for deleting it.
571 template<typename NodeT>
572 NodeT* stealNode(const Coord& xyz, const ValueType& value, bool active);
573
574 /// @brief Return a pointer to the leaf node that contains voxel (x, y, z).
575 /// If no such node exists, create one that preserves the values and
576 /// active states of all voxels.
577 /// @details Use this method to preallocate a static tree topology over which to
578 /// safely perform multithreaded processing.
579 LeafNodeType* touchLeaf(const Coord& xyz);
580
581 //@{
582 /// @brief Return a pointer to the node of type @c NodeType that contains
583 /// voxel (x, y, z). If no such node exists, return @c nullptr.
584 template<typename NodeType> NodeType* probeNode(const Coord& xyz);
585 template<typename NodeType> const NodeType* probeConstNode(const Coord& xyz) const;
586 template<typename NodeType> const NodeType* probeNode(const Coord& xyz) const;
587 //@}
588
589 //@{
590 /// @brief Return a pointer to the leaf node that contains voxel (x, y, z).
591 /// If no such node exists, return @c nullptr.
592 LeafNodeType* probeLeaf(const Coord& xyz);
593 const LeafNodeType* probeConstLeaf(const Coord& xyz) const;
594 const LeafNodeType* probeLeaf(const Coord& xyz) const { return this->probeConstLeaf(xyz); }
595 //@}
596
597 //@{
598 /// @brief Adds all nodes of a certain type to a container with the following API:
599 /// @code
600 /// struct ArrayT {
601 /// using value_type = ...; // the type of node to be added to the array
602 /// void push_back(value_type nodePtr); // add a node to the array
603 /// };
604 /// @endcode
605 /// @details An example of a wrapper around a c-style array is:
606 /// @code
607 /// struct MyArray {
608 /// using value_type = LeafType*;
609 /// value_type* ptr;
610 /// MyArray(value_type* array) : ptr(array) {}
611 /// void push_back(value_type leaf) { *ptr++ = leaf; }
612 ///};
613 /// @endcode
614 /// @details An example that constructs a list of pointer to all leaf nodes is:
615 /// @code
616 /// std::vector<const LeafNodeType*> array;//most std contains have the required API
617 /// array.reserve(tree.leafCount());//this is a fast preallocation.
618 /// tree.getNodes(array);
619 /// @endcode
620 template<typename ArrayT> void getNodes(ArrayT& array);
621 template<typename ArrayT> void getNodes(ArrayT& array) const;
622 //@}
623
624 /// @brief Steals all nodes of a certain type from the tree and
625 /// adds them to a container with the following API:
626 /// @code
627 /// struct ArrayT {
628 /// using value_type = ...; // the type of node to be added to the array
629 /// void push_back(value_type nodePtr); // add a node to the array
630 /// };
631 /// @endcode
632 /// @details An example of a wrapper around a c-style array is:
633 /// @code
634 /// struct MyArray {
635 /// using value_type = LeafType*;
636 /// value_type* ptr;
637 /// MyArray(value_type* array) : ptr(array) {}
638 /// void push_back(value_type leaf) { *ptr++ = leaf; }
639 ///};
640 /// @endcode
641 /// @details An example that constructs a list of pointer to all leaf nodes is:
642 /// @code
643 /// std::vector<const LeafNodeType*> array;//most std contains have the required API
644 /// array.reserve(tree.leafCount());//this is a fast preallocation.
645 /// tree.stealNodes(array);
646 /// @endcode
647 template<typename ArrayT>
648 void stealNodes(ArrayT& array) { this->clearAllAccessors(); mRoot.stealNodes(array); }
649 template<typename ArrayT>
650 void stealNodes(ArrayT& array, const ValueType& value, bool state)
651 {
652 this->clearAllAccessors();
653 mRoot.stealNodes(array, value, state);
654 }
655
656 //
657 // Aux methods
658 //
659 /// @brief Return @c true if this tree contains no nodes other than
660 /// the root node and no tiles other than background tiles.
661 bool empty() const { return mRoot.empty(); }
662
663 /// Remove all tiles from this tree and all nodes other than the root node.
664 void clear();
665
666 /// @brief Return an accessor that provides random read and write access
667 /// to this tree's voxels.
668 /// @details The accessor is safe in the sense that it is registered with this tree.
669 Accessor getAccessor();
670 /// @brief Return an unsafe accessor that provides random read and write access
671 /// to this tree's voxels.
672 /// @details The accessor is unsafe in the sense that it is not registered
673 /// with this tree's tree. In some rare cases this can give a performance advantage
674 /// over a registered accessor, but it is unsafe if the tree topology is modified.
675 /// @warning Only use this method if you're an expert and know the
676 /// risks of using an unregistered accessor (see tree/ValueAccessor.h)
677 UnsafeAccessor getUnsafeAccessor();
678 /// Return an accessor that provides random read-only access to this tree's voxels.
679 ConstAccessor getAccessor() const;
680 /// Return an accessor that provides random read-only access to this tree's voxels.
681 ConstAccessor getConstAccessor() const;
682 /// @brief Return an unsafe accessor that provides random read-only access
683 /// to this tree's voxels.
684 /// @details The accessor is unsafe in the sense that it is not registered
685 /// with this tree. In some rare cases this can give a performance advantage
686 /// over a registered accessor, but it is unsafe if the tree topology is modified.
687 /// @warning Only use this method if you're an expert and know the
688 /// risks of using an unregistered accessor (see tree/ValueAccessor.h)
689 ConstUnsafeAccessor getConstUnsafeAccessor();
690
691 /// Clear all registered accessors.
692 void clearAllAccessors();
693
694 //@{
695 /// @brief Register an accessor for this tree. Registered accessors are
696 /// automatically cleared whenever one of this tree's nodes is deleted.
697 void attachAccessor(ValueAccessorBase<Tree, true>&) const;
698 void attachAccessor(ValueAccessorBase<const Tree, true>&) const;
699 //@}
700
701 //@{
702 /// Dummy implementations
703 void attachAccessor(ValueAccessorBase<Tree, false>&) const {}
704 void attachAccessor(ValueAccessorBase<const Tree, false>&) const {}
705 //@}
706
707 //@{
708 /// Deregister an accessor so that it is no longer automatically cleared.
709 void releaseAccessor(ValueAccessorBase<Tree, true>&) const;
710 void releaseAccessor(ValueAccessorBase<const Tree, true>&) const;
711 //@}
712
713 //@{
714 /// Dummy implementations
715 void releaseAccessor(ValueAccessorBase<Tree, false>&) const {}
716 void releaseAccessor(ValueAccessorBase<const Tree, false>&) const {}
717 //@}
718
719 /// @brief Return this tree's background value wrapped as metadata.
720 /// @note Query the metadata object for the value's type.
721 Metadata::Ptr getBackgroundValue() const override;
722
723 /// @brief Return this tree's background value.
724 ///
725 /// @note Use tools::changeBackground to efficiently modify the
726 /// background values. Else use tree.root().setBackground, which
727 /// is serial and hence slower.
728 const ValueType& background() const { return mRoot.background(); }
729
730 /// Min and max are both inclusive.
731 void getIndexRange(CoordBBox& bbox) const override { mRoot.getIndexRange(bbox); }
732
733 /// @brief Efficiently merge another tree into this tree using one of several schemes.
734 /// @details This operation is primarily intended to combine trees that are mostly
735 /// non-overlapping (for example, intermediate trees from computations that are
736 /// parallelized across disjoint regions of space).
737 /// @note This operation is not guaranteed to produce an optimally sparse tree.
738 /// Follow merge() with prune() for optimal sparseness.
739 /// @warning This operation always empties the other tree.
740 void merge(Tree& other, MergePolicy = MERGE_ACTIVE_STATES);
741
742 /// @brief Union this tree's set of active values with the active values
743 /// of the other tree, whose @c ValueType may be different.
744 /// @details The resulting state of a value is active if the corresponding value
745 /// was already active OR if it is active in the other tree. Also, a resulting
746 /// value maps to a voxel if the corresponding value already mapped to a voxel
747 /// OR if it is a voxel in the other tree. Thus, a resulting value can only
748 /// map to a tile if the corresponding value already mapped to a tile
749 /// AND if it is a tile value in other tree.
750 ///
751 /// @note This operation modifies only active states, not values.
752 /// Specifically, active tiles and voxels in this tree are not changed, and
753 /// tiles or voxels that were inactive in this tree but active in the other tree
754 /// are marked as active in this tree but left with their original values.
755 ///
756 /// @note If preserveTiles is true, any active tile in this topology
757 /// will not be densified by overlapping child topology.
758 template<typename OtherRootNodeType>
759 void topologyUnion(const Tree<OtherRootNodeType>& other, const bool preserveTiles = false);
760
761 /// @brief Intersects this tree's set of active values with the active values
762 /// of the other tree, whose @c ValueType may be different.
763 /// @details The resulting state of a value is active only if the corresponding
764 /// value was already active AND if it is active in the other tree. Also, a
765 /// resulting value maps to a voxel if the corresponding value
766 /// already mapped to an active voxel in either of the two grids
767 /// and it maps to an active tile or voxel in the other grid.
768 ///
769 /// @note This operation can delete branches in this grid if they
770 /// overlap with inactive tiles in the other grid. Likewise active
771 /// voxels can be turned into inactive voxels resulting in leaf
772 /// nodes with no active values. Thus, it is recommended to
773 /// subsequently call tools::pruneInactive.
774 template<typename OtherRootNodeType>
775 void topologyIntersection(const Tree<OtherRootNodeType>& other);
776
777 /// @brief Difference this tree's set of active values with the active values
778 /// of the other tree, whose @c ValueType may be different. So a
779 /// resulting voxel will be active only if the original voxel is
780 /// active in this tree and inactive in the other tree.
781 ///
782 /// @note This operation can delete branches in this grid if they
783 /// overlap with active tiles in the other grid. Likewise active
784 /// voxels can be turned into inactive voxels resulting in leaf
785 /// nodes with no active values. Thus, it is recommended to
786 /// subsequently call tools::pruneInactive.
787 template<typename OtherRootNodeType>
788 void topologyDifference(const Tree<OtherRootNodeType>& other);
789
790 /// For a given function @c f, use sparse traversal to compute <tt>f(this, other)</tt>
791 /// over all corresponding pairs of values (tile or voxel) of this tree and the other tree
792 /// and store the result in this tree.
793 /// This method is typically more space-efficient than the two-tree combine2(),
794 /// since it moves rather than copies nodes from the other tree into this tree.
795 /// @note This operation always empties the other tree.
796 /// @param other a tree of the same type as this tree
797 /// @param op a functor of the form <tt>void op(const T& a, const T& b, T& result)</tt>,
798 /// where @c T is this tree's @c ValueType, that computes
799 /// <tt>result = f(a, b)</tt>
800 /// @param prune if true, prune the resulting tree one branch at a time (this is usually
801 /// more space-efficient than pruning the entire tree in one pass)
802 ///
803 /// @par Example:
804 /// Compute the per-voxel difference between two floating-point trees,
805 /// @c aTree and @c bTree, and store the result in @c aTree (leaving @c bTree empty).
806 /// @code
807 /// {
808 /// struct Local {
809 /// static inline void diff(const float& a, const float& b, float& result) {
810 /// result = a - b;
811 /// }
812 /// };
813 /// aTree.combine(bTree, Local::diff);
814 /// }
815 /// @endcode
816 ///
817 /// @par Example:
818 /// Compute <tt>f * a + (1 - f) * b</tt> over all voxels of two floating-point trees,
819 /// @c aTree and @c bTree, and store the result in @c aTree (leaving @c bTree empty).
820 /// @code
821 /// namespace {
822 /// struct Blend {
823 /// Blend(float f): frac(f) {}
824 /// inline void operator()(const float& a, const float& b, float& result) const {
825 /// result = frac * a + (1.0 - frac) * b;
826 /// }
827 /// float frac;
828 /// };
829 /// }
830 /// {
831 /// aTree.combine(bTree, Blend(0.25)); // 0.25 * a + 0.75 * b
832 /// }
833 /// @endcode
834 template<typename CombineOp>
835 void combine(Tree& other, CombineOp& op, bool prune = false);
836 template<typename CombineOp>
837 void combine(Tree& other, const CombineOp& op, bool prune = false);
838
839 /// Like combine(), but with
840 /// @param other a tree of the same type as this tree
841 /// @param op a functor of the form <tt>void op(CombineArgs<ValueType>& args)</tt> that
842 /// computes <tt>args.setResult(f(args.a(), args.b()))</tt> and, optionally,
843 /// <tt>args.setResultIsActive(g(args.aIsActive(), args.bIsActive()))</tt>
844 /// for some functions @c f and @c g
845 /// @param prune if true, prune the resulting tree one branch at a time (this is usually
846 /// more space-efficient than pruning the entire tree in one pass)
847 ///
848 /// This variant passes not only the @em a and @em b values but also the active states
849 /// of the @em a and @em b values to the functor, which may then return, by calling
850 /// @c args.setResultIsActive(), a computed active state for the result value.
851 /// By default, the result is active if either the @em a or the @em b value is active.
852 ///
853 /// @see openvdb/Types.h for the definition of the CombineArgs struct.
854 ///
855 /// @par Example:
856 /// Replace voxel values in floating-point @c aTree with corresponding values
857 /// from floating-point @c bTree (leaving @c bTree empty) wherever the @c bTree
858 /// values are larger. Also, preserve the active states of any transferred values.
859 /// @code
860 /// {
861 /// struct Local {
862 /// static inline void max(CombineArgs<float>& args) {
863 /// if (args.b() > args.a()) {
864 /// // Transfer the B value and its active state.
865 /// args.setResult(args.b());
866 /// args.setResultIsActive(args.bIsActive());
867 /// } else {
868 /// // Preserve the A value and its active state.
869 /// args.setResult(args.a());
870 /// args.setResultIsActive(args.aIsActive());
871 /// }
872 /// }
873 /// };
874 /// aTree.combineExtended(bTree, Local::max);
875 /// }
876 /// @endcode
877 template<typename ExtendedCombineOp>
878 void combineExtended(Tree& other, ExtendedCombineOp& op, bool prune = false);
879 template<typename ExtendedCombineOp>
880 void combineExtended(Tree& other, const ExtendedCombineOp& op, bool prune = false);
881
882 /// For a given function @c f, use sparse traversal to compute <tt>f(a, b)</tt> over all
883 /// corresponding pairs of values (tile or voxel) of trees A and B and store the result
884 /// in this tree.
885 /// @param a,b two trees with the same configuration (levels and node dimensions)
886 /// as this tree but with the B tree possibly having a different value type
887 /// @param op a functor of the form <tt>void op(const T1& a, const T2& b, T1& result)</tt>,
888 /// where @c T1 is this tree's and the A tree's @c ValueType and @c T2 is the
889 /// B tree's @c ValueType, that computes <tt>result = f(a, b)</tt>
890 /// @param prune if true, prune the resulting tree one branch at a time (this is usually
891 /// more space-efficient than pruning the entire tree in one pass)
892 ///
893 /// @throw TypeError if the B tree's configuration doesn't match this tree's
894 /// or if this tree's ValueType is not constructible from the B tree's ValueType.
895 ///
896 /// @par Example:
897 /// Compute the per-voxel difference between two floating-point trees,
898 /// @c aTree and @c bTree, and store the result in a third tree.
899 /// @code
900 /// {
901 /// struct Local {
902 /// static inline void diff(const float& a, const float& b, float& result) {
903 /// result = a - b;
904 /// }
905 /// };
906 /// FloatTree resultTree;
907 /// resultTree.combine2(aTree, bTree, Local::diff);
908 /// }
909 /// @endcode
910 template<typename CombineOp, typename OtherTreeType /*= Tree*/>
911 void combine2(const Tree& a, const OtherTreeType& b, CombineOp& op, bool prune = false);
912 template<typename CombineOp, typename OtherTreeType /*= Tree*/>
913 void combine2(const Tree& a, const OtherTreeType& b, const CombineOp& op, bool prune = false);
914
915 /// Like combine2(), but with
916 /// @param a,b two trees with the same configuration (levels and node dimensions)
917 /// as this tree but with the B tree possibly having a different value type
918 /// @param op a functor of the form <tt>void op(CombineArgs<T1, T2>& args)</tt>, where
919 /// @c T1 is this tree's and the A tree's @c ValueType and @c T2 is the B tree's
920 /// @c ValueType, that computes <tt>args.setResult(f(args.a(), args.b()))</tt>
921 /// and, optionally,
922 /// <tt>args.setResultIsActive(g(args.aIsActive(), args.bIsActive()))</tt>
923 /// for some functions @c f and @c g
924 /// @param prune if true, prune the resulting tree one branch at a time (this is usually
925 /// more space-efficient than pruning the entire tree in one pass)
926 /// This variant passes not only the @em a and @em b values but also the active states
927 /// of the @em a and @em b values to the functor, which may then return, by calling
928 /// <tt>args.setResultIsActive()</tt>, a computed active state for the result value.
929 /// By default, the result is active if either the @em a or the @em b value is active.
930 ///
931 /// @throw TypeError if the B tree's configuration doesn't match this tree's
932 /// or if this tree's ValueType is not constructible from the B tree's ValueType.
933 ///
934 /// @see openvdb/Types.h for the definition of the CombineArgs struct.
935 ///
936 /// @par Example:
937 /// Compute the per-voxel maximum values of two single-precision floating-point trees,
938 /// @c aTree and @c bTree, and store the result in a third tree. Set the active state
939 /// of each output value to that of the larger of the two input values.
940 /// @code
941 /// {
942 /// struct Local {
943 /// static inline void max(CombineArgs<float>& args) {
944 /// if (args.b() > args.a()) {
945 /// // Transfer the B value and its active state.
946 /// args.setResult(args.b());
947 /// args.setResultIsActive(args.bIsActive());
948 /// } else {
949 /// // Preserve the A value and its active state.
950 /// args.setResult(args.a());
951 /// args.setResultIsActive(args.aIsActive());
952 /// }
953 /// }
954 /// };
955 /// FloatTree aTree = ...;
956 /// FloatTree bTree = ...;
957 /// FloatTree resultTree;
958 /// resultTree.combine2Extended(aTree, bTree, Local::max);
959 /// }
960 /// @endcode
961 ///
962 /// @par Example:
963 /// Compute the per-voxel maximum values of a double-precision and a single-precision
964 /// floating-point tree, @c aTree and @c bTree, and store the result in a third,
965 /// double-precision tree. Set the active state of each output value to that of
966 /// the larger of the two input values.
967 /// @code
968 /// {
969 /// struct Local {
970 /// static inline void max(CombineArgs<double, float>& args) {
971 /// if (args.b() > args.a()) {
972 /// // Transfer the B value and its active state.
973 /// args.setResult(args.b());
974 /// args.setResultIsActive(args.bIsActive());
975 /// } else {
976 /// // Preserve the A value and its active state.
977 /// args.setResult(args.a());
978 /// args.setResultIsActive(args.aIsActive());
979 /// }
980 /// }
981 /// };
982 /// DoubleTree aTree = ...;
983 /// FloatTree bTree = ...;
984 /// DoubleTree resultTree;
985 /// resultTree.combine2Extended(aTree, bTree, Local::max);
986 /// }
987 /// @endcode
988 template<typename ExtendedCombineOp, typename OtherTreeType /*= Tree*/>
989 void combine2Extended(const Tree& a, const OtherTreeType& b, ExtendedCombineOp& op,
990 bool prune = false);
991 template<typename ExtendedCombineOp, typename OtherTreeType /*= Tree*/>
992 void combine2Extended(const Tree& a, const OtherTreeType& b, const ExtendedCombineOp&,
993 bool prune = false);
994
995 //
996 // Iteration
997 //
998 //@{
999 /// Return an iterator over children of the root node.
1000 typename RootNodeType::ChildOnCIter beginRootChildren() const { return mRoot.cbeginChildOn(); }
1001 typename RootNodeType::ChildOnCIter cbeginRootChildren() const { return mRoot.cbeginChildOn(); }
1002 typename RootNodeType::ChildOnIter beginRootChildren() { return mRoot.beginChildOn(); }
1003 //@}
1004
1005 //@{
1006 /// Return an iterator over non-child entries of the root node's table.
1007 typename RootNodeType::ChildOffCIter beginRootTiles() const { return mRoot.cbeginChildOff(); }
1008 typename RootNodeType::ChildOffCIter cbeginRootTiles() const { return mRoot.cbeginChildOff(); }
1009 typename RootNodeType::ChildOffIter beginRootTiles() { return mRoot.beginChildOff(); }
1010 //@}
1011
1012 //@{
1013 /// Return an iterator over all entries of the root node's table.
1014 typename RootNodeType::ChildAllCIter beginRootDense() const { return mRoot.cbeginChildAll(); }
1015 typename RootNodeType::ChildAllCIter cbeginRootDense() const { return mRoot.cbeginChildAll(); }
1016 typename RootNodeType::ChildAllIter beginRootDense() { return mRoot.beginChildAll(); }
1017 //@}
1018
1019
1020 //@{
1021 /// Iterator over all nodes in this tree
1022 using NodeIter = NodeIteratorBase<Tree, typename RootNodeType::ChildOnIter>;
1023 using NodeCIter = NodeIteratorBase<const Tree, typename RootNodeType::ChildOnCIter>;
1024 //@}
1025
1026 //@{
1027 /// Iterator over all leaf nodes in this tree
1028 using LeafIter = LeafIteratorBase<Tree, typename RootNodeType::ChildOnIter>;
1029 using LeafCIter = LeafIteratorBase<const Tree, typename RootNodeType::ChildOnCIter>;
1030 //@}
1031
1032 //@{
1033 /// Return an iterator over all nodes in this tree.
1034 NodeIter beginNode() { return NodeIter(*this); }
1035 NodeCIter beginNode() const { return NodeCIter(*this); }
1036 NodeCIter cbeginNode() const { return NodeCIter(*this); }
1037 //@}
1038
1039 //@{
1040 /// Return an iterator over all leaf nodes in this tree.
1041 LeafIter beginLeaf() { return LeafIter(*this); }
1042 LeafCIter beginLeaf() const { return LeafCIter(*this); }
1043 LeafCIter cbeginLeaf() const { return LeafCIter(*this); }
1044 //@}
1045
1046 using ValueAllIter = TreeValueIteratorBase<Tree, typename RootNodeType::ValueAllIter>;
1047 using ValueAllCIter = TreeValueIteratorBase<const Tree, typename RootNodeType::ValueAllCIter>;
1048 using ValueOnIter = TreeValueIteratorBase<Tree, typename RootNodeType::ValueOnIter>;
1049 using ValueOnCIter = TreeValueIteratorBase<const Tree, typename RootNodeType::ValueOnCIter>;
1050 using ValueOffIter = TreeValueIteratorBase<Tree, typename RootNodeType::ValueOffIter>;
1051 using ValueOffCIter = TreeValueIteratorBase<const Tree, typename RootNodeType::ValueOffCIter>;
1052
1053 //@{
1054 /// Return an iterator over all values (tile and voxel) across all nodes.
1055 ValueAllIter beginValueAll() { return ValueAllIter(*this); }
1056 ValueAllCIter beginValueAll() const { return ValueAllCIter(*this); }
1057 ValueAllCIter cbeginValueAll() const { return ValueAllCIter(*this); }
1058 //@}
1059 //@{
1060 /// Return an iterator over active values (tile and voxel) across all nodes.
1061 ValueOnIter beginValueOn() { return ValueOnIter(*this); }
1062 ValueOnCIter beginValueOn() const { return ValueOnCIter(*this); }
1063 ValueOnCIter cbeginValueOn() const { return ValueOnCIter(*this); }
1064 //@}
1065 //@{
1066 /// Return an iterator over inactive values (tile and voxel) across all nodes.
1067 ValueOffIter beginValueOff() { return ValueOffIter(*this); }
1068 ValueOffCIter beginValueOff() const { return ValueOffCIter(*this); }
1069 ValueOffCIter cbeginValueOff() const { return ValueOffCIter(*this); }
1070 //@}
1071
1072 /// @brief Return an iterator of type @c IterT (for example, begin<ValueOnIter>() is
1073 /// equivalent to beginValueOn()).
1074 template<typename IterT> IterT begin();
1075 /// @brief Return a const iterator of type CIterT (for example, cbegin<ValueOnCIter>()
1076 /// is equivalent to cbeginValueOn()).
1077 template<typename CIterT> CIterT cbegin() const;
1078
1079
1080protected:
1081 using AccessorRegistry = tbb::concurrent_hash_map<ValueAccessorBase<Tree, true>*, bool>;
1082 using ConstAccessorRegistry = tbb::concurrent_hash_map<ValueAccessorBase<const Tree, true>*, bool>;
1083
1084 /// @brief Notify all registered accessors, by calling ValueAccessor::release(),
1085 /// that this tree is about to be deleted.
1086 void releaseAllAccessors();
1087
1088 // TBB body object used to deallocates nodes in parallel.
1089 template<typename NodeType>
1090 struct DeallocateNodes {
1091 DeallocateNodes(std::vector<NodeType*>& nodes)
1092 : mNodes(nodes.empty() ? nullptr : &nodes.front()) { }
1093 void operator()(const tbb::blocked_range<size_t>& range) const {
1094 for (size_t n = range.begin(), N = range.end(); n < N; ++n) {
1095 delete mNodes[n]; mNodes[n] = nullptr;
1096 }
1097 }
1098 NodeType ** const mNodes;
1099 };
1100
1101 //
1102 // Data members
1103 //
1104 RootNodeType mRoot; // root node of the tree
1105 mutable AccessorRegistry mAccessorRegistry;
1106 mutable ConstAccessorRegistry mConstAccessorRegistry;
1107}; // end of Tree class
1108
1109
1110/// @brief Tree3<T, N1, N2>::Type is the type of a three-level tree
1111/// (Root, Internal, Leaf) with value type T and
1112/// internal and leaf node log dimensions N1 and N2, respectively.
1113/// @note This is NOT the standard tree configuration (Tree4 is).
1114template<typename T, Index N1=4, Index N2=3>
1115 struct Tree3 {
1116 using Type = Tree<RootNode<InternalNode<LeafNode<T, N2>, N1>>>;
1117};
1118
1119
1120/// @brief Tree4<T, N1, N2, N3>::Type is the type of a four-level tree
1121/// (Root, Internal, Internal, Leaf) with value type T and
1122/// internal and leaf node log dimensions N1, N2 and N3, respectively.
1123/// @note This is the standard tree configuration.
1124template<typename T, Index N1=5, Index N2=4, Index N3=3>
1125 struct Tree4 {
1126 using Type = Tree<RootNode<InternalNode<InternalNode<LeafNode<T, N3>, N2>, N1>>>;
1127};
1128
1129/// @brief Tree5<T, N1, N2, N3, N4>::Type is the type of a five-level tree
1130/// (Root, Internal, Internal, Internal, Leaf) with value type T and
1131/// internal and leaf node log dimensions N1, N2, N3 and N4, respectively.
1132/// @note This is NOT the standard tree configuration (Tree4 is).
1133template<typename T, Index N1=6, Index N2=5, Index N3=4, Index N4=3>
1134 struct Tree5 {
1135 using Type =
1136 Tree<RootNode<InternalNode<InternalNode<InternalNode<LeafNode<T, N4>, N3>, N2>, N1>>>;
1137};
1138
1139
1140////////////////////////////////////////
1141
1142
1143inline void
1144TreeBase::readTopology(std::istream& is, bool /*saveFloatAsHalf*/)
1145{
1146 int32_t bufferCount;
1147 is.read(reinterpret_cast<char*>(&bufferCount), sizeof(int32_t));
1148 if (bufferCount != 1) OPENVDB_LOG_WARN("multi-buffer trees are no longer supported");
1149}
1150
1151
1152inline void
1153TreeBase::writeTopology(std::ostream& os, bool /*saveFloatAsHalf*/) const
1154{
1155 int32_t bufferCount = 1;
1156 os.write(reinterpret_cast<char*>(&bufferCount), sizeof(int32_t));
1157}
1158
1159
1160inline void
1161TreeBase::print(std::ostream& os, int /*verboseLevel*/) const
1162{
1163 os << " Tree Type: " << type()
1164 << " Active Voxel Count: " << activeVoxelCount() << std::endl
1165 << " Active tile Count: " << activeTileCount() << std::endl
1166 << " Inactive Voxel Count: " << inactiveVoxelCount() << std::endl
1167 << " Leaf Node Count: " << leafCount() << std::endl
1168 << " Non-leaf Node Count: " << nonLeafCount() << std::endl;
1169}
1170
1171
1172////////////////////////////////////////
1173
1174
1175//
1176// Type traits for tree iterators
1177//
1178
1179/// @brief TreeIterTraits provides, for all tree iterators, a begin(tree) function
1180/// that returns an iterator over a tree of arbitrary type.
1181 template<typename TreeT, typename IterT> struct TreeIterTraits;
1182
1183 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOnIter> {
1184 static typename TreeT::RootNodeType::ChildOnIter begin(TreeT& tree) {
1185 return tree.beginRootChildren();
1186 }
1187};
1188
1189 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOnCIter> {
1190 static typename TreeT::RootNodeType::ChildOnCIter begin(const TreeT& tree) {
1191 return tree.cbeginRootChildren();
1192 }
1193};
1194
1195 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOffIter> {
1196 static typename TreeT::RootNodeType::ChildOffIter begin(TreeT& tree) {
1197 return tree.beginRootTiles();
1198 }
1199};
1200
1201 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildOffCIter> {
1202 static typename TreeT::RootNodeType::ChildOffCIter begin(const TreeT& tree) {
1203 return tree.cbeginRootTiles();
1204 }
1205};
1206
1207 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildAllIter> {
1208 static typename TreeT::RootNodeType::ChildAllIter begin(TreeT& tree) {
1209 return tree.beginRootDense();
1210 }
1211};
1212
1213 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::RootNodeType::ChildAllCIter> {
1214 static typename TreeT::RootNodeType::ChildAllCIter begin(const TreeT& tree) {
1215 return tree.cbeginRootDense();
1216 }
1217};
1218
1219 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::NodeIter> {
1220 static typename TreeT::NodeIter begin(TreeT& tree) { return tree.beginNode(); }
1221};
1222
1223 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::NodeCIter> {
1224 static typename TreeT::NodeCIter begin(const TreeT& tree) { return tree.cbeginNode(); }
1225};
1226
1227 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::LeafIter> {
1228 static typename TreeT::LeafIter begin(TreeT& tree) { return tree.beginLeaf(); }
1229};
1230
1231 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::LeafCIter> {
1232 static typename TreeT::LeafCIter begin(const TreeT& tree) { return tree.cbeginLeaf(); }
1233};
1234
1235 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueOnIter> {
1236 static typename TreeT::ValueOnIter begin(TreeT& tree) { return tree.beginValueOn(); }
1237};
1238
1239 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueOnCIter> {
1240 static typename TreeT::ValueOnCIter begin(const TreeT& tree) { return tree.cbeginValueOn(); }
1241};
1242
1243 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueOffIter> {
1244 static typename TreeT::ValueOffIter begin(TreeT& tree) { return tree.beginValueOff(); }
1245};
1246
1247 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueOffCIter> {
1248 static typename TreeT::ValueOffCIter begin(const TreeT& tree) { return tree.cbeginValueOff(); }
1249};
1250
1251 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueAllIter> {
1252 static typename TreeT::ValueAllIter begin(TreeT& tree) { return tree.beginValueAll(); }
1253};
1254
1255 template<typename TreeT> struct TreeIterTraits<TreeT, typename TreeT::ValueAllCIter> {
1256 static typename TreeT::ValueAllCIter begin(const TreeT& tree) { return tree.cbeginValueAll(); }
1257};
1258
1259
1260template<typename RootNodeType>
1261template<typename IterT>
1262inline IterT
1263Tree<RootNodeType>::begin()
1264{
1265 return TreeIterTraits<Tree, IterT>::begin(*this);
1266}
1267
1268
1269template<typename RootNodeType>
1270template<typename IterT>
1271inline IterT
1272 Tree<RootNodeType>::cbegin() const
1273{
1274 return TreeIterTraits<Tree, IterT>::begin(*this);
1275}
1276
1277
1278////////////////////////////////////////
1279
1280
1281template<typename RootNodeType>
1282void
1283Tree<RootNodeType>::readTopology(std::istream& is, bool saveFloatAsHalf)
1284{
1285 this->clearAllAccessors();
1286 TreeBase::readTopology(is, saveFloatAsHalf);
1287 mRoot.readTopology(is, saveFloatAsHalf);
1288}
1289
1290
1291template<typename RootNodeType>
1292void
1293Tree<RootNodeType>::writeTopology(std::ostream& os, bool saveFloatAsHalf) const
1294{
1295 TreeBase::writeTopology(os, saveFloatAsHalf);
1296 mRoot.writeTopology(os, saveFloatAsHalf);
1297}
1298
1299
1300template<typename RootNodeType>
1301inline void
1302Tree<RootNodeType>::readBuffers(std::istream &is, bool saveFloatAsHalf)
1303{
1304 this->clearAllAccessors();
1305 mRoot.readBuffers(is, saveFloatAsHalf);
1306}
1307
1308
1309template<typename RootNodeType>
1310inline void
1311 Tree<RootNodeType>::readBuffers(std::istream &is, const CoordBBox& bbox, bool saveFloatAsHalf)
1312{
1313 this->clearAllAccessors();
1314 mRoot.readBuffers(is, bbox, saveFloatAsHalf);
1315}
1316
1317
1318template<typename RootNodeType>
1319inline void
1320Tree<RootNodeType>::readNonresidentBuffers() const
1321{
1322 for (LeafCIter it = this->cbeginLeaf(); it; ++it) {
1323 // Retrieving the value of a leaf voxel forces loading of the leaf node's voxel buffer.
1324 it->getValue(Index(0));
1325 }
1326}
1327
1328
1329template<typename RootNodeType>
1330inline void
1331Tree<RootNodeType>::writeBuffers(std::ostream &os, bool saveFloatAsHalf) const
1332{
1333 mRoot.writeBuffers(os, saveFloatAsHalf);
1334}
1335
1336
1337template<typename RootNodeType>
1338template<typename ArrayT>
1339inline void
1340Tree<RootNodeType>::getNodes(ArrayT& array)
1341{
1342 using NodeT = typename std::remove_pointer<typename ArrayT::value_type>::type;
1343 static_assert(!std::is_same<NodeT, RootNodeType>::value,
1344 "getNodes() does not work for the RootNode. Use Tree::root()");
1345 mRoot.getNodes(array);
1346}
1347
1348
1349template<typename RootNodeType>
1350template<typename ArrayT>
1351inline void
1352 Tree<RootNodeType>::getNodes(ArrayT& array) const
1353{
1354 using NodeT = typename std::remove_pointer<typename ArrayT::value_type>::type;
1355 static_assert(!std::is_same<NodeT, const RootNodeType>::value,
1356 "getNodes() does not work for the RootNode. Use Tree::root()");
1357 mRoot.getNodes(array);
1358}
1359
1360
1361template<typename RootNodeType>
1362inline void
1363Tree<RootNodeType>::clear()
1364{
1365 std::vector<LeafNodeType*> leafnodes;
1366 this->stealNodes(leafnodes);
1367
1368 tbb::parallel_for(tbb::blocked_range<size_t>(0, leafnodes.size()),
1369 DeallocateNodes<LeafNodeType>(leafnodes));
1370
1371 std::vector<typename RootNodeType::ChildNodeType*> internalNodes;
1372 this->stealNodes(internalNodes);
1373
1374 tbb::parallel_for(tbb::blocked_range<size_t>(0, internalNodes.size()),
1375 DeallocateNodes<typename RootNodeType::ChildNodeType>(internalNodes));
1376
1377 mRoot.clear();
1378
1379 this->clearAllAccessors();
1380}
1381
1382
1383////////////////////////////////////////
1384
1385
1386template<typename RootNodeType>
1387typename Tree<RootNodeType>::Accessor
1388Tree<RootNodeType>::getAccessor()
1389{
1390 return Accessor(*this);
1391}
1392
1393template<typename RootNodeType>
1394typename Tree<RootNodeType>::UnsafeAccessor
1395Tree<RootNodeType>::getUnsafeAccessor()
1396{
1397 return UnsafeAccessor(*this);
1398}
1399
1400template<typename RootNodeType>
1401typename Tree<RootNodeType>::ConstAccessor
1402 Tree<RootNodeType>::getAccessor() const
1403{
1404 return ConstAccessor(*this);
1405}
1406
1407template<typename RootNodeType>
1408typename Tree<RootNodeType>::ConstAccessor
1409Tree<RootNodeType>::getConstAccessor() const
1410{
1411 return ConstAccessor(*this);
1412}
1413
1414template<typename RootNodeType>
1415typename Tree<RootNodeType>::ConstUnsafeAccessor
1416Tree<RootNodeType>::getConstUnsafeAccessor()
1417{
1418 return ConstUnsafeAccessor(*this);
1419}
1420
1421template<typename RootNodeType>
1422inline void
1423Tree<RootNodeType>::attachAccessor(ValueAccessorBase<Tree, true>& accessor) const
1424{
1425 typename AccessorRegistry::accessor a;
1426 mAccessorRegistry.insert(a, &accessor);
1427}
1428
1429
1430template<typename RootNodeType>
1431inline void
1432 Tree<RootNodeType>::attachAccessor(ValueAccessorBase<const Tree, true>& accessor) const
1433{
1434 typename ConstAccessorRegistry::accessor a;
1435 mConstAccessorRegistry.insert(a, &accessor);
1436}
1437
1438
1439template<typename RootNodeType>
1440inline void
1441Tree<RootNodeType>::releaseAccessor(ValueAccessorBase<Tree, true>& accessor) const
1442{
1443 mAccessorRegistry.erase(&accessor);
1444}
1445
1446
1447template<typename RootNodeType>
1448inline void
1449 Tree<RootNodeType>::releaseAccessor(ValueAccessorBase<const Tree, true>& accessor) const
1450{
1451 mConstAccessorRegistry.erase(&accessor);
1452}
1453
1454
1455template<typename RootNodeType>
1456inline void
1457Tree<RootNodeType>::clearAllAccessors()
1458{
1459 for (typename AccessorRegistry::iterator it = mAccessorRegistry.begin();
1460 it != mAccessorRegistry.end(); ++it)
1461 {
1462 if (it->first) it->first->clear();
1463 }
1464
1465 for (typename ConstAccessorRegistry::iterator it = mConstAccessorRegistry.begin();
1466 it != mConstAccessorRegistry.end(); ++it)
1467 {
1468 if (it->first) it->first->clear();
1469 }
1470}
1471
1472
1473template<typename RootNodeType>
1474inline void
1475Tree<RootNodeType>::releaseAllAccessors()
1476{
1477 mAccessorRegistry.erase(nullptr);
1478 for (typename AccessorRegistry::iterator it = mAccessorRegistry.begin();
1479 it != mAccessorRegistry.end(); ++it)
1480 {
1481 it->first->release();
1482 }
1483 mAccessorRegistry.clear();
1484
1485 mAccessorRegistry.erase(nullptr);
1486 for (typename ConstAccessorRegistry::iterator it = mConstAccessorRegistry.begin();
1487 it != mConstAccessorRegistry.end(); ++it)
1488 {
1489 it->first->release();
1490 }
1491 mConstAccessorRegistry.clear();
1492}
1493
1494
1495////////////////////////////////////////
1496
1497
1498template<typename RootNodeType>
1499inline const typename RootNodeType::ValueType&
1500Tree<RootNodeType>::getValue(const Coord& xyz) const
1501{
1502 return mRoot.getValue(xyz);
1503}
1504
1505
1506template<typename RootNodeType>
1507template<typename AccessT>
1508inline const typename RootNodeType::ValueType&
1509 Tree<RootNodeType>::getValue(const Coord& xyz, AccessT& accessor) const
1510{
1511 return accessor.getValue(xyz);
1512}
1513
1514
1515template<typename RootNodeType>
1516inline int
1517Tree<RootNodeType>::getValueDepth(const Coord& xyz) const
1518{
1519 return mRoot.getValueDepth(xyz);
1520}
1521
1522
1523template<typename RootNodeType>
1524inline void
1525Tree<RootNodeType>::setValueOff(const Coord& xyz)
1526{
1527 mRoot.setValueOff(xyz);
1528}
1529
1530
1531template<typename RootNodeType>
1532inline void
1533 Tree<RootNodeType>::setValueOff(const Coord& xyz, const ValueType& value)
1534{
1535 mRoot.setValueOff(xyz, value);
1536}
1537
1538
1539template<typename RootNodeType>
1540inline void
1541Tree<RootNodeType>::setActiveState(const Coord& xyz, bool on)
1542{
1543 mRoot.setActiveState(xyz, on);
1544}
1545
1546
1547template<typename RootNodeType>
1548inline void
1549Tree<RootNodeType>::setValue(const Coord& xyz, const ValueType& value)
1550{
1551 mRoot.setValueOn(xyz, value);
1552}
1553
1554template<typename RootNodeType>
1555inline void
1556Tree<RootNodeType>::setValueOnly(const Coord& xyz, const ValueType& value)
1557{
1558 mRoot.setValueOnly(xyz, value);
1559}
1560
1561template<typename RootNodeType>
1562template<typename AccessT>
1563inline void
1564 Tree<RootNodeType>::setValue(const Coord& xyz, const ValueType& value, AccessT& accessor)
1565{
1566 accessor.setValue(xyz, value);
1567}
1568
1569
1570template<typename RootNodeType>
1571inline void
1572Tree<RootNodeType>::setValueOn(const Coord& xyz)
1573{
1574 mRoot.setActiveState(xyz, true);
1575}
1576
1577
1578template<typename RootNodeType>
1579inline void
1580 Tree<RootNodeType>::setValueOn(const Coord& xyz, const ValueType& value)
1581{
1582 mRoot.setValueOn(xyz, value);
1583}
1584
1585
1586template<typename RootNodeType>
1587template<typename ModifyOp>
1588inline void
1589Tree<RootNodeType>::modifyValue(const Coord& xyz, const ModifyOp& op)
1590{
1591 mRoot.modifyValue(xyz, op);
1592}
1593
1594
1595template<typename RootNodeType>
1596template<typename ModifyOp>
1597inline void
1598Tree<RootNodeType>::modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
1599{
1600 mRoot.modifyValueAndActiveState(xyz, op);
1601}
1602
1603
1604template<typename RootNodeType>
1605inline bool
1606Tree<RootNodeType>::probeValue(const Coord& xyz, ValueType& value) const
1607{
1608 return mRoot.probeValue(xyz, value);
1609}
1610
1611
1612////////////////////////////////////////
1613
1614
1615template<typename RootNodeType>
1616inline void
1617Tree<RootNodeType>::addTile(Index level, const Coord& xyz,
1618 const ValueType& value, bool active)
1619{
1620 mRoot.addTile(level, xyz, value, active);
1621}
1622
1623
1624template<typename RootNodeType>
1625template<typename NodeT>
1626inline NodeT*
1627Tree<RootNodeType>::stealNode(const Coord& xyz, const ValueType& value, bool active)
1628{
1629 this->clearAllAccessors();
1630 return mRoot.template stealNode<NodeT>(xyz, value, active);
1631}
1632
1633
1634template<typename RootNodeType>
1635inline typename RootNodeType::LeafNodeType*
1636Tree<RootNodeType>::touchLeaf(const Coord& xyz)
1637{
1638 return mRoot.touchLeaf(xyz);
1639}
1640
1641
1642template<typename RootNodeType>
1643inline typename RootNodeType::LeafNodeType*
1644Tree<RootNodeType>::probeLeaf(const Coord& xyz)
1645{
1646 return mRoot.probeLeaf(xyz);
1647}
1648
1649
1650template<typename RootNodeType>
1651inline const typename RootNodeType::LeafNodeType*
1652Tree<RootNodeType>::probeConstLeaf(const Coord& xyz) const
1653{
1654 return mRoot.probeConstLeaf(xyz);
1655}
1656
1657
1658template<typename RootNodeType>
1659template<typename NodeType>
1660inline NodeType*
1661Tree<RootNodeType>::probeNode(const Coord& xyz)
1662{
1663 return mRoot.template probeNode<NodeType>(xyz);
1664}
1665
1666
1667template<typename RootNodeType>
1668template<typename NodeType>
1669inline const NodeType*
1670 Tree<RootNodeType>::probeNode(const Coord& xyz) const
1671{
1672 return this->template probeConstNode<NodeType>(xyz);
1673}
1674
1675
1676template<typename RootNodeType>
1677template<typename NodeType>
1678inline const NodeType*
1679Tree<RootNodeType>::probeConstNode(const Coord& xyz) const
1680{
1681 return mRoot.template probeConstNode<NodeType>(xyz);
1682}
1683
1684
1685////////////////////////////////////////
1686
1687
1688template<typename RootNodeType>
1689inline void
1690Tree<RootNodeType>::clip(const CoordBBox& bbox)
1691{
1692 this->clearAllAccessors();
1693 return mRoot.clip(bbox);
1694}
1695
1696
1697template<typename RootNodeType>
1698inline void
1699Tree<RootNodeType>::clipUnallocatedNodes()
1700{
1701 this->clearAllAccessors();
1702 for (LeafIter it = this->beginLeaf(); it; ) {
1703 const LeafNodeType* leaf = it.getLeaf();
1704 ++it; // advance the iterator before deleting the leaf node
1705 if (!leaf->isAllocated()) {
1706 this->addTile(/*level=*/0, leaf->origin(), this->background(), /*active=*/false);
1707 }
1708 }
1709}
1710
1711#if OPENVDB_ABI_VERSION_NUMBER >= 12
1712template<typename RootNodeType>
1713inline Index64
1714Tree<RootNodeType>::unallocatedLeafCount() const
1715{
1716 Index64 sum = 0;
1717 for (auto it = this->cbeginLeaf(); it; ++it) if (!it->isAllocated()) ++sum;
1718 return sum;
1719}
1720#else
1721template<typename RootNodeType>
1722inline Index32
1723 Tree<RootNodeType>::unallocatedLeafCount() const
1724{
1725 Index32 sum = 0;
1726 for (auto it = this->cbeginLeaf(); it; ++it) if (!it->isAllocated()) ++sum;
1727 return sum;
1728}
1729#endif
1730
1731
1732template<typename RootNodeType>
1733inline void
1734Tree<RootNodeType>::sparseFill(const CoordBBox& bbox, const ValueType& value, bool active)
1735{
1736 this->clearAllAccessors();
1737 return mRoot.sparseFill(bbox, value, active);
1738}
1739
1740
1741template<typename RootNodeType>
1742inline void
1743Tree<RootNodeType>::denseFill(const CoordBBox& bbox, const ValueType& value, bool active)
1744{
1745 this->clearAllAccessors();
1746 return mRoot.denseFill(bbox, value, active);
1747}
1748
1749
1750template<typename RootNodeType>
1751inline void
1752Tree<RootNodeType>::voxelizeActiveTiles(bool threaded)
1753{
1754 this->clearAllAccessors();
1755 mRoot.voxelizeActiveTiles(threaded);
1756}
1757
1758
1759template<typename RootNodeType>
1760 Metadata::Ptr
1761Tree<RootNodeType>::getBackgroundValue() const
1762{
1763 Metadata::Ptr result;
1764 if (Metadata::isRegisteredType(valueType())) {
1765 using MetadataT = TypedMetadata<ValueType>;
1766 result = Metadata::createMetadata(valueType());
1767 if (result->typeName() == MetadataT::staticTypeName()) {
1768 MetadataT* m = static_cast<MetadataT*>(result.get());
1769 m->value() = mRoot.background();
1770 }
1771 }
1772 return result;
1773}
1774
1775
1776////////////////////////////////////////
1777
1778
1779template<typename RootNodeType>
1780inline void
1781Tree<RootNodeType>::merge(Tree& other, MergePolicy policy)
1782{
1783 this->clearAllAccessors();
1784 other.clearAllAccessors();
1785 switch (policy) {
1786 case MERGE_ACTIVE_STATES:
1787 mRoot.template merge<MERGE_ACTIVE_STATES>(other.mRoot); break;
1788 case MERGE_NODES:
1789 mRoot.template merge<MERGE_NODES>(other.mRoot); break;
1790 case MERGE_ACTIVE_STATES_AND_NODES:
1791 mRoot.template merge<MERGE_ACTIVE_STATES_AND_NODES>(other.mRoot); break;
1792 }
1793}
1794
1795
1796template<typename RootNodeType>
1797template<typename OtherRootNodeType>
1798inline void
1799Tree<RootNodeType>::topologyUnion(const Tree<OtherRootNodeType>& other, const bool preserveTiles)
1800{
1801 this->clearAllAccessors();
1802 mRoot.topologyUnion(other.root(), preserveTiles);
1803}
1804
1805template<typename RootNodeType>
1806template<typename OtherRootNodeType>
1807inline void
1808Tree<RootNodeType>::topologyIntersection(const Tree<OtherRootNodeType>& other)
1809{
1810 this->clearAllAccessors();
1811 mRoot.topologyIntersection(other.root());
1812}
1813
1814template<typename RootNodeType>
1815template<typename OtherRootNodeType>
1816inline void
1817Tree<RootNodeType>::topologyDifference(const Tree<OtherRootNodeType>& other)
1818{
1819 this->clearAllAccessors();
1820 mRoot.topologyDifference(other.root());
1821}
1822
1823////////////////////////////////////////
1824
1825
1826/// @brief Helper class to adapt a three-argument (a, b, result) CombineOp functor
1827/// into a single-argument functor that accepts a CombineArgs struct
1828template<typename AValueT, typename CombineOp, typename BValueT = AValueT>
1829 struct CombineOpAdapter
1830{
1831 CombineOpAdapter(CombineOp& _op): op(_op) {}
1832
1833 void operator()(CombineArgs<AValueT, BValueT>& args) const {
1834 op(args.a(), args.b(), args.result());
1835 }
1836
1837 CombineOp& op;
1838};
1839
1840
1841template<typename RootNodeType>
1842template<typename CombineOp>
1843inline void
1844Tree<RootNodeType>::combine(Tree& other, CombineOp& op, bool prune)
1845{
1846 CombineOpAdapter<ValueType, CombineOp> extendedOp(op);
1847 this->combineExtended(other, extendedOp, prune);
1848}
1849
1850
1851/// @internal This overload is needed (for ICC and GCC, but not for VC) to disambiguate
1852/// code like this: <tt>aTree.combine(bTree, MyCombineOp(...))</tt>.
1853template<typename RootNodeType>
1854template<typename CombineOp>
1855inline void
1856 Tree<RootNodeType>::combine(Tree& other, const CombineOp& op, bool prune)
1857{
1858 CombineOpAdapter<ValueType, const CombineOp> extendedOp(op);
1859 this->combineExtended(other, extendedOp, prune);
1860}
1861
1862
1863template<typename RootNodeType>
1864template<typename ExtendedCombineOp>
1865inline void
1866Tree<RootNodeType>::combineExtended(Tree& other, ExtendedCombineOp& op, bool prune)
1867{
1868 this->clearAllAccessors();
1869 mRoot.combine(other.root(), op, prune);
1870}
1871
1872
1873/// @internal This overload is needed (for ICC and GCC, but not for VC) to disambiguate
1874/// code like this: <tt>aTree.combineExtended(bTree, MyCombineOp(...))</tt>.
1875template<typename RootNodeType>
1876template<typename ExtendedCombineOp>
1877inline void
1878 Tree<RootNodeType>::combineExtended(Tree& other, const ExtendedCombineOp& op, bool prune)
1879{
1880 this->clearAllAccessors();
1881 mRoot.template combine<const ExtendedCombineOp>(other.mRoot, op, prune);
1882}
1883
1884
1885template<typename RootNodeType>
1886template<typename CombineOp, typename OtherTreeType>
1887inline void
1888Tree<RootNodeType>::combine2(const Tree& a, const OtherTreeType& b, CombineOp& op, bool prune)
1889{
1890 CombineOpAdapter<ValueType, CombineOp, typename OtherTreeType::ValueType> extendedOp(op);
1891 this->combine2Extended(a, b, extendedOp, prune);
1892}
1893
1894
1895/// @internal This overload is needed (for ICC and GCC, but not for VC) to disambiguate
1896/// code like this: <tt>tree.combine2(aTree, bTree, MyCombineOp(...))</tt>.
1897template<typename RootNodeType>
1898template<typename CombineOp, typename OtherTreeType>
1899inline void
1900 Tree<RootNodeType>::combine2(const Tree& a, const OtherTreeType& b, const CombineOp& op, bool prune)
1901{
1902 CombineOpAdapter<ValueType, const CombineOp, typename OtherTreeType::ValueType> extendedOp(op);
1903 this->combine2Extended(a, b, extendedOp, prune);
1904}
1905
1906
1907template<typename RootNodeType>
1908template<typename ExtendedCombineOp, typename OtherTreeType>
1909inline void
1910Tree<RootNodeType>::combine2Extended(const Tree& a, const OtherTreeType& b,
1911 ExtendedCombineOp& op, bool prune)
1912{
1913 this->clearAllAccessors();
1914 mRoot.combine2(a.root(), b.root(), op, prune);
1915}
1916
1917
1918/// @internal This overload is needed (for ICC and GCC, but not for VC) to disambiguate
1919/// code like the following, where the functor argument is a temporary:
1920/// <tt>tree.combine2Extended(aTree, bTree, MyCombineOp(...))</tt>.
1921template<typename RootNodeType>
1922template<typename ExtendedCombineOp, typename OtherTreeType>
1923inline void
1924 Tree<RootNodeType>::combine2Extended(const Tree& a, const OtherTreeType& b,
1925 const ExtendedCombineOp& op, bool prune)
1926{
1927 this->clearAllAccessors();
1928 mRoot.template combine2<const ExtendedCombineOp>(a.root(), b.root(), op, prune);
1929}
1930
1931
1932////////////////////////////////////////
1933
1934
1935template<typename RootNodeType>
1936inline const Name&
1937Tree<RootNodeType>::treeType()
1938{
1939 static std::string sTreeTypeName = []()
1940 {
1941 // @todo use RootNode::NodeChain::foreach() instead
1942 std::vector<Index> dims;
1943 Tree::getNodeLog2Dims(dims);
1944 std::ostringstream ostr;
1945 ostr << "Tree_" << typeNameAsString<BuildType>();
1946 for (size_t i = 1, N = dims.size(); i < N; ++i) { // start from 1 to skip the RootNode
1947 ostr << "_" << dims[i];
1948 }
1949 return ostr.str();
1950 }();
1951 return sTreeTypeName;
1952}
1953
1954
1955template<typename RootNodeType>
1956template<typename OtherRootNodeType>
1957inline bool
1958Tree<RootNodeType>::hasSameTopology(const Tree<OtherRootNodeType>& other) const
1959{
1960 return mRoot.hasSameTopology(other.root());
1961}
1962
1963
1964template<typename RootNodeType>
1965inline bool
1966Tree<RootNodeType>::evalLeafBoundingBox(CoordBBox& bbox) const
1967{
1968 bbox.reset(); // default invalid bbox
1969
1970 if (this->empty()) return false; // empty
1971
1972 mRoot.evalActiveBoundingBox(bbox, false);
1973
1974 return !bbox.empty();
1975}
1976
1977template<typename RootNodeType>
1978inline bool
1979Tree<RootNodeType>::evalActiveVoxelBoundingBox(CoordBBox& bbox) const
1980{
1981 bbox.reset(); // default invalid bbox
1982
1983 if (this->empty()) return false; // empty
1984
1985 mRoot.evalActiveBoundingBox(bbox, true);
1986
1987 return !bbox.empty();
1988}
1989
1990
1991template<typename RootNodeType>
1992inline bool
1993Tree<RootNodeType>::evalActiveVoxelDim(Coord& dim) const
1994{
1995 CoordBBox bbox;
1996 bool notEmpty = this->evalActiveVoxelBoundingBox(bbox);
1997 dim = bbox.extents();
1998 return notEmpty;
1999}
2000
2001
2002template<typename RootNodeType>
2003inline bool
2004Tree<RootNodeType>::evalLeafDim(Coord& dim) const
2005{
2006 CoordBBox bbox;
2007 bool notEmpty = this->evalLeafBoundingBox(bbox);
2008 dim = bbox.extents();
2009 return notEmpty;
2010}
2011
2012
2013template<typename RootNodeType>
2014inline void
2015Tree<RootNodeType>::getNodeLog2Dims(std::vector<Index>& dims)
2016{
2017 dims.clear();
2018 RootNodeType::getNodeLog2Dims(dims);
2019}
2020
2021
2022template<typename RootNodeType>
2023inline void
2024Tree<RootNodeType>::print(std::ostream& os, int verboseLevel) const
2025{
2026 if (verboseLevel <= 0) return;
2027
2028 /// @todo Consider using boost::io::ios_precision_saver instead.
2029 struct OnExit {
2030 std::ostream& os;
2031 std::streamsize savedPrecision;
2032 OnExit(std::ostream& _os): os(_os), savedPrecision(os.precision()) {}
2033 ~OnExit() { os.precision(savedPrecision); }
2034 };
2035 OnExit restorePrecision(os);
2036
2037 std::vector<Index> dims;
2038 Tree::getNodeLog2Dims(dims);// leaf is the last element
2039
2040 os << "Information about Tree:\n"
2041 << " Type: " << this->type() << "\n";
2042
2043 os << " Configuration:\n";
2044
2045 if (verboseLevel <= 1) {
2046 // Print node types and sizes.
2047 os << " Root(" << mRoot.getTableSize() << ")";
2048 if (dims.size() > 1) {
2049 for (size_t i = 1, N = dims.size() - 1; i < N; ++i) {
2050 os << ", Internal(" << (1 << dims[i]) << "^3)";
2051 }
2052 os << ", Leaf(" << (1 << dims.back()) << "^3)\n";
2053 }
2054 os << " Background value: " << mRoot.background() << "\n";
2055 return;
2056 }
2057
2058 // The following is tree information that is expensive to extract.
2059
2060 ValueType minVal = zeroVal<ValueType>(), maxVal = zeroVal<ValueType>();
2061 if (verboseLevel > 3) {
2062 // This forces loading of all non-resident nodes.
2063 const math::MinMax<ValueType> extrema = tools::minMax(*this);
2064 minVal = extrema.min();
2065 maxVal = extrema.max();
2066 }
2067
2068 const auto nodeCount = this->nodeCount();//fast
2069 const Index64 leafCount = nodeCount.front();// leaf is the first element
2070 OPENVDB_ASSERT(dims.size() == nodeCount.size());
2071
2072 Index64 totalNodeCount = 0;
2073 for (size_t i = 0; i < nodeCount.size(); ++i) totalNodeCount += nodeCount[i];
2074
2075 // Print node types, counts and sizes.
2076 os << " Root(1 x " << mRoot.getTableSize() << ")";
2077 if (dims.size() >= 2) {
2078 for (size_t i = 1, N = dims.size() - 1; i < N; ++i) {
2079 os << ", Internal(" << util::formattedInt(nodeCount[N - i]);
2080 os << " x " << (1 << dims[i]) << "^3)";
2081 }
2082 os << ", Leaf(" << util::formattedInt(leafCount);
2083 os << " x " << (1 << dims.back()) << "^3)\n";
2084 }
2085 os << " Background value: " << mRoot.background() << "\n";
2086
2087 // Statistics of topology and values
2088
2089 if (verboseLevel > 3) {
2090 os << " Min value: " << minVal << "\n";
2091 os << " Max value: " << maxVal << "\n";
2092 }
2093
2094 const Index64
2095 numActiveVoxels = this->activeVoxelCount(),
2096 numActiveLeafVoxels = this->activeLeafVoxelCount(),
2097 numActiveTiles = this->activeTileCount();
2098
2099 os << " Number of active voxels: " << util::formattedInt(numActiveVoxels) << "\n";
2100 os << " Number of active tiles: " << util::formattedInt(numActiveTiles) << "\n";
2101
2102 Coord dim(0, 0, 0);
2103 Index64 totalVoxels = 0;
2104 if (numActiveVoxels) { // nonempty
2105 CoordBBox bbox;
2106 this->evalActiveVoxelBoundingBox(bbox);
2107 dim = bbox.extents();
2108 totalVoxels = dim.x() * uint64_t(dim.y()) * dim.z();
2109
2110 os << " Bounding box of active voxels: " << bbox << "\n";
2111 os << " Dimensions of active voxels: "
2112 << dim[0] << " x " << dim[1] << " x " << dim[2] << "\n";
2113
2114 const double activeRatio = (100.0 * double(numActiveVoxels)) / double(totalVoxels);
2115 os << " Percentage of active voxels: " << std::setprecision(3) << activeRatio << "%\n";
2116
2117 if (leafCount > 0) {
2118 const double fillRatio = (100.0 * double(numActiveLeafVoxels))
2119 / (double(leafCount) * double(LeafNodeType::NUM_VOXELS));
2120 os << " Average leaf node fill ratio: " << fillRatio << "%\n";
2121 }
2122
2123 if (verboseLevel > 2) {
2124 Index64 sum = 0;// count the number of unallocated leaf nodes
2125 for (auto it = this->cbeginLeaf(); it; ++it) if (!it->isAllocated()) ++sum;
2126 os << " Number of unallocated nodes: "
2127 << util::formattedInt(sum) << " ("
2128 << (100.0 * double(sum) / double(totalNodeCount)) << "%)\n";
2129 }
2130 } else {
2131 os << " Tree is empty!\n";
2132 }
2133 os << std::flush;
2134
2135 if (verboseLevel == 2) return;
2136
2137 // Memory footprint in bytes
2138 const Index64
2139 actualMem = this->memUsage(),
2140 denseMem = sizeof(ValueType) * totalVoxels,
2141 voxelsMem = sizeof(ValueType) * numActiveLeafVoxels;
2142 ///< @todo not accurate for BoolTree (and probably should count tile values)
2143
2144 os << "Memory footprint:\n";
2145 util::printBytes(os, actualMem, " Actual: ");
2146 util::printBytes(os, voxelsMem, " Active leaf voxels: ");
2147
2148 if (numActiveVoxels) {
2149 util::printBytes(os, denseMem, " Dense equivalent: ");
2150 os << " Actual footprint is " << (100.0 * double(actualMem) / double(denseMem))
2151 << "% of an equivalent dense volume\n";
2152 os << " Leaf voxel footprint is " << (100.0 * double(voxelsMem) / double(actualMem))
2153 << "% of actual footprint\n";
2154 }
2155}
2156
2157} // namespace tree
2158} // namespace OPENVDB_VERSION_NAME
2159} // namespace openvdb
2160
2161#endif // OPENVDB_TREE_TREE_HAS_BEEN_INCLUDED
Assert.h
OPENVDB_ASSERT
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
BBox.h
Count.h
Functions to count tiles, nodes or voxels in a grid.
Formats.h
Utility routines to output nicely-formatted numeric values.
InternalNode.h
Internal table nodes for OpenVDB trees.
LeafNode.h
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Metadata.h
Platform.h
OPENVDB_NO_DEPRECATION_WARNING_END
#define OPENVDB_NO_DEPRECATION_WARNING_END
Definition Platform.h:218
OPENVDB_NO_DEPRECATION_WARNING_BEGIN
#define OPENVDB_NO_DEPRECATION_WARNING_BEGIN
Bracket code with OPENVDB_NO_DEPRECATION_WARNING_BEGIN/_END, to inhibit warnings about deprecated cod...
Definition Platform.h:217
OPENVDB_API
#define OPENVDB_API
Definition Platform.h:291
RootNode.h
The root node of an OpenVDB tree.
TreeIterator.h
ValueAccessor.h
ValueAccessors are designed to help accelerate accesses into the OpenVDB Tree structures by storing c...
openvdb::v13_0::CombineArgs
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition Types.h:636
openvdb::v13_0::CombineArgs::result
const AValueType & result() const
Get the output value.
Definition Types.h:680
openvdb::v13_0::CombineArgs::b
const BValueType & b() const
Get the B input value.
Definition Types.h:677
openvdb::v13_0::CombineArgs::a
const AValueType & a() const
Get the A input value.
Definition Types.h:675
openvdb::v13_0::Metadata::createMetadata
static Metadata::Ptr createMetadata(const Name &typeName)
Create new metadata of the given type.
openvdb::v13_0::Metadata::isRegisteredType
static bool isRegisteredType(const Name &typeName)
Return true if the given type is known by the metadata type registry.
openvdb::v13_0::Metadata::Ptr
SharedPtr< Metadata > Ptr
Definition Metadata.h:27
openvdb::v13_0::NotImplementedError
Definition Exceptions.h:61
openvdb::v13_0::TopologyCopy
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition Types.h:750
openvdb::v13_0::TypedMetadata
Templated metadata class to hold specific types.
Definition Metadata.h:123
openvdb::v13_0::math::CoordBBox
Axis-aligned bounding box of signed integer coordinates.
Definition Coord.h:252
openvdb::v13_0::math::CoordBBox::extents
Coord extents() const
Definition Coord.h:385
openvdb::v13_0::math::CoordBBox::empty
bool empty() const
Return true if this bounding box is empty (i.e., encloses no coordinates).
Definition Coord.h:359
openvdb::v13_0::math::CoordBBox::reset
void reset()
Definition Coord.h:330
openvdb::v13_0::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
openvdb::v13_0::math::Coord::y
Int32 y() const
Definition Coord.h:132
openvdb::v13_0::math::Coord::x
Int32 x() const
Definition Coord.h:131
openvdb::v13_0::math::Coord::z
Int32 z() const
Definition Coord.h:133
openvdb::v13_0::math::Extrema::min
double min() const
Return the minimum value.
Definition Stats.h:122
openvdb::v13_0::math::Extrema::max
double max() const
Return the maximum value.
Definition Stats.h:125
openvdb::v13_0::math::MinMax
Templated class to compute the minimum and maximum values.
Definition Stats.h:32
openvdb::v13_0::tree::LeafIteratorBase
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels).
Definition TreeIterator.h:1188
openvdb::v13_0::tree::NodeIteratorBase
Base class for tree-traversal iterators over all nodes.
Definition TreeIterator.h:937
openvdb::v13_0::tree::RootNode::ChildAllIter
DenseIter< RootNode, MapIter, ChildType, ValueType > ChildAllIter
Definition RootNode.h:366
openvdb::v13_0::tree::RootNode::LeafNodeType
typename ChildType::LeafNodeType LeafNodeType
Definition RootNode.h:43
openvdb::v13_0::tree::RootNode::ChildOnIter
ChildIter< RootNode, MapIter, ChildOnPred, ChildType > ChildOnIter
Definition RootNode.h:362
openvdb::v13_0::tree::RootNode::ChildOffCIter
ValueIter< const RootNode, MapCIter, ChildOffPred, ValueType > ChildOffCIter
Definition RootNode.h:365
openvdb::v13_0::tree::RootNode::LEVEL
static const Index LEVEL
Definition RootNode.h:47
openvdb::v13_0::tree::RootNode::ValueType
typename ChildType::ValueType ValueType
Definition RootNode.h:44
openvdb::v13_0::tree::RootNode::BuildType
typename ChildType::BuildType BuildType
Definition RootNode.h:45
openvdb::v13_0::tree::RootNode::ChildAllCIter
DenseIter< const RootNode, MapCIter, const ChildType, const ValueType > ChildAllCIter
Definition RootNode.h:367
openvdb::v13_0::tree::RootNode::ChildOffIter
ValueIter< RootNode, MapIter, ChildOffPred, const ValueType > ChildOffIter
Definition RootNode.h:364
openvdb::v13_0::tree::RootNode::ChildOnCIter
ChildIter< const RootNode, MapCIter, ChildOnPred, const ChildType > ChildOnCIter
Definition RootNode.h:363
openvdb::v13_0::tree::TreeBase::valueType
virtual Name valueType() const =0
Return the name of the type of a voxel's value (e.g., "float" or "vec3d").
openvdb::v13_0::tree::TreeBase::type
virtual const Name & type() const =0
Return the name of this tree's type.
openvdb::v13_0::tree::TreeBase::writeTopology
virtual void writeTopology(std::ostream &, bool saveFloatAsHalf=false) const
Write the tree topology to a stream.
Definition Tree.h:1153
openvdb::v13_0::tree::TreeBase::unallocatedLeafCount
virtual Index64 unallocatedLeafCount() const =0
Return the total number of unallocated leaf nodes residing in this tree.
openvdb::v13_0::tree::TreeBase::~TreeBase
virtual ~TreeBase()=default
openvdb::v13_0::tree::TreeBase::activeLeafVoxelCount
virtual Index64 activeLeafVoxelCount() const =0
Return the number of active voxels stored in leaf nodes.
openvdb::v13_0::tree::TreeBase::nodeCount
virtual std::vector< Index64 > nodeCount() const =0
openvdb::v13_0::tree::TreeBase::readBuffers
virtual void readBuffers(std::istream &, bool saveFloatAsHalf=false)=0
Read all data buffers for this tree.
openvdb::v13_0::tree::TreeBase::isType
bool isType() const
Return true if this tree is of the same type as the template parameter.
Definition Tree.h:56
openvdb::v13_0::tree::TreeBase::writeBuffers
virtual void writeBuffers(std::ostream &, bool saveFloatAsHalf=false) const =0
Write out all the data buffers for this tree.
openvdb::v13_0::tree::TreeBase::leafCount
virtual Index64 leafCount() const =0
Return the number of leaf nodes.
openvdb::v13_0::tree::TreeBase::getBackgroundValue
virtual Metadata::Ptr getBackgroundValue() const
Return this tree's background value wrapped as metadata.
Definition Tree.h:66
openvdb::v13_0::tree::TreeBase::nonLeafCount
virtual Index64 nonLeafCount() const =0
Return the number of non-leaf nodes.
openvdb::v13_0::tree::TreeBase::TreeBase
TreeBase()=default
openvdb::v13_0::tree::TreeBase::print
virtual void print(std::ostream &os=std::cout, int verboseLevel=1) const
Print statistics, memory usage and other information about this tree.
Definition Tree.h:1161
openvdb::v13_0::tree::TreeBase::readBuffers
virtual void readBuffers(std::istream &, const CoordBBox &, bool saveFloatAsHalf=false)=0
Read all of this tree's data buffers that intersect the given bounding box.
openvdb::v13_0::tree::TreeBase::getIndexRange
virtual void getIndexRange(CoordBBox &bbox) const =0
openvdb::v13_0::tree::TreeBase::activeVoxelCount
virtual Index64 activeVoxelCount() const =0
Return the total number of active voxels.
openvdb::v13_0::tree::TreeBase::inactiveVoxelCount
virtual Index64 inactiveVoxelCount() const =0
Return the number of inactive voxels within the bounding box of all active voxels.
openvdb::v13_0::tree::TreeBase::clipUnallocatedNodes
virtual void clipUnallocatedNodes()=0
Replace with background tiles any nodes whose voxel buffers have not yet been allocated.
openvdb::v13_0::tree::TreeBase::readNonresidentBuffers
virtual void readNonresidentBuffers() const =0
Read all of this tree's data buffers that are not yet resident in memory (because delayed loading is ...
openvdb::v13_0::tree::TreeBase::inactiveLeafVoxelCount
virtual Index64 inactiveLeafVoxelCount() const =0
Return the number of inactive voxels stored in leaf nodes.
openvdb::v13_0::tree::TreeBase::memUsage
virtual Index64 memUsage() const
Return the total amount of memory in bytes occupied by this tree.
Definition Tree.h:151
openvdb::v13_0::tree::TreeBase::copy
virtual TreeBase::Ptr copy() const =0
Return a pointer to a deep copy of this tree.
openvdb::v13_0::tree::TreeBase::Ptr
SharedPtr< TreeBase > Ptr
Definition Tree.h:40
openvdb::v13_0::tree::TreeBase::evalLeafDim
virtual bool evalLeafDim(Coord &dim) const =0
Return in dim the dimensions of the axis-aligned bounding box of all leaf nodes.
openvdb::v13_0::tree::TreeBase::evalActiveVoxelBoundingBox
virtual bool evalActiveVoxelBoundingBox(CoordBBox &bbox) const =0
Return in bbox the axis-aligned bounding box of all active voxels and tiles.
openvdb::v13_0::tree::TreeBase::treeDepth
virtual Index treeDepth() const =0
Return the depth of this tree.
openvdb::v13_0::tree::TreeBase::activeTileCount
virtual Index64 activeTileCount() const =0
Return the total number of active tiles.
openvdb::v13_0::tree::TreeBase::ConstPtr
SharedPtr< const TreeBase > ConstPtr
Definition Tree.h:41
openvdb::v13_0::tree::TreeBase::evalActiveVoxelDim
virtual bool evalActiveVoxelDim(Coord &dim) const =0
Return in dim the dimensions of the axis-aligned bounding box of all active voxels....
openvdb::v13_0::tree::TreeBase::evalLeafBoundingBox
virtual bool evalLeafBoundingBox(CoordBBox &bbox) const =0
Return in bbox the axis-aligned bounding box of all active tiles and leaf nodes with active values.
openvdb::v13_0::tree::TreeBase::operator=
TreeBase & operator=(const TreeBase &)=delete
openvdb::v13_0::tree::TreeBase::TreeBase
TreeBase(const TreeBase &)=default
openvdb::v13_0::tree::TreeBase::readTopology
virtual void readTopology(std::istream &, bool saveFloatAsHalf=false)
Read the tree topology from a stream.
Definition Tree.h:1144
openvdb::v13_0::tree::TreeValueIteratorBase
Base class for tree-traversal iterators over tile and voxel values.
Definition TreeIterator.h:618
openvdb::v13_0::tree::Tree
Definition Tree.h:195
openvdb::v13_0::tree::Tree::readTopology
void readTopology(std::istream &, bool saveFloatAsHalf=false) override
Read the tree topology from a stream.
Definition Tree.h:1283
openvdb::v13_0::tree::Tree::beginRootDense
RootNodeType::ChildAllCIter beginRootDense() const
Return an iterator over all entries of the root node's table.
Definition Tree.h:1014
openvdb::v13_0::tree::Tree::getBackgroundValue
Metadata::Ptr getBackgroundValue() const override
Return this tree's background value wrapped as metadata.
Definition Tree.h:1761
openvdb::v13_0::tree::Tree::getValueDepth
int getValueDepth(const Coord &xyz) const
Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides.
Definition Tree.h:1517
openvdb::v13_0::tree::Tree::hasSameTopology
bool hasSameTopology(const Tree< OtherRootNodeType > &other) const
Return true if the given tree has the same node and active value topology as this tree,...
Definition Tree.h:1958
openvdb::v13_0::tree::Tree::unallocatedLeafCount
Index64 unallocatedLeafCount() const override
Return the total number of unallocated leaf nodes residing in this tree.
Definition Tree.h:1714
openvdb::v13_0::tree::Tree::cbegin
CIterT cbegin() const
Return a const iterator of type CIterT (for example, cbegin<ValueOnCIter>() is equivalent to cbeginVa...
openvdb::v13_0::tree::Tree::evalActiveVoxelBoundingBox
bool evalActiveVoxelBoundingBox(CoordBBox &bbox) const override
Return in bbox the axis-aligned bounding box of all active voxels and tiles.
Definition Tree.h:1979
openvdb::v13_0::tree::Tree::stealNode
NodeT * stealNode(const Coord &xyz, const ValueType &value, bool active)
Return a pointer to the node of type NodeT that contains voxel (x, y, z) and replace it with a tile o...
Definition Tree.h:1627
openvdb::v13_0::tree::Tree::releaseAccessor
void releaseAccessor(ValueAccessorBase< Tree, false > &) const
Dummy implementations.
Definition Tree.h:715
openvdb::v13_0::tree::Tree::probeNode
NodeType * probeNode(const Coord &xyz)
Return a pointer to the node of type NodeType that contains voxel (x, y, z). If no such node exists,...
Definition Tree.h:1661
openvdb::v13_0::tree::Tree::probeNode
const NodeType * probeNode(const Coord &xyz) const
Definition Tree.h:1670
openvdb::v13_0::tree::Tree::combine
void combine(Tree &other, CombineOp &op, bool prune=false)
Definition Tree.h:1844
openvdb::v13_0::tree::Tree::getValue
const ValueType & getValue(const Coord &xyz, AccessT &) const
Return the value of the voxel at the given coordinates and update the given accessor's node cache.
openvdb::v13_0::tree::Tree::releaseAccessor
void releaseAccessor(ValueAccessorBase< const Tree, false > &) const
Definition Tree.h:716
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::mConstAccessorRegistry
ConstAccessorRegistry mConstAccessorRegistry
Definition Tree.h:1106
openvdb::v13_0::tree::Tree::isValueOn
bool isValueOn(const Coord &xyz) const
Return true if the value at the given coordinates is active.
Definition Tree.h:487
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::root
RootNodeType & root()
Definition Tree.h:303
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ValueOffIter
TreeValueIteratorBase< Tree, typename RootNodeType::ValueOffIter > ValueOffIter
Definition Tree.h:1050
openvdb::v13_0::tree::Tree::Tree
Tree(const Tree &other)
Deep copy constructor.
Definition Tree.h:229
openvdb::v13_0::tree::Tree::cbeginRootTiles
RootNodeType::ChildOffCIter cbeginRootTiles() const
Definition Tree.h:1008
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ValueOffCIter
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueOffCIter > ValueOffCIter
Definition Tree.h:1051
openvdb::v13_0::tree::Tree::beginLeaf
LeafCIter beginLeaf() const
Definition Tree.h:1042
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::Accessor
ValueAccessor< Tree, true > Accessor
Definition Tree.h:207
openvdb::v13_0::tree::Tree::writeBuffers
void writeBuffers(std::ostream &, bool saveFloatAsHalf=false) const override
Write out all data buffers for this tree.
Definition Tree.h:1331
openvdb::v13_0::tree::Tree::writeTopology
void writeTopology(std::ostream &, bool saveFloatAsHalf=false) const override
Write the tree topology to a stream.
Definition Tree.h:1293
openvdb::v13_0::tree::Tree::cbeginValueOff
ValueOffCIter cbeginValueOff() const
Definition Tree.h:1069
openvdb::v13_0::tree::Tree::Tree
Tree(const Tree< OtherRootType > &other)
Value conversion deep copy constructor.
Definition Tree.h:240
openvdb::v13_0::tree::Tree::probeConstLeaf
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Definition Tree.h:1652
openvdb::v13_0::tree::Tree::begin
IterT begin()
Return an iterator of type IterT (for example, begin<ValueOnIter>() is equivalent to beginValueOn()).
Definition Tree.h:1263
openvdb::v13_0::tree::Tree::memUsage
Index64 memUsage() const override
Return the total amount of memory in bytes occupied by this tree.
Definition Tree.h:404
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::clearAllAccessors
void clearAllAccessors()
openvdb::v13_0::tree::Tree::merge
void merge(Tree &other, MergePolicy=MERGE_ACTIVE_STATES)
Efficiently merge another tree into this tree using one of several schemes.
Definition Tree.h:1781
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ValueAllCIter
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueAllCIter > ValueAllCIter
Definition Tree.h:1047
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::RootNodeType
tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > RootNodeType
Definition Tree.h:200
openvdb::v13_0::tree::Tree::beginRootDense
RootNodeType::ChildAllIter beginRootDense()
Definition Tree.h:1016
openvdb::v13_0::tree::Tree::getAccessor
Accessor getAccessor()
Return an accessor that provides random read and write access to this tree's voxels.
Definition Tree.h:1388
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::UnsafeAccessor
ValueAccessor< Tree, false > UnsafeAccessor
Definition Tree.h:209
openvdb::v13_0::tree::Tree::cbeginLeaf
LeafCIter cbeginLeaf() const
Definition Tree.h:1043
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::LeafCIter
LeafIteratorBase< const Tree, typename RootNodeType::ChildOnCIter > LeafCIter
Definition Tree.h:1029
openvdb::v13_0::tree::Tree::type
const Name & type() const override
Return the name of this type of tree.
Definition Tree.h:296
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::DEPTH
static const Index DEPTH
Definition Tree.h:205
openvdb::v13_0::tree::Tree::beginRootTiles
RootNodeType::ChildOffIter beginRootTiles()
Definition Tree.h:1009
openvdb::v13_0::tree::Tree::getNodes
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition Tree.h:1340
openvdb::v13_0::tree::Tree::readBuffers
void readBuffers(std::istream &, const CoordBBox &, bool saveFloatAsHalf=false) override
Read all of this tree's data buffers that intersect the given bounding box.
Definition Tree.h:1311
openvdb::v13_0::tree::Tree::treeType
static const Name & treeType()
Return the name of this type of tree.
Definition Tree.h:1937
openvdb::v13_0::tree::Tree::voxelizeActiveTiles
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition Tree.h:1752
openvdb::v13_0::tree::Tree::beginRootChildren
RootNodeType::ChildOnCIter beginRootChildren() const
Return an iterator over children of the root node.
Definition Tree.h:1000
openvdb::v13_0::tree::Tree::combine
void combine(Tree &other, const CombineOp &op, bool prune=false)
Definition Tree.h:1856
openvdb::v13_0::tree::Tree::operator!=
bool operator!=(const Tree &) const
Definition Tree.h:299
openvdb::v13_0::tree::Tree::Tree
Tree()
Definition Tree.h:224
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::mAccessorRegistry
AccessorRegistry mAccessorRegistry
Definition Tree.h:1105
openvdb::v13_0::tree::Tree::clip
void clip(const CoordBBox &)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition Tree.h:1690
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ConstAccessor
ValueAccessor< const Tree, true > ConstAccessor
Definition Tree.h:208
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::mRoot
RootNodeType mRoot
Definition Tree.h:1104
openvdb::v13_0::tree::Tree::cbeginValueAll
ValueAllCIter cbeginValueAll() const
Definition Tree.h:1057
openvdb::v13_0::tree::Tree::prune
void prune(const ValueType &tolerance=zeroVal< ValueType >())
Reduce the memory footprint of this tree by replacing with tiles any nodes whose values are all the s...
Definition Tree.h:548
openvdb::v13_0::tree::Tree::probeLeaf
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition Tree.h:1644
openvdb::v13_0::tree::Tree::topologyIntersection
void topologyIntersection(const Tree< OtherRootNodeType > &other)
Intersects this tree's set of active values with the active values of the other tree,...
Definition Tree.h:1808
openvdb::v13_0::tree::Tree::releaseAccessor
void releaseAccessor(ValueAccessorBase< Tree, true > &) const
Deregister an accessor so that it is no longer automatically cleared.
Definition Tree.h:1441
openvdb::v13_0::tree::Tree::touchLeaf
LeafNodeType * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition Tree.h:1636
openvdb::v13_0::tree::Tree::beginRootChildren
RootNodeType::ChildOnIter beginRootChildren()
Definition Tree.h:1002
openvdb::v13_0::tree::Tree::leafCount
Index64 leafCount() const override
Return the number of leaf nodes.
Definition Tree.h:363
openvdb::v13_0::tree::Tree::beginValueOn
ValueOnCIter beginValueOn() const
Definition Tree.h:1062
openvdb::v13_0::tree::Tree::operator==
bool operator==(const Tree &) const
Definition Tree.h:298
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::Ptr
SharedPtr< Tree > Ptr
Definition Tree.h:197
openvdb::v13_0::tree::Tree::attachAccessor
void attachAccessor(ValueAccessorBase< Tree, true > &) const
Register an accessor for this tree. Registered accessors are automatically cleared whenever one of th...
Definition Tree.h:1423
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::NodeIter
NodeIteratorBase< Tree, typename RootNodeType::ChildOnIter > NodeIter
Definition Tree.h:1022
openvdb::v13_0::tree::Tree::activeLeafVoxelCount
Index64 activeLeafVoxelCount() const override
Return the number of active voxels stored in leaf nodes.
Definition Tree.h:394
openvdb::v13_0::tree::Tree::modifyValueAndActiveState
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition Tree.h:1598
openvdb::v13_0::tree::Tree::getConstUnsafeAccessor
ConstUnsafeAccessor getConstUnsafeAccessor()
Return an unsafe accessor that provides random read-only access to this tree's voxels.
Definition Tree.h:1416
openvdb::v13_0::tree::Tree::combine2Extended
void combine2Extended(const Tree &a, const OtherTreeType &b, const ExtendedCombineOp &, bool prune=false)
Definition Tree.h:1924
openvdb::v13_0::tree::Tree::inactiveVoxelCount
Index64 inactiveVoxelCount() const override
Return the number of inactive voxels within the bounding box of all active voxels.
Definition Tree.h:400
openvdb::v13_0::tree::Tree::setValueOnly
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates but don't change its active state.
Definition Tree.h:1556
openvdb::v13_0::tree::Tree::empty
bool empty() const
Return true if this tree contains no nodes other than the root node and no tiles other than backgroun...
Definition Tree.h:661
openvdb::v13_0::tree::Tree::activeVoxelCount
Index64 activeVoxelCount() const override
Return the total number of active voxels.
Definition Tree.h:398
openvdb::v13_0::tree::Tree::inactiveLeafVoxelCount
Index64 inactiveLeafVoxelCount() const override
Return the number of inactive voxels stored in leaf nodes.
Definition Tree.h:396
openvdb::v13_0::tree::Tree::fill
void fill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Definition Tree.h:519
openvdb::v13_0::tree::Tree::beginValueOff
ValueOffCIter beginValueOff() const
Definition Tree.h:1068
openvdb::v13_0::tree::Tree::addLeaf
void addLeaf(LeafNodeType *leaf)
Add the given leaf node to this tree, creating a new branch if necessary. If a leaf node with the sam...
Definition Tree.h:559
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ValueAllIter
TreeValueIteratorBase< Tree, typename RootNodeType::ValueAllIter > ValueAllIter
Definition Tree.h:1046
openvdb::v13_0::tree::Tree::beginRootTiles
RootNodeType::ChildOffCIter beginRootTiles() const
Return an iterator over non-child entries of the root node's table.
Definition Tree.h:1007
openvdb::v13_0::tree::Tree::combineExtended
void combineExtended(Tree &other, ExtendedCombineOp &op, bool prune=false)
Definition Tree.h:1866
openvdb::v13_0::tree::Tree::setValueOff
void setValueOff(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as inactive.
Definition Tree.h:1533
openvdb::v13_0::tree::Tree::addTile
void addTile(Index level, const Coord &xyz, const ValueType &value, bool active)
Add a tile containing voxel (x, y, z) at the specified tree level, creating a new branch if necessary...
Definition Tree.h:1617
openvdb::v13_0::tree::Tree::releaseAccessor
void releaseAccessor(ValueAccessorBase< const Tree, true > &) const
Definition Tree.h:1449
openvdb::v13_0::tree::Tree::probeValue
bool probeValue(const Coord &xyz, ValueType &value) const
Get the value of the voxel at the given coordinates.
Definition Tree.h:1606
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ValueOnCIter
TreeValueIteratorBase< const Tree, typename RootNodeType::ValueOnCIter > ValueOnCIter
Definition Tree.h:1049
openvdb::v13_0::tree::Tree::setActiveState
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don't change its value.
Definition Tree.h:1541
openvdb::v13_0::tree::Tree::beginValueOn
ValueOnIter beginValueOn()
Return an iterator over active values (tile and voxel) across all nodes.
Definition Tree.h:1061
openvdb::v13_0::tree::Tree::topologyDifference
void topologyDifference(const Tree< OtherRootNodeType > &other)
Difference this tree's set of active values with the active values of the other tree,...
Definition Tree.h:1817
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::releaseAllAccessors
void releaseAllAccessors()
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::BuildType
typename RootNodeType::BuildType BuildType
Definition Tree.h:202
openvdb::v13_0::tree::Tree::setValue
void setValue(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active.
Definition Tree.h:1549
openvdb::v13_0::tree::Tree::combine2Extended
void combine2Extended(const Tree &a, const OtherTreeType &b, ExtendedCombineOp &op, bool prune=false)
Definition Tree.h:1910
openvdb::v13_0::tree::Tree::activeTileCount
Index64 activeTileCount() const override
Return the total number of active tiles.
Definition Tree.h:402
openvdb::v13_0::tree::Tree::setValueOff
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition Tree.h:1525
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ConstAccessorRegistry
tbb::concurrent_hash_map< ValueAccessorBase< const Tree, true > *, bool > ConstAccessorRegistry
Definition Tree.h:1082
openvdb::v13_0::tree::Tree::cbeginValueOn
ValueOnCIter cbeginValueOn() const
Definition Tree.h:1063
openvdb::v13_0::tree::Tree::copy
TreeBase::Ptr copy() const override
Return a pointer to a deep copy of this tree.
Definition Tree.h:288
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ValueType
typename RootNodeType::ValueType ValueType
Definition Tree.h:201
openvdb::v13_0::tree::Tree::attachAccessor
void attachAccessor(ValueAccessorBase< Tree, false > &) const
Dummy implementations.
Definition Tree.h:703
openvdb::v13_0::tree::Tree::getValue
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition Tree.h:1500
openvdb::v13_0::tree::Tree::probeLeaf
const LeafNodeType * probeLeaf(const Coord &xyz) const
Definition Tree.h:594
openvdb::v13_0::tree::Tree::print
void print(std::ostream &os=std::cout, int verboseLevel=1) const override
Print statistics, memory usage and other information about this tree.
Definition Tree.h:2024
openvdb::v13_0::tree::Tree::combineExtended
void combineExtended(Tree &other, const ExtendedCombineOp &op, bool prune=false)
Definition Tree.h:1878
openvdb::v13_0::tree::Tree::attachAccessor
void attachAccessor(ValueAccessorBase< const Tree, false > &) const
Definition Tree.h:704
openvdb::v13_0::tree::Tree::getUnsafeAccessor
UnsafeAccessor getUnsafeAccessor()
Return an unsafe accessor that provides random read and write access to this tree's voxels.
Definition Tree.h:1395
openvdb::v13_0::tree::Tree::combine2
void combine2(const Tree &a, const OtherTreeType &b, const CombineOp &op, bool prune=false)
Definition Tree.h:1900
openvdb::v13_0::tree::Tree::beginNode
NodeCIter beginNode() const
Definition Tree.h:1035
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ConstUnsafeAccessor
ValueAccessor< const Tree, false > ConstUnsafeAccessor
Definition Tree.h:210
openvdb::v13_0::tree::Tree::modifyValue
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active.
Definition Tree.h:1589
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::LeafIter
LeafIteratorBase< Tree, typename RootNodeType::ChildOnIter > LeafIter
Definition Tree.h:1028
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ConstPtr
SharedPtr< const Tree > ConstPtr
Definition Tree.h:198
openvdb::v13_0::tree::Tree::readNonresidentBuffers
void readNonresidentBuffers() const override
Read all of this tree's data buffers that are not yet resident in memory (because delayed loading is ...
Definition Tree.h:1320
openvdb::v13_0::tree::Tree::Tree
Tree(const OtherTreeType &other, const ValueType &background, TopologyCopy)
Topology copy constructor from a tree of a different type.
Definition Tree.h:276
openvdb::v13_0::tree::Tree::cbeginRootDense
RootNodeType::ChildAllCIter cbeginRootDense() const
Definition Tree.h:1015
openvdb::v13_0::tree::Tree::getNodes
void getNodes(ArrayT &array) const
Definition Tree.h:1352
openvdb::v13_0::tree::Tree::denseFill
void denseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value and ensure that those voxels are a...
Definition Tree.h:1743
openvdb::v13_0::tree::Tree::evalLeafBoundingBox
bool evalLeafBoundingBox(CoordBBox &bbox) const override
Return in bbox the axis-aligned bounding box of all active tiles and leaf nodes with active values.
Definition Tree.h:1966
openvdb::v13_0::tree::Tree::stealNodes
void stealNodes(ArrayT &array, const ValueType &value, bool state)
Definition Tree.h:650
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::clear
void clear()
openvdb::v13_0::tree::Tree::evalLeafDim
bool evalLeafDim(Coord &dim) const override
Return in dim the dimensions of the axis-aligned bounding box of all leaf nodes.
Definition Tree.h:2004
openvdb::v13_0::tree::Tree::cbeginRootChildren
RootNodeType::ChildOnCIter cbeginRootChildren() const
Definition Tree.h:1001
openvdb::v13_0::tree::Tree::setValue
void setValue(const Coord &xyz, const ValueType &value, AccessT &)
Set the value of the voxel at the given coordinates, mark the voxel as active, and update the given a...
Definition Tree.h:1564
openvdb::v13_0::tree::Tree::nodeCount
std::vector< Index64 > nodeCount() const override
Definition Tree.h:371
openvdb::v13_0::tree::Tree::cbeginNode
NodeCIter cbeginNode() const
Definition Tree.h:1036
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::background
const ValueType & background() const
Definition Tree.h:728
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::NodeCIter
NodeIteratorBase< const Tree, typename RootNodeType::ChildOnCIter > NodeCIter
Definition Tree.h:1023
openvdb::v13_0::tree::Tree::operator=
Tree & operator=(const Tree &)=delete
openvdb::v13_0::tree::Tree::getNodeLog2Dims
static void getNodeLog2Dims(std::vector< Index > &dims)
Traverse the type hierarchy of nodes, and return, in dims, a list of the Log2Dims of nodes in order f...
Definition Tree.h:2015
openvdb::v13_0::tree::Tree::beginValueOff
ValueOffIter beginValueOff()
Return an iterator over inactive values (tile and voxel) across all nodes.
Definition Tree.h:1067
openvdb::v13_0::tree::Tree::getIndexRange
void getIndexRange(CoordBBox &bbox) const override
Min and max are both inclusive.
Definition Tree.h:731
openvdb::v13_0::tree::Tree::attachAccessor
void attachAccessor(ValueAccessorBase< const Tree, true > &) const
Definition Tree.h:1432
openvdb::v13_0::tree::Tree::readBuffers
void readBuffers(std::istream &, bool saveFloatAsHalf=false) override
Read all data buffers for this tree.
Definition Tree.h:1302
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::LeafNodeType
typename RootNodeType::LeafNodeType LeafNodeType
Definition Tree.h:203
openvdb::v13_0::tree::Tree::getConstAccessor
ConstAccessor getConstAccessor() const
Return an accessor that provides random read-only access to this tree's voxels.
Definition Tree.h:1409
openvdb::v13_0::tree::Tree::setValueOn
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition Tree.h:1572
openvdb::v13_0::tree::Tree::beginLeaf
LeafIter beginLeaf()
Return an iterator over all leaf nodes in this tree.
Definition Tree.h:1041
openvdb::v13_0::tree::Tree::sparseFill
void sparseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
Definition Tree.h:1734
openvdb::v13_0::tree::Tree::Tree
Tree(const OtherTreeType &other, const ValueType &inactiveValue, const ValueType &activeValue, TopologyCopy)
Topology copy constructor from a tree of a different type.
Definition Tree.h:255
openvdb::v13_0::tree::Tree::evalActiveVoxelDim
bool evalActiveVoxelDim(Coord &dim) const override
Return in dim the dimensions of the axis-aligned bounding box of all active voxels....
Definition Tree.h:1993
openvdb::v13_0::tree::Tree::~Tree
~Tree() override
Definition Tree.h:285
openvdb::v13_0::tree::Tree::probeConstNode
const NodeType * probeConstNode(const Coord &xyz) const
Definition Tree.h:1679
openvdb::v13_0::tree::Tree::hasActiveTiles
bool hasActiveTiles() const
Return true if this tree has any active tiles.
Definition Tree.h:491
openvdb::v13_0::tree::Tree::Tree
Tree(const ValueType &background)
Empty tree constructor.
Definition Tree.h:283
openvdb::v13_0::tree::Tree::clipUnallocatedNodes
void clipUnallocatedNodes() override
Replace with background tiles any nodes whose voxel buffers have not yet been allocated.
Definition Tree.h:1699
openvdb::v13_0::tree::Tree::setValueOn
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active.
Definition Tree.h:1580
openvdb::v13_0::tree::Tree::isValueOff
bool isValueOff(const Coord &xyz) const
Return true if the value at the given coordinates is inactive.
Definition Tree.h:489
openvdb::v13_0::tree::Tree::stealNodes
void stealNodes(ArrayT &array)
Steals all nodes of a certain type from the tree and adds them to a container with the following API:
Definition Tree.h:648
openvdb::v13_0::tree::Tree::topologyUnion
void topologyUnion(const Tree< OtherRootNodeType > &other, const bool preserveTiles=false)
Union this tree's set of active values with the active values of the other tree, whose ValueType may ...
Definition Tree.h:1799
openvdb::v13_0::tree::Tree::valueType
Name valueType() const override
Return the name of the type of a voxel's value (e.g., "float" or "vec3d").
Definition Tree.h:291
openvdb::v13_0::tree::Tree::combine2
void combine2(const Tree &a, const OtherTreeType &b, CombineOp &op, bool prune=false)
Definition Tree.h:1888
openvdb::v13_0::tree::Tree::treeDepth
Index treeDepth() const override
Return the depth of this tree.
Definition Tree.h:360
openvdb::v13_0::tree::Tree::root
const RootNodeType & root() const
Definition Tree.h:304
openvdb::v13_0::tree::Tree::beginValueAll
ValueAllCIter beginValueAll() const
Definition Tree.h:1056
openvdb::v13_0::tree::Tree::beginNode
NodeIter beginNode()
Return an iterator over all nodes in this tree.
Definition Tree.h:1034
openvdb::v13_0::tree::Tree::getAccessor
ConstAccessor getAccessor() const
Return an accessor that provides random read-only access to this tree's voxels.
Definition Tree.h:1402
openvdb::v13_0::tree::Tree::nonLeafCount
Index64 nonLeafCount() const override
Return the number of non-leaf nodes.
Definition Tree.h:389
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::AccessorRegistry
tbb::concurrent_hash_map< ValueAccessorBase< Tree, true > *, bool > AccessorRegistry
Definition Tree.h:1081
openvdb::v13_0::tree::Tree::beginValueAll
ValueAllIter beginValueAll()
Return an iterator over all values (tile and voxel) across all nodes.
Definition Tree.h:1055
openvdb::v13_0::tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 > > >::ValueOnIter
TreeValueIteratorBase< Tree, typename RootNodeType::ValueOnIter > ValueOnIter
Definition Tree.h:1048
openvdb::v13_0::tree::ValueAccessorBase
This base class for ValueAccessors manages registration of an accessor with a tree so that the tree c...
Definition ValueAccessor.h:152
logging.h
OPENVDB_LOG_WARN
#define OPENVDB_LOG_WARN(message)
Log a warning message of the form 'someVar << "some text" << ...'.
Definition logging.h:256
openvdb::v13_0::tools::countActiveLeafVoxels
Index64 countActiveLeafVoxels(const TreeT &tree, bool threaded=true)
Return the total number of active voxels stored in leaf nodes.
Definition Count.h:436
openvdb::v13_0::tools::minMax
math::MinMax< typename TreeT::ValueType > minMax(const TreeT &tree, bool threaded=true)
Return the minimum and maximum active values in this tree.
Definition Count.h:516
openvdb::v13_0::tools::countInactiveVoxels
Index64 countInactiveVoxels(const TreeT &tree, bool threaded=true)
Return the total number of inactive voxels in the tree.
Definition Count.h:461
openvdb::v13_0::tools::countActiveVoxels
Index64 countActiveVoxels(const TreeT &tree, bool threaded=true)
Return the total number of active voxels in the tree.
Definition Count.h:413
openvdb::v13_0::tools::memUsage
Index64 memUsage(const TreeT &tree, bool threaded=true)
Return the total amount of memory in bytes occupied by this tree.
Definition Count.h:493
openvdb::v13_0::tools::countInactiveLeafVoxels
Index64 countInactiveLeafVoxels(const TreeT &tree, bool threaded=true)
Return the total number of inactive voxels stored in leaf nodes.
Definition Count.h:471
openvdb::v13_0::tools::countActiveTiles
Index64 countActiveTiles(const TreeT &tree, bool threaded=true)
Return the total number of active tiles in the tree.
Definition Count.h:482
openvdb::v13_0::tree
Definition PointDataGrid.h:170
openvdb::v13_0::tree::ValueAccessor
ValueAccessorImpl< TreeType, IsSafe, MutexType, openvdb::make_index_sequence< CacheLevels > > ValueAccessor
Default alias for a ValueAccessor. This is simply a helper alias for the generic definition but takes...
Definition ValueAccessor.h:86
openvdb::v13_0::util::formattedInt
FormattedInt< IntT > formattedInt(IntT n)
Definition Formats.h:118
openvdb::v13_0::util::printBytes
OPENVDB_API int printBytes(std::ostream &os, uint64_t bytes, const std::string &head="", const std::string &tail="\n", bool exact=false, int width=8, int precision=3)
openvdb::v13_0::Name
std::string Name
Definition Name.h:19
openvdb::v13_0::Index
Index32 Index
Definition Types.h:34
openvdb::v13_0::zeroVal
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:71
openvdb::v13_0::Index32
uint32_t Index32
Definition Types.h:32
openvdb::v13_0::Index64
uint64_t Index64
Definition Types.h:33
openvdb::v13_0::SharedPtr
std::shared_ptr< T > SharedPtr
Definition Types.h:95
openvdb::v13_0::MergePolicy
MergePolicy
Definition Types.h:573
openvdb::v13_0::MERGE_ACTIVE_STATES
@ MERGE_ACTIVE_STATES
Definition Types.h:574
openvdb::v13_0::MERGE_NODES
@ MERGE_NODES
Definition Types.h:575
openvdb::v13_0::MERGE_ACTIVE_STATES_AND_NODES
@ MERGE_ACTIVE_STATES_AND_NODES
Definition Types.h:576
openvdb::v13_0::typeNameAsString
const char * typeNameAsString()
Definition Types.h:583
openvdb
Definition Exceptions.h:13
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
Types.h
openvdb::v13_0::tree::CombineOpAdapter
Helper class to adapt a three-argument (a, b, result) CombineOp functor into a single-argument functo...
Definition Tree.h:1830
openvdb::v13_0::tree::CombineOpAdapter::operator()
void operator()(CombineArgs< AValueT, BValueT > &args) const
Definition Tree.h:1833
openvdb::v13_0::tree::CombineOpAdapter::CombineOpAdapter
CombineOpAdapter(CombineOp &_op)
Definition Tree.h:1831
openvdb::v13_0::tree::CombineOpAdapter::op
CombineOp & op
Definition Tree.h:1837
openvdb::v13_0::tree::Tree3
Tree3<T, N1, N2>::Type is the type of a three-level tree (Root, Internal, Leaf) with value type T and...
Definition Tree.h:1115
openvdb::v13_0::tree::Tree3::Type
Tree< RootNode< InternalNode< LeafNode< T, N2 >, N1 > > > Type
Definition Tree.h:1116
openvdb::v13_0::tree::Tree4
Tree4<T, N1, N2, N3>::Type is the type of a four-level tree (Root, Internal, Internal,...
Definition Tree.h:1125
openvdb::v13_0::tree::Type::Type
Tree< RootNode< InternalNode< InternalNode< LeafNode< bool, N3 >, N2 >, N1 > > > Type
Definition Tree.h:1126
openvdb::v13_0::tree::Tree5
Tree5<T, N1, N2, N3, N4>::Type is the type of a five-level tree (Root, Internal, Internal,...
Definition Tree.h:1134
openvdb::v13_0::tree::Tree5::Type
Tree< RootNode< InternalNode< InternalNode< InternalNode< LeafNode< T, N4 >, N3 >, N2 >, N1 > > > Type
Definition Tree.h:1135
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::LeafCIter >::begin
static TreeT::LeafCIter begin(const TreeT &tree)
Definition Tree.h:1232
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::LeafIter >::begin
static TreeT::LeafIter begin(TreeT &tree)
Definition Tree.h:1228
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::NodeCIter >::begin
static TreeT::NodeCIter begin(const TreeT &tree)
Definition Tree.h:1224
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::NodeIter >::begin
static TreeT::NodeIter begin(TreeT &tree)
Definition Tree.h:1220
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::RootNodeType::ChildAllCIter >::begin
static TreeT::RootNodeType::ChildAllCIter begin(const TreeT &tree)
Definition Tree.h:1214
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::RootNodeType::ChildAllIter >::begin
static TreeT::RootNodeType::ChildAllIter begin(TreeT &tree)
Definition Tree.h:1208
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::RootNodeType::ChildOffCIter >::begin
static TreeT::RootNodeType::ChildOffCIter begin(const TreeT &tree)
Definition Tree.h:1202
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::RootNodeType::ChildOffIter >::begin
static TreeT::RootNodeType::ChildOffIter begin(TreeT &tree)
Definition Tree.h:1196
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::RootNodeType::ChildOnCIter >::begin
static TreeT::RootNodeType::ChildOnCIter begin(const TreeT &tree)
Definition Tree.h:1190
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::RootNodeType::ChildOnIter >::begin
static TreeT::RootNodeType::ChildOnIter begin(TreeT &tree)
Definition Tree.h:1184
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::ValueAllCIter >::begin
static TreeT::ValueAllCIter begin(const TreeT &tree)
Definition Tree.h:1256
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::ValueAllIter >::begin
static TreeT::ValueAllIter begin(TreeT &tree)
Definition Tree.h:1252
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::ValueOffCIter >::begin
static TreeT::ValueOffCIter begin(const TreeT &tree)
Definition Tree.h:1248
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::ValueOffIter >::begin
static TreeT::ValueOffIter begin(TreeT &tree)
Definition Tree.h:1244
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::ValueOnCIter >::begin
static TreeT::ValueOnCIter begin(const TreeT &tree)
Definition Tree.h:1240
openvdb::v13_0::tree::TreeIterTraits< TreeT, typename TreeT::ValueOnIter >::begin
static TreeT::ValueOnIter begin(TreeT &tree)
Definition Tree.h:1236
openvdb::v13_0::tree::TreeIterTraits
TreeIterTraits provides, for all tree iterators, a begin(tree) function that returns an iterator over...
Definition Tree.h:1181
openvdb::v13_0::tree::Tree::DeallocateNodes
Definition Tree.h:1090
openvdb::v13_0::tree::Tree::DeallocateNodes::DeallocateNodes
DeallocateNodes(std::vector< NodeType * > &nodes)
Definition Tree.h:1091
openvdb::v13_0::tree::Tree::DeallocateNodes::mNodes
NodeType **const mNodes
Definition Tree.h:1098
openvdb::v13_0::tree::Tree::DeallocateNodes::operator()
void operator()(const tbb::blocked_range< size_t > &range) const
Definition Tree.h:1093
openvdb::v13_0::tree::Tree::ValueConverter
ValueConverter<T>::Type is the type of a tree having the same hierarchy as this tree but a different ...
Definition Tree.h:219
openvdb::v13_0::tree::Tree::ValueConverter::Type
Tree< typename RootNodeType::template ValueConverter< OtherValueType >::Type > Type
Definition Tree.h:220
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218