HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LeafNodeMask.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
4 #ifndef OPENVDB_TREE_LEAF_NODE_MASK_HAS_BEEN_INCLUDED
5 #define OPENVDB_TREE_LEAF_NODE_MASK_HAS_BEEN_INCLUDED
6 
7 #include <openvdb/version.h>
8 #include <openvdb/Types.h>
9 #include <openvdb/io/Compression.h> // for io::readData(), etc.
10 #include <openvdb/math/Math.h> // for math::isZero()
11 #include <openvdb/util/NodeMasks.h>
12 #include "LeafNode.h"
13 #include "Iterator.h"
14 #include <iostream>
15 #include <sstream>
16 #include <string>
17 #include <type_traits>
18 #include <vector>
19 
20 
21 namespace openvdb {
23 namespace OPENVDB_VERSION_NAME {
24 namespace tree {
25 
26 /// @brief LeafNode specialization for values of type ValueMask that encodes both
27 /// the active states and the boolean values of (2^Log2Dim)^3 voxels
28 /// in a single bit mask, i.e. voxel values and states are indistinguishable!
29 template<Index Log2Dim>
30 class LeafNode<ValueMask, Log2Dim>
31 {
32 public:
34  using BuildType = ValueMask;// this is a rare case where
35  using ValueType = bool;// value type != build type
36  using Buffer = LeafBuffer<ValueType, Log2Dim>;// buffer uses the bool specialization
39 
40  // These static declarations must be on separate lines to avoid VC9 compiler errors.
41  static const Index LOG2DIM = Log2Dim; // needed by parent nodes
42  static const Index TOTAL = Log2Dim; // needed by parent nodes
43  static const Index DIM = 1 << TOTAL; // dimension along one coordinate direction
44  static const Index NUM_VALUES = 1 << 3 * Log2Dim;
45  static const Index NUM_VOXELS = NUM_VALUES; // total number of voxels represented by this node
46  static const Index SIZE = NUM_VALUES;
47  static const Index LEVEL = 0; // level 0 = leaf
48 
49  /// @brief ValueConverter<T>::Type is the type of a LeafNode having the same
50  /// dimensions as this node but a different value type, T.
51  template<typename OtherValueType>
52  struct ValueConverter { using Type = LeafNode<OtherValueType, Log2Dim>; };
53 
54  /// @brief SameConfiguration<OtherNodeType>::value is @c true if and only if
55  /// OtherNodeType is the type of a LeafNode with the same dimensions as this node.
56  template<typename OtherNodeType>
57  struct SameConfiguration {
59  };
60 
61  /// Default constructor
62  LeafNode();
63 
64  /// Constructor
65  /// @param xyz the coordinates of a voxel that lies within the node
66  /// @param value the initial value = state for all of this node's voxels
67  /// @param dummy dummy value
68  explicit LeafNode(const Coord& xyz, bool value = false, bool dummy = false);
69 
70  /// "Partial creation" constructor used during file input
71  LeafNode(PartialCreate, const Coord& xyz, bool value = false, bool dummy = false);
72 
73  /// Deep copy constructor
74  LeafNode(const LeafNode&);
75 
76  /// Value conversion copy constructor
77  template<typename OtherValueType>
78  explicit LeafNode(const LeafNode<OtherValueType, Log2Dim>& other);
79 
80  /// Topology copy constructor
81  template<typename ValueType>
83 
84  //@{
85  /// @brief Topology copy constructor
86  /// @note This variant exists mainly to enable template instantiation.
87  template<typename ValueType>
88  LeafNode(const LeafNode<ValueType, Log2Dim>& other, bool offValue, bool onValue, TopologyCopy);
89  template<typename ValueType>
90  LeafNode(const LeafNode<ValueType, Log2Dim>& other, bool background, TopologyCopy);
91  //@}
92 
93  /// Destructor
94  ~LeafNode();
95 
96  //
97  // Statistics
98  //
99  /// Return log2 of the size of the buffer storage.
100  static Index log2dim() { return Log2Dim; }
101  /// Return the number of voxels in each dimension.
102  static Index dim() { return DIM; }
103  /// Return the total number of voxels represented by this LeafNode
104  static Index size() { return SIZE; }
105  /// Return the total number of voxels represented by this LeafNode
106  static Index numValues() { return SIZE; }
107  /// Return the level of this node, which by definition is zero for LeafNodes
108  static Index getLevel() { return LEVEL; }
109  /// Append the Log2Dim of this LeafNode to the specified vector
110  static void getNodeLog2Dims(std::vector<Index>& dims) { dims.push_back(Log2Dim); }
111  /// Return the dimension of child nodes of this LeafNode, which is one for voxels.
112  static Index getChildDim() { return 1; }
113  /// Return the leaf count for this node, which is one.
114  static Index32 leafCount() { return 1; }
115  /// no-op
116  void nodeCount(std::vector<Index32> &) const {}
117  /// Return the non-leaf count for this node, which is zero.
118  static Index32 nonLeafCount() { return 0; }
119 
120  /// Return the number of active voxels.
121  Index64 onVoxelCount() const { return mBuffer.mData.countOn(); }
122  /// Return the number of inactive voxels.
123  Index64 offVoxelCount() const { return mBuffer.mData.countOff(); }
124  Index64 onLeafVoxelCount() const { return this->onVoxelCount(); }
125  Index64 offLeafVoxelCount() const { return this->offVoxelCount(); }
126  static Index64 onTileCount() { return 0; }
127  static Index64 offTileCount() { return 0; }
128 
129  /// Return @c true if this node has no active voxels.
130  bool isEmpty() const { return mBuffer.mData.isOff(); }
131  /// Return @c true if this node only contains active voxels.
132  bool isDense() const { return mBuffer.mData.isOn(); }
133  /// @brief Return @c true if memory for this node's buffer has been allocated.
134  /// @details Currently, boolean leaf nodes don't support partial creation,
135  /// so this always returns @c true.
136  bool isAllocated() const { return true; }
137  /// @brief Allocate memory for this node's buffer if it has not already been allocated.
138  /// @details Currently, boolean leaf nodes don't support partial creation,
139  /// so this has no effect.
140  bool allocate() { return true; }
141 
142  /// Return the memory in bytes occupied by this node.
143  Index64 memUsage() const;
144  Index64 memUsageIfLoaded() const;
145 
146  /// Expand the given bounding box so that it includes this leaf node's active voxels.
147  /// If visitVoxels is false this LeafNode will be approximated as dense, i.e. with all
148  /// voxels active. Else the individual active voxels are visited to produce a tight bbox.
149  void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const;
150 
151  /// @brief Return the bounding box of this node, i.e., the full index space
152  /// spanned by this leaf node.
153  CoordBBox getNodeBoundingBox() const { return CoordBBox::createCube(mOrigin, DIM); }
154 
155  /// Set the grid index coordinates of this node's local origin.
156  void setOrigin(const Coord& origin) { mOrigin = origin; }
157  //@{
158  /// Return the grid index coordinates of this node's local origin.
159  const Coord& origin() const { return mOrigin; }
160  void getOrigin(Coord& origin) const { origin = mOrigin; }
161  void getOrigin(Int32& x, Int32& y, Int32& z) const { mOrigin.asXYZ(x, y, z); }
162  //@}
163 
164  /// Return the linear table offset of the given global or local coordinates.
165  static Index coordToOffset(const Coord& xyz);
166  /// @brief Return the local coordinates for a linear table offset,
167  /// where offset 0 has coordinates (0, 0, 0).
168  static Coord offsetToLocalCoord(Index n);
169  /// Return the global coordinates for a linear table offset.
170  Coord offsetToGlobalCoord(Index n) const;
171 
172  /// Return the transient data value.
173  Index32 transientData() const { return mTransientData; }
174  /// Set the transient data value.
176 
177  /// Return a string representation of this node.
178  std::string str() const;
179 
180  /// @brief Return @c true if the given node (which may have a different @c ValueType
181  /// than this node) has the same active value topology as this node.
182  template<typename OtherType, Index OtherLog2Dim>
183  bool hasSameTopology(const LeafNode<OtherType, OtherLog2Dim>* other) const;
184 
185  /// Check for buffer equivalence by value.
186  bool operator==(const LeafNode&) const;
187  bool operator!=(const LeafNode&) const;
188 
189  //
190  // Buffer management
191  //
192  /// @brief Exchange this node's data buffer with the given data buffer
193  /// without changing the active states of the values.
194  void swap(Buffer& other) { mBuffer.swap(other); }
195  const Buffer& buffer() const { return mBuffer; }
196  Buffer& buffer() { return mBuffer; }
197 
198  //
199  // I/O methods
200  //
201  /// Read in just the topology.
202  void readTopology(std::istream&, bool fromHalf = false);
203  /// Write out just the topology.
204  void writeTopology(std::ostream&, bool toHalf = false) const;
205 
206  /// Read in the topology and the origin.
207  void readBuffers(std::istream&, bool fromHalf = false);
208  void readBuffers(std::istream& is, const CoordBBox&, bool fromHalf = false);
209  /// Write out the topology and the origin.
210  void writeBuffers(std::ostream&, bool toHalf = false) const;
211 
212  //
213  // Accessor methods
214  //
215  /// Return the value of the voxel at the given coordinates.
216  const bool& getValue(const Coord& xyz) const;
217  /// Return the value of the voxel at the given offset.
218  const bool& getValue(Index offset) const;
219 
220  /// @brief Return @c true if the voxel at the given coordinates is active.
221  /// @param xyz the coordinates of the voxel to be probed
222  /// @param[out] val the value of the voxel at the given coordinates
223  bool probeValue(const Coord& xyz, bool& val) const;
224 
225  /// Return the level (0) at which leaf node values reside.
226  static Index getValueLevel(const Coord&) { return LEVEL; }
227 
228  /// Set the active state of the voxel at the given coordinates but don't change its value.
229  void setActiveState(const Coord& xyz, bool on);
230  /// Set the active state of the voxel at the given offset but don't change its value.
231  void setActiveState(Index offset, bool on) { assert(offset<SIZE); mBuffer.mData.set(offset, on); }
232 
233  /// Set the value of the voxel at the given coordinates but don't change its active state.
234  void setValueOnly(const Coord& xyz, bool val);
235  /// Set the value of the voxel at the given offset but don't change its active state.
236  void setValueOnly(Index offset, bool val) { assert(offset<SIZE); mBuffer.setValue(offset,val); }
237 
238  /// Mark the voxel at the given coordinates as inactive but don't change its value.
239  void setValueOff(const Coord& xyz) { mBuffer.mData.setOff(this->coordToOffset(xyz)); }
240  /// Mark the voxel at the given offset as inactive but don't change its value.
241  void setValueOff(Index offset) { assert(offset < SIZE); mBuffer.mData.setOff(offset); }
242 
243  /// Set the value of the voxel at the given coordinates and mark the voxel as inactive.
244  void setValueOff(const Coord& xyz, bool val);
245  /// Set the value of the voxel at the given offset and mark the voxel as inactive.
246  void setValueOff(Index offset, bool val);
247 
248  /// Mark the voxel at the given coordinates as active but don't change its value.
249  void setValueOn(const Coord& xyz) { mBuffer.mData.setOn(this->coordToOffset(xyz)); }
250  /// Mark the voxel at the given offset as active but don't change its value.
251  void setValueOn(Index offset) { assert(offset < SIZE); mBuffer.mData.setOn(offset); }
252 
253  /// Set the value of the voxel at the given coordinates and mark the voxel as active.
254  void setValueOn(const Coord& xyz, bool val);
255  /// Set the value of the voxel at the given coordinates and mark the voxel as active.
256  void setValue(const Coord& xyz, bool val) { this->setValueOn(xyz, val); }
257  /// Set the value of the voxel at the given offset and mark the voxel as active.
258  void setValueOn(Index offset, bool val);
259 
260  /// @brief Apply a functor to the value of the voxel at the given offset
261  /// and mark the voxel as active.
262  template<typename ModifyOp>
263  void modifyValue(Index offset, const ModifyOp& op);
264  /// @brief Apply a functor to the value of the voxel at the given coordinates
265  /// and mark the voxel as active.
266  template<typename ModifyOp>
267  void modifyValue(const Coord& xyz, const ModifyOp& op);
268 
269  /// Apply a functor to the voxel at the given coordinates.
270  template<typename ModifyOp>
271  void modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op);
272 
273  /// Mark all voxels as active but don't change their values.
274  void setValuesOn() { mBuffer.mData.setOn(); }
275  /// Mark all voxels as inactive but don't change their values.
276  void setValuesOff() { mBuffer.mData.setOff(); }
277 
278  /// Return @c true if the voxel at the given coordinates is active.
279  bool isValueOn(const Coord& xyz) const { return mBuffer.mData.isOn(this->coordToOffset(xyz)); }
280  /// Return @c true if the voxel at the given offset is active.
281  bool isValueOn(Index offset) const { assert(offset < SIZE); return mBuffer.mData.isOn(offset); }
282 
283  /// Return @c false since leaf nodes never contain tiles.
284  static bool hasActiveTiles() { return false; }
285 
286  /// Set all voxels that lie outside the given axis-aligned box to the background.
287  void clip(const CoordBBox&, bool background);
288 
289  /// Set all voxels within an axis-aligned box to the specified value.
290  void fill(const CoordBBox& bbox, bool value, bool = false);
291  /// Set all voxels within an axis-aligned box to the specified value.
292  void denseFill(const CoordBBox& bbox, bool value, bool = false) { this->fill(bbox, value); }
293 
294  /// Set the state of all voxels to the specified active state.
295  void fill(const bool& value, bool dummy = false);
296 
297  /// @brief Copy into a dense grid the values of the voxels that lie within
298  /// a given bounding box.
299  ///
300  /// @param bbox inclusive bounding box of the voxels to be copied into the dense grid
301  /// @param dense dense grid with a stride in @e z of one (see tools::Dense
302  /// in tools/Dense.h for the required API)
303  ///
304  /// @note @a bbox is assumed to be identical to or contained in the coordinate domains
305  /// of both the dense grid and this node, i.e., no bounds checking is performed.
306  /// @note Consider using tools::CopyToDense in tools/Dense.h
307  /// instead of calling this method directly.
308  template<typename DenseT>
309  void copyToDense(const CoordBBox& bbox, DenseT& dense) const;
310 
311  /// @brief Copy from a dense grid into this node the values of the voxels
312  /// that lie within a given bounding box.
313  /// @details Only values that are different (by more than the given tolerance)
314  /// from the background value will be active. Other values are inactive
315  /// and truncated to the background value.
316  ///
317  /// @param bbox inclusive bounding box of the voxels to be copied into this node
318  /// @param dense dense grid with a stride in @e z of one (see tools::Dense
319  /// in tools/Dense.h for the required API)
320  /// @param background background value of the tree that this node belongs to
321  /// @param tolerance tolerance within which a value equals the background value
322  ///
323  /// @note @a bbox is assumed to be identical to or contained in the coordinate domains
324  /// of both the dense grid and this node, i.e., no bounds checking is performed.
325  /// @note Consider using tools::CopyFromDense in tools/Dense.h
326  /// instead of calling this method directly.
327  template<typename DenseT>
328  void copyFromDense(const CoordBBox& bbox, const DenseT& dense, bool background, bool tolerance);
329 
330  /// @brief Return the value of the voxel at the given coordinates.
331  /// @note Used internally by ValueAccessor.
332  template<typename AccessorT>
333  const bool& getValueAndCache(const Coord& xyz, AccessorT&) const {return this->getValue(xyz);}
334 
335  /// @brief Return @c true if the voxel at the given coordinates is active.
336  /// @note Used internally by ValueAccessor.
337  template<typename AccessorT>
338  bool isValueOnAndCache(const Coord& xyz, AccessorT&) const { return this->isValueOn(xyz); }
339 
340  /// @brief Change the value of the voxel at the given coordinates and mark it as active.
341  /// @note Used internally by ValueAccessor.
342  template<typename AccessorT>
343  void setValueAndCache(const Coord& xyz, bool val, AccessorT&) { this->setValueOn(xyz, val); }
344 
345  /// @brief Change the value of the voxel at the given coordinates
346  /// but preserve its state.
347  /// @note Used internally by ValueAccessor.
348  template<typename AccessorT>
349  void setValueOnlyAndCache(const Coord& xyz, bool val, AccessorT&) {this->setValueOnly(xyz,val);}
350 
351  /// @brief Change the value of the voxel at the given coordinates and mark it as inactive.
352  /// @note Used internally by ValueAccessor.
353  template<typename AccessorT>
354  void setValueOffAndCache(const Coord& xyz, bool value, AccessorT&)
355  {
356  this->setValueOff(xyz, value);
357  }
358 
359  /// @brief Apply a functor to the value of the voxel at the given coordinates
360  /// and mark the voxel as active.
361  /// @note Used internally by ValueAccessor.
362  template<typename ModifyOp, typename AccessorT>
363  void modifyValueAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&)
364  {
365  this->modifyValue(xyz, op);
366  }
367 
368  /// Apply a functor to the voxel at the given coordinates.
369  /// @note Used internally by ValueAccessor.
370  template<typename ModifyOp, typename AccessorT>
371  void modifyValueAndActiveStateAndCache(const Coord& xyz, const ModifyOp& op, AccessorT&)
372  {
373  this->modifyValueAndActiveState(xyz, op);
374  }
375 
376  /// @brief Set the active state of the voxel at the given coordinates
377  /// without changing its value.
378  /// @note Used internally by ValueAccessor.
379  template<typename AccessorT>
380  void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT&)
381  {
382  this->setActiveState(xyz, on);
383  }
384 
385  /// @brief Return @c true if the voxel at the given coordinates is active
386  /// and return the voxel value in @a val.
387  /// @note Used internally by ValueAccessor.
388  template<typename AccessorT>
389  bool probeValueAndCache(const Coord& xyz, bool& val, AccessorT&) const
390  {
391  return this->probeValue(xyz, val);
392  }
393 
394  /// @brief Return the LEVEL (=0) at which leaf node values reside.
395  /// @note Used internally by ValueAccessor.
396  template<typename AccessorT>
397  static Index getValueLevelAndCache(const Coord&, AccessorT&) { return LEVEL; }
398 
399  /// @brief Return a const reference to the first entry in the buffer.
400  /// @note Since it's actually a reference to a static data member
401  /// it should not be converted to a non-const pointer!
402  const bool& getFirstValue() const { if (mBuffer.mData.isOn(0)) return Buffer::sOn; else return Buffer::sOff; }
403  /// @brief Return a const reference to the last entry in the buffer.
404  /// @note Since it's actually a reference to a static data member
405  /// it should not be converted to a non-const pointer!
406  const bool& getLastValue() const { if (mBuffer.mData.isOn(SIZE-1)) return Buffer::sOn; else return Buffer::sOff; }
407 
408  /// Return @c true if all of this node's voxels have the same active state
409  /// and are equal to within the given tolerance, and return the value in
410  /// @a constValue and the active state in @a state.
411  bool isConstant(bool& constValue, bool& state, bool tolerance = 0) const;
412 
413  /// @brief Computes the median value of all the active and inactive voxels in this node.
414  /// @return The median value.
415  ///
416  /// @details The median for boolean values is defined as the mode
417  /// of the values, i.e. the value that occurs most often.
418  bool medianAll() const;
419 
420  /// @brief Computes the median value of all the active voxels in this node.
421  /// @return The number of active voxels.
422  ///
423  /// @param value Updated with the median value of all the active voxels.
424  ///
425  /// @note Since the value and state are shared for this
426  /// specialization of the LeafNode the @a value will always be true!
427  Index medianOn(ValueType &value) const;
428 
429  /// @brief Computes the median value of all the inactive voxels in this node.
430  /// @return The number of inactive voxels.
431  ///
432  /// @param value Updated with the median value of all the inactive
433  /// voxels.
434  ///
435  /// @note Since the value and state are shared for this
436  /// specialization of the LeafNode the @a value will always be false!
437  Index medianOff(ValueType &value) const;
438 
439  /// Return @c true if all of this node's values are inactive.
440  bool isInactive() const { return mBuffer.mData.isOff(); }
441 
442  /// @brief no-op since for this template specialization voxel
443  /// values and states are indistinguishable.
444  void resetBackground(bool, bool) {}
445 
446  /// @brief Invert the bits of the voxels, i.e. states and values
447  void negate() { mBuffer.mData.toggle(); }
448 
449  template<MergePolicy Policy>
450  void merge(const LeafNode& other, bool bg = false, bool otherBG = false);
451  template<MergePolicy Policy> void merge(bool tileValue, bool tileActive=false);
452 
453  /// @brief No-op
454  /// @details This function exists only to enable template instantiation.
455  void voxelizeActiveTiles(bool = true) {}
456 
457  /// @brief Union this node's set of active values with the active values
458  /// of the other node, whose @c ValueType may be different. So a
459  /// resulting voxel will be active if either of the original voxels
460  /// were active.
461  ///
462  /// @note This operation modifies only active states, not values.
463  template<typename OtherType>
464  void topologyUnion(const LeafNode<OtherType, Log2Dim>& other, const bool preserveTiles = false);
465 
466  /// @brief Intersect this node's set of active values with the active values
467  /// of the other node, whose @c ValueType may be different. So a
468  /// resulting voxel will be active only if both of the original voxels
469  /// were active.
470  ///
471  /// @details The last dummy argument is required to match the signature
472  /// for InternalNode::topologyIntersection.
473  ///
474  /// @note This operation modifies only active states, not
475  /// values. Also note that this operation can result in all voxels
476  /// being inactive so consider subsequently calling prune.
477  template<typename OtherType>
478  void topologyIntersection(const LeafNode<OtherType, Log2Dim>& other, const bool&);
479 
480  /// @brief Difference this node's set of active values with the active values
481  /// of the other node, whose @c ValueType may be different. So a
482  /// resulting voxel will be active only if the original voxel is
483  /// active in this LeafNode and inactive in the other LeafNode.
484  ///
485  /// @details The last dummy argument is required to match the signature
486  /// for InternalNode::topologyDifference.
487  ///
488  /// @note This operation modifies only active states, not values.
489  /// Also, because it can deactivate all of this node's voxels,
490  /// consider subsequently calling prune.
491  template<typename OtherType>
492  void topologyDifference(const LeafNode<OtherType, Log2Dim>& other, const bool&);
493 
494  template<typename CombineOp>
495  void combine(const LeafNode& other, CombineOp& op);
496  template<typename CombineOp>
497  void combine(bool, bool valueIsActive, CombineOp& op);
498 
499  template<typename CombineOp, typename OtherType /*= bool*/>
500  void combine2(const LeafNode& other, const OtherType&, bool valueIsActive, CombineOp&);
501  template<typename CombineOp, typename OtherNodeT /*= LeafNode*/>
502  void combine2(bool, const OtherNodeT& other, bool valueIsActive, CombineOp&);
503  template<typename CombineOp, typename OtherNodeT /*= LeafNode*/>
504  void combine2(const LeafNode& b0, const OtherNodeT& b1, CombineOp&);
505 
506  //@{
507  /// This function exists only to enable template instantiation.
508  void prune(const ValueType& /*tolerance*/ = zeroVal<ValueType>()) {}
509  void addLeaf(LeafNode*) {}
510  template<typename AccessorT>
511  void addLeafAndCache(LeafNode*, AccessorT&) {}
512  template<typename NodeT>
513  NodeT* stealNode(const Coord&, const ValueType&, bool) { return nullptr; }
514  template<typename NodeT>
515  NodeT* probeNode(const Coord&) { return nullptr; }
516  template<typename NodeT>
517  const NodeT* probeConstNode(const Coord&) const { return nullptr; }
518  template<typename ArrayT> void getNodes(ArrayT&) const {}
519  template<typename ArrayT> void stealNodes(ArrayT&, const ValueType&, bool) {}
520  //@}
521 
522  void addTile(Index level, const Coord&, bool val, bool active);
523  void addTile(Index offset, bool val, bool active);
524  template<typename AccessorT>
525  void addTileAndCache(Index level, const Coord&, bool val, bool active, AccessorT&);
526 
527  //@{
528  /// @brief Return a pointer to this node.
529  LeafNode* touchLeaf(const Coord&) { return this; }
530  template<typename AccessorT>
531  LeafNode* touchLeafAndCache(const Coord&, AccessorT&) { return this; }
532  LeafNode* probeLeaf(const Coord&) { return this; }
533  template<typename AccessorT>
534  LeafNode* probeLeafAndCache(const Coord&, AccessorT&) { return this; }
535  template<typename NodeT, typename AccessorT>
536  NodeT* probeNodeAndCache(const Coord&, AccessorT&)
537  {
539  if (!(std::is_same<NodeT, LeafNode>::value)) return nullptr;
540  return reinterpret_cast<NodeT*>(this);
542  }
543  //@}
544  //@{
545  /// @brief Return a @const pointer to this node.
546  const LeafNode* probeLeaf(const Coord&) const { return this; }
547  template<typename AccessorT>
548  const LeafNode* probeLeafAndCache(const Coord&, AccessorT&) const { return this; }
549  const LeafNode* probeConstLeaf(const Coord&) const { return this; }
550  template<typename AccessorT>
551  const LeafNode* probeConstLeafAndCache(const Coord&, AccessorT&) const { return this; }
552  template<typename NodeT, typename AccessorT>
553  const NodeT* probeConstNodeAndCache(const Coord&, AccessorT&) const
554  {
556  if (!(std::is_same<NodeT, LeafNode>::value)) return nullptr;
557  return reinterpret_cast<const NodeT*>(this);
559  }
560  //@}
561 
562  //
563  // Iterators
564  //
565 protected:
569 
570  template<typename MaskIterT, typename NodeT, typename ValueT>
571  struct ValueIter:
572  // Derives from SparseIteratorBase, but can also be used as a dense iterator,
573  // if MaskIterT is a dense mask iterator type.
574  public SparseIteratorBase<MaskIterT, ValueIter<MaskIterT, NodeT, ValueT>, NodeT, ValueT>
575  {
577 
579  ValueIter(const MaskIterT& iter, NodeT* parent): BaseT(iter, parent) {}
580 
581  const bool& getItem(Index pos) const { return this->parent().getValue(pos); }
582  const bool& getValue() const { return this->getItem(this->pos()); }
583 
584  // Note: setItem() can't be called on const iterators.
585  void setItem(Index pos, bool value) const { this->parent().setValueOnly(pos, value); }
586  // Note: setValue() can't be called on const iterators.
587  void setValue(bool value) const { this->setItem(this->pos(), value); }
588 
589  // Note: modifyItem() can't be called on const iterators.
590  template<typename ModifyOp>
591  void modifyItem(Index n, const ModifyOp& op) const { this->parent().modifyValue(n, op); }
592  // Note: modifyValue() can't be called on const iterators.
593  template<typename ModifyOp>
594  void modifyValue(const ModifyOp& op) const { this->modifyItem(this->pos(), op); }
595  };
596 
597  /// Leaf nodes have no children, so their child iterators have no get/set accessors.
598  template<typename MaskIterT, typename NodeT>
599  struct ChildIter:
600  public SparseIteratorBase<MaskIterT, ChildIter<MaskIterT, NodeT>, NodeT, bool>
601  {
603  ChildIter(const MaskIterT& iter, NodeT* parent): SparseIteratorBase<
604  MaskIterT, ChildIter<MaskIterT, NodeT>, NodeT, bool>(iter, parent) {}
605  };
606 
607  template<typename NodeT, typename ValueT>
608  struct DenseIter: public DenseIteratorBase<
609  MaskDenseIter, DenseIter<NodeT, ValueT>, NodeT, /*ChildT=*/void, ValueT>
610  {
613 
615  DenseIter(const MaskDenseIter& iter, NodeT* parent): BaseT(iter, parent) {}
616 
617  bool getItem(Index pos, void*& child, NonConstValueT& value) const
618  {
619  value = this->parent().getValue(pos);
620  child = nullptr;
621  return false; // no child
622  }
623 
624  // Note: setItem() can't be called on const iterators.
625  //void setItem(Index pos, void* child) const {}
626 
627  // Note: unsetItem() can't be called on const iterators.
628  void unsetItem(Index pos, const ValueT& val) const {this->parent().setValueOnly(pos, val);}
629  };
630 
631 public:
632  using ValueOnIter = ValueIter<MaskOnIter, LeafNode, const bool>;
633  using ValueOnCIter = ValueIter<MaskOnIter, const LeafNode, const bool>;
634  using ValueOffIter = ValueIter<MaskOffIter, LeafNode, const bool>;
635  using ValueOffCIter = ValueIter<MaskOffIter, const LeafNode, const bool>;
636  using ValueAllIter = ValueIter<MaskDenseIter, LeafNode, const bool>;
637  using ValueAllCIter = ValueIter<MaskDenseIter, const LeafNode, const bool>;
638  using ChildOnIter = ChildIter<MaskOnIter, LeafNode>;
639  using ChildOnCIter = ChildIter<MaskOnIter, const LeafNode>;
640  using ChildOffIter = ChildIter<MaskOffIter, LeafNode>;
641  using ChildOffCIter = ChildIter<MaskOffIter, const LeafNode>;
642  using ChildAllIter = DenseIter<LeafNode, bool>;
643  using ChildAllCIter = DenseIter<const LeafNode, const bool>;
644 
645  ValueOnCIter cbeginValueOn() const { return ValueOnCIter(mBuffer.mData.beginOn(), this); }
646  ValueOnCIter beginValueOn() const { return ValueOnCIter(mBuffer.mData.beginOn(), this); }
647  ValueOnIter beginValueOn() { return ValueOnIter(mBuffer.mData.beginOn(), this); }
648  ValueOffCIter cbeginValueOff() const { return ValueOffCIter(mBuffer.mData.beginOff(), this); }
649  ValueOffCIter beginValueOff() const { return ValueOffCIter(mBuffer.mData.beginOff(), this); }
650  ValueOffIter beginValueOff() { return ValueOffIter(mBuffer.mData.beginOff(), this); }
651  ValueAllCIter cbeginValueAll() const { return ValueAllCIter(mBuffer.mData.beginDense(), this); }
652  ValueAllCIter beginValueAll() const { return ValueAllCIter(mBuffer.mData.beginDense(), this); }
653  ValueAllIter beginValueAll() { return ValueAllIter(mBuffer.mData.beginDense(), this); }
654 
655  ValueOnCIter cendValueOn() const { return ValueOnCIter(mBuffer.mData.endOn(), this); }
656  ValueOnCIter endValueOn() const { return ValueOnCIter(mBuffer.mData.endOn(), this); }
657  ValueOnIter endValueOn() { return ValueOnIter(mBuffer.mData.endOn(), this); }
658  ValueOffCIter cendValueOff() const { return ValueOffCIter(mBuffer.mData.endOff(), this); }
659  ValueOffCIter endValueOff() const { return ValueOffCIter(mBuffer.mData.endOff(), this); }
660  ValueOffIter endValueOff() { return ValueOffIter(mBuffer.mData.endOff(), this); }
661  ValueAllCIter cendValueAll() const { return ValueAllCIter(mBuffer.mData.endDense(), this); }
662  ValueAllCIter endValueAll() const { return ValueAllCIter(mBuffer.mData.endDense(), this); }
663  ValueAllIter endValueAll() { return ValueAllIter(mBuffer.mData.endDense(), this); }
664 
665  // Note that [c]beginChildOn() and [c]beginChildOff() actually return end iterators,
666  // because leaf nodes have no children.
667  ChildOnCIter cbeginChildOn() const { return ChildOnCIter(mBuffer.mData.endOn(), this); }
668  ChildOnCIter beginChildOn() const { return ChildOnCIter(mBuffer.mData.endOn(), this); }
669  ChildOnIter beginChildOn() { return ChildOnIter(mBuffer.mData.endOn(), this); }
670  ChildOffCIter cbeginChildOff() const { return ChildOffCIter(mBuffer.mData.endOff(), this); }
671  ChildOffCIter beginChildOff() const { return ChildOffCIter(mBuffer.mData.endOff(), this); }
672  ChildOffIter beginChildOff() { return ChildOffIter(mBuffer.mData.endOff(), this); }
673  ChildAllCIter cbeginChildAll() const { return ChildAllCIter(mBuffer.mData.beginDense(), this); }
674  ChildAllCIter beginChildAll() const { return ChildAllCIter(mBuffer.mData.beginDense(), this); }
675  ChildAllIter beginChildAll() { return ChildAllIter(mBuffer.mData.beginDense(), this); }
676 
677  ChildOnCIter cendChildOn() const { return ChildOnCIter(mBuffer.mData.endOn(), this); }
678  ChildOnCIter endChildOn() const { return ChildOnCIter(mBuffer.mData.endOn(), this); }
679  ChildOnIter endChildOn() { return ChildOnIter(mBuffer.mData.endOn(), this); }
680  ChildOffCIter cendChildOff() const { return ChildOffCIter(mBuffer.mData.endOff(), this); }
681  ChildOffCIter endChildOff() const { return ChildOffCIter(mBuffer.mData.endOff(), this); }
682  ChildOffIter endChildOff() { return ChildOffIter(mBuffer.mData.endOff(), this); }
683  ChildAllCIter cendChildAll() const { return ChildAllCIter(mBuffer.mData.endDense(), this); }
684  ChildAllCIter endChildAll() const { return ChildAllCIter(mBuffer.mData.endDense(), this); }
685  ChildAllIter endChildAll() { return ChildAllIter(mBuffer.mData.endDense(), this); }
686 
687  //
688  // Mask accessors
689  //
690  bool isValueMaskOn(Index n) const { return mBuffer.mData.isOn(n); }
691  bool isValueMaskOn() const { return mBuffer.mData.isOn(); }
692  bool isValueMaskOff(Index n) const { return mBuffer.mData.isOff(n); }
693  bool isValueMaskOff() const { return mBuffer.mData.isOff(); }
694  const NodeMaskType& getValueMask() const { return mBuffer.mData; }
695  const NodeMaskType& valueMask() const { return mBuffer.mData; }
696  NodeMaskType& getValueMask() { return mBuffer.mData; }
697  void setValueMask(const NodeMaskType& mask) { mBuffer.mData = mask; }
698  bool isChildMaskOn(Index) const { return false; } // leaf nodes have no children
699  bool isChildMaskOff(Index) const { return true; }
700  bool isChildMaskOff() const { return true; }
701 protected:
702  void setValueMask(Index n, bool on) { mBuffer.mData.set(n, on); }
703  void setValueMaskOn(Index n) { mBuffer.mData.setOn(n); }
704  void setValueMaskOff(Index n) { mBuffer.mData.setOff(n); }
705 
706  /// Compute the origin of the leaf node that contains the voxel with the given coordinates.
707  static void evalNodeOrigin(Coord& xyz) { xyz &= ~(DIM - 1); }
708 
709  /// Bitmask representing the values AND state of voxels
711  /// Global grid index coordinates (x,y,z) of the local origin of this node
712  Coord mOrigin;
713  /// Transient data (not serialized)
714  Index32 mTransientData = 0;
715 
716 private:
717  /// @brief During topology-only construction, access is needed
718  /// to protected/private members of other template instances.
719  template<typename, Index> friend class LeafNode;
720 
721  friend struct ValueIter<MaskOnIter, LeafNode, bool>;
722  friend struct ValueIter<MaskOffIter, LeafNode, bool>;
723  friend struct ValueIter<MaskDenseIter, LeafNode, bool>;
724  friend struct ValueIter<MaskOnIter, const LeafNode, bool>;
725  friend struct ValueIter<MaskOffIter, const LeafNode, bool>;
726  friend struct ValueIter<MaskDenseIter, const LeafNode, bool>;
727 
728  //@{
729  /// Allow iterators to call mask accessor methods (see below).
730  /// @todo Make mask accessors public?
734  //@}
735 
736  template<typename, Index> friend class LeafBuffer;
737 
738 }; // class LeafNode<ValueMask>
739 
740 
741 ////////////////////////////////////////
742 
743 
744 template<Index Log2Dim>
745 inline
747  : mOrigin(0, 0, 0)
748 {
749 }
750 
751 template<Index Log2Dim>
752 inline
754  : mBuffer(value || active)
755  , mOrigin(xyz & (~(DIM - 1)))
756 {
757 }
758 
759 
760 template<Index Log2Dim>
761 inline
763  : mBuffer(value || active)
764  , mOrigin(xyz & (~(DIM - 1)))
765 {
766 }
767 
768 
769 template<Index Log2Dim>
770 inline
772  : mBuffer(other.mBuffer)
773  , mOrigin(other.mOrigin)
774  , mTransientData(other.mTransientData)
775 {
776 }
777 
778 
779 // Copy-construct from a leaf node with the same configuration but a different ValueType.
780 template<Index Log2Dim>
781 template<typename ValueT>
782 inline
784  : mBuffer(other.valueMask())
785  , mOrigin(other.origin())
786  , mTransientData(other.mTransientData)
787 {
788 }
789 
790 
791 template<Index Log2Dim>
792 template<typename ValueT>
793 inline
795  bool, TopologyCopy)
796  : mBuffer(other.valueMask())// value = active state
797  , mOrigin(other.origin())
798  , mTransientData(other.mTransientData)
799 {
800 }
801 
802 
803 template<Index Log2Dim>
804 template<typename ValueT>
805 inline
807  : mBuffer(other.valueMask())// value = active state
808  , mOrigin(other.origin())
809  , mTransientData(other.mTransientData)
810 {
811 }
812 
813 
814 template<Index Log2Dim>
815 template<typename ValueT>
816 inline
818  bool offValue, bool onValue, TopologyCopy)
819  : mBuffer(other.valueMask())
820  , mOrigin(other.origin())
821  , mTransientData(other.mTransientData)
822 {
823  if (offValue==true) {
824  if (onValue==false) {
825  mBuffer.mData.toggle();
826  } else {
827  mBuffer.mData.setOn();
828  }
829  }
830 }
831 
832 
833 template<Index Log2Dim>
834 inline
836 {
837 }
838 
839 
840 ////////////////////////////////////////
841 
842 
843 template<Index Log2Dim>
844 inline Index64
846 {
847  // Use sizeof(*this) to capture alignment-related padding
848  return sizeof(*this);
849 }
850 
851 
852 template<Index Log2Dim>
853 inline Index64
855 {
856  // Use sizeof(*this) to capture alignment-related padding
857  return sizeof(*this);
858 }
859 
860 
861 template<Index Log2Dim>
862 inline void
864 {
865  CoordBBox this_bbox = this->getNodeBoundingBox();
866  if (bbox.isInside(this_bbox)) return;//this LeafNode is already enclosed in the bbox
867  if (ValueOnCIter iter = this->cbeginValueOn()) {//any active values?
868  if (visitVoxels) {//use voxel granularity?
869  this_bbox.reset();
870  for(; iter; ++iter) this_bbox.expand(this->offsetToLocalCoord(iter.pos()));
871  this_bbox.translate(this->origin());
872  }
873  bbox.expand(this_bbox);
874  }
875 }
876 
877 
878 template<Index Log2Dim>
879 template<typename OtherType, Index OtherLog2Dim>
880 inline bool
882 {
883  assert(other);
884  return (Log2Dim == OtherLog2Dim && mBuffer.mData == other->getValueMask());
885 }
886 
887 
888 template<Index Log2Dim>
889 inline std::string
891 {
892  std::ostringstream ostr;
893  ostr << "LeafNode @" << mOrigin << ": ";
894  for (Index32 n = 0; n < SIZE; ++n) ostr << (mBuffer.mData.isOn(n) ? '#' : '.');
895  return ostr.str();
896 }
897 
898 
899 ////////////////////////////////////////
900 
901 
902 template<Index Log2Dim>
903 inline Index
905 {
906  assert ((xyz[0] & (DIM-1u)) < DIM && (xyz[1] & (DIM-1u)) < DIM && (xyz[2] & (DIM-1u)) < DIM);
907  return ((xyz[0] & (DIM-1u)) << 2*Log2Dim)
908  + ((xyz[1] & (DIM-1u)) << Log2Dim)
909  + (xyz[2] & (DIM-1u));
910 }
911 
912 
913 template<Index Log2Dim>
914 inline Coord
916 {
917  assert(n < (1 << 3*Log2Dim));
918  Coord xyz;
919  xyz.setX(n >> 2*Log2Dim);
920  n &= ((1 << 2*Log2Dim) - 1);
921  xyz.setY(n >> Log2Dim);
922  xyz.setZ(n & ((1 << Log2Dim) - 1));
923  return xyz;
924 }
925 
926 
927 template<Index Log2Dim>
928 inline Coord
930 {
931  return (this->offsetToLocalCoord(n) + this->origin());
932 }
933 
934 
935 ////////////////////////////////////////
936 
937 
938 template<Index Log2Dim>
939 inline void
940 LeafNode<ValueMask, Log2Dim>::readTopology(std::istream& is, bool /*fromHalf*/)
941 {
942  mBuffer.mData.load(is);
943 }
944 
945 
946 template<Index Log2Dim>
947 inline void
948 LeafNode<ValueMask, Log2Dim>::writeTopology(std::ostream& os, bool /*toHalf*/) const
949 {
950  mBuffer.mData.save(os);
951 }
952 
953 
954 template<Index Log2Dim>
955 inline void
956 LeafNode<ValueMask, Log2Dim>::readBuffers(std::istream& is, const CoordBBox& clipBBox, bool fromHalf)
957 {
958  // Boolean LeafNodes don't currently implement lazy loading.
959  // Instead, load the full buffer, then clip it.
960 
961  this->readBuffers(is, fromHalf);
962 
963  // Get this tree's background value.
964  bool background = false;
965  if (const void* bgPtr = io::getGridBackgroundValuePtr(is)) {
966  background = *static_cast<const bool*>(bgPtr);
967  }
968  this->clip(clipBBox, background);
969 }
970 
971 
972 template<Index Log2Dim>
973 inline void
974 LeafNode<ValueMask, Log2Dim>::readBuffers(std::istream& is, bool /*fromHalf*/)
975 {
976  // Read in the value mask = buffer.
977  mBuffer.mData.load(is);
978  // Read in the origin.
979  is.read(reinterpret_cast<char*>(&mOrigin), sizeof(Coord::ValueType) * 3);
980 }
981 
982 
983 template<Index Log2Dim>
984 inline void
985 LeafNode<ValueMask, Log2Dim>::writeBuffers(std::ostream& os, bool /*toHalf*/) const
986 {
987  // Write out the value mask = buffer.
988  mBuffer.mData.save(os);
989  // Write out the origin.
990  os.write(reinterpret_cast<const char*>(&mOrigin), sizeof(Coord::ValueType) * 3);
991 }
992 
993 
994 ////////////////////////////////////////
995 
996 
997 template<Index Log2Dim>
998 inline bool
1000 {
1001  return mOrigin == other.mOrigin && mBuffer == other.mBuffer;
1002 }
1003 
1004 
1005 template<Index Log2Dim>
1006 inline bool
1008 {
1009  return !(this->operator==(other));
1010 }
1011 
1012 
1013 ////////////////////////////////////////
1014 
1015 
1016 template<Index Log2Dim>
1017 inline bool
1018 LeafNode<ValueMask, Log2Dim>::isConstant(bool& constValue, bool& state, bool) const
1019 {
1020  if (!mBuffer.mData.isConstant(state)) return false;
1021 
1022  constValue = state;
1023  return true;
1024 }
1025 
1026 
1027 ////////////////////////////////////////
1028 
1029 template<Index Log2Dim>
1030 inline bool
1032 {
1033  const Index countTrue = mBuffer.mData.countOn();
1034  return countTrue > (NUM_VALUES >> 1);
1035 }
1036 
1037 template<Index Log2Dim>
1038 inline Index
1040 {
1041  const Index countTrueOn = mBuffer.mData.countOn();
1042  state = true;//since value and state are the same for this specialization of the leaf node
1043  return countTrueOn;
1044 }
1045 
1046 template<Index Log2Dim>
1047 inline Index
1049 {
1050  const Index countFalseOff = mBuffer.mData.countOff();
1051  state = false;//since value and state are the same for this specialization of the leaf node
1052  return countFalseOff;
1053 }
1054 
1055 
1056 ////////////////////////////////////////
1057 
1058 
1059 template<Index Log2Dim>
1060 inline void
1061 LeafNode<ValueMask, Log2Dim>::addTile(Index /*level*/, const Coord& xyz, bool val, bool active)
1062 {
1063  this->addTile(this->coordToOffset(xyz), val, active);
1064 }
1065 
1066 template<Index Log2Dim>
1067 inline void
1069 {
1070  assert(offset < SIZE);
1071  this->setValueOnly(offset, val);
1072  this->setActiveState(offset, active);
1073 }
1074 
1075 template<Index Log2Dim>
1076 template<typename AccessorT>
1077 inline void
1079  bool val, bool active, AccessorT&)
1080 {
1081  this->addTile(level, xyz, val, active);
1082 }
1083 
1084 
1085 ////////////////////////////////////////
1086 
1087 
1088 template<Index Log2Dim>
1089 inline const bool&
1091 {
1092  // This *CANNOT* use operator ? because Visual C++
1093  if (mBuffer.mData.isOn(this->coordToOffset(xyz))) return Buffer::sOn; else return Buffer::sOff;
1094 }
1095 
1096 
1097 template<Index Log2Dim>
1098 inline const bool&
1100 {
1101  assert(offset < SIZE);
1102  // This *CANNOT* use operator ? for Windows
1103  if (mBuffer.mData.isOn(offset)) return Buffer::sOn; else return Buffer::sOff;
1104 }
1105 
1106 
1107 template<Index Log2Dim>
1108 inline bool
1109 LeafNode<ValueMask, Log2Dim>::probeValue(const Coord& xyz, bool& val) const
1110 {
1111  const Index offset = this->coordToOffset(xyz);
1112  val = mBuffer.mData.isOn(offset);
1113  return val;
1114 }
1115 
1116 
1117 template<Index Log2Dim>
1118 inline void
1120 {
1121  this->setValueOn(this->coordToOffset(xyz), val);
1122 }
1123 
1124 
1125 template<Index Log2Dim>
1126 inline void
1128 {
1129  assert(offset < SIZE);
1130  mBuffer.mData.set(offset, val);
1131 }
1132 
1133 
1134 template<Index Log2Dim>
1135 inline void
1137 {
1138  this->setValueOnly(this->coordToOffset(xyz), val);
1139 }
1140 
1141 
1142 template<Index Log2Dim>
1143 inline void
1145 {
1146  mBuffer.mData.set(this->coordToOffset(xyz), on);
1147 }
1148 
1149 
1150 template<Index Log2Dim>
1151 inline void
1153 {
1154  this->setValueOff(this->coordToOffset(xyz), val);
1155 }
1156 
1157 
1158 template<Index Log2Dim>
1159 inline void
1161 {
1162  assert(offset < SIZE);
1163  mBuffer.mData.set(offset, val);
1164 }
1165 
1166 
1167 template<Index Log2Dim>
1168 template<typename ModifyOp>
1169 inline void
1171 {
1172  bool val = mBuffer.mData.isOn(offset);
1173  op(val);
1174  mBuffer.mData.set(offset, val);
1175 }
1176 
1177 
1178 template<Index Log2Dim>
1179 template<typename ModifyOp>
1180 inline void
1181 LeafNode<ValueMask, Log2Dim>::modifyValue(const Coord& xyz, const ModifyOp& op)
1182 {
1183  this->modifyValue(this->coordToOffset(xyz), op);
1184 }
1185 
1186 
1187 template<Index Log2Dim>
1188 template<typename ModifyOp>
1189 inline void
1190 LeafNode<ValueMask, Log2Dim>::modifyValueAndActiveState(const Coord& xyz, const ModifyOp& op)
1191 {
1192  const Index offset = this->coordToOffset(xyz);
1193  bool val = mBuffer.mData.isOn(offset), state = val;
1194  op(val, state);
1195  mBuffer.mData.set(offset, val);
1196 }
1197 
1198 
1199 ////////////////////////////////////////
1200 
1201 
1202 template<Index Log2Dim>
1203 template<MergePolicy Policy>
1204 inline void
1205 LeafNode<ValueMask, Log2Dim>::merge(const LeafNode& other, bool /*bg*/, bool /*otherBG*/)
1206 {
1208  if (Policy == MERGE_NODES) return;
1209  mBuffer.mData |= other.mBuffer.mData;
1211 }
1212 
1213 template<Index Log2Dim>
1214 template<MergePolicy Policy>
1215 inline void
1217 {
1219  if (Policy != MERGE_ACTIVE_STATES_AND_NODES) return;
1220  if (tileValue) mBuffer.mData.setOn();
1222 }
1223 
1224 
1225 ////////////////////////////////////////
1226 
1227 
1228 template<Index Log2Dim>
1229 template<typename OtherType>
1230 inline void
1232 {
1233  mBuffer.mData |= other.valueMask();
1234 }
1235 
1236 
1237 template<Index Log2Dim>
1238 template<typename OtherType>
1239 inline void
1241  const bool&)
1242 {
1243  mBuffer.mData &= other.valueMask();
1244 }
1245 
1246 
1247 template<Index Log2Dim>
1248 template<typename OtherType>
1249 inline void
1251  const bool&)
1252 {
1253  mBuffer.mData &= !other.valueMask();
1254 }
1255 
1256 
1257 ////////////////////////////////////////
1258 
1259 
1260 template<Index Log2Dim>
1261 inline void
1262 LeafNode<ValueMask, Log2Dim>::clip(const CoordBBox& clipBBox, bool background)
1263 {
1264  CoordBBox nodeBBox = this->getNodeBoundingBox();
1265  if (!clipBBox.hasOverlap(nodeBBox)) {
1266  // This node lies completely outside the clipping region. Fill it with background tiles.
1267  this->fill(nodeBBox, background, /*active=*/false);
1268  } else if (clipBBox.isInside(nodeBBox)) {
1269  // This node lies completely inside the clipping region. Leave it intact.
1270  return;
1271  }
1272 
1273  // This node isn't completely contained inside the clipping region.
1274  // Set any voxels that lie outside the region to the background value.
1275 
1276  // Construct a boolean mask that is on inside the clipping region and off outside it.
1278  nodeBBox.intersect(clipBBox);
1279  Coord xyz;
1280  int &x = xyz.x(), &y = xyz.y(), &z = xyz.z();
1281  for (x = nodeBBox.min().x(); x <= nodeBBox.max().x(); ++x) {
1282  for (y = nodeBBox.min().y(); y <= nodeBBox.max().y(); ++y) {
1283  for (z = nodeBBox.min().z(); z <= nodeBBox.max().z(); ++z) {
1284  mask.setOn(static_cast<Index32>(this->coordToOffset(xyz)));
1285  }
1286  }
1287  }
1288 
1289  // Set voxels that lie in the inactive region of the mask (i.e., outside
1290  // the clipping region) to the background value.
1291  for (MaskOffIter maskIter = mask.beginOff(); maskIter; ++maskIter) {
1292  this->setValueOff(maskIter.pos(), background);
1293  }
1294 }
1295 
1296 
1297 ////////////////////////////////////////
1298 
1299 
1300 template<Index Log2Dim>
1301 inline void
1303 {
1304  auto clippedBBox = this->getNodeBoundingBox();
1305  clippedBBox.intersect(bbox);
1306  if (!clippedBBox) return;
1307 
1308  for (Int32 x = clippedBBox.min().x(); x <= clippedBBox.max().x(); ++x) {
1309  const Index offsetX = (x & (DIM-1u))<<2*Log2Dim;
1310  for (Int32 y = clippedBBox.min().y(); y <= clippedBBox.max().y(); ++y) {
1311  const Index offsetXY = offsetX + ((y & (DIM-1u))<< Log2Dim);
1312  for (Int32 z = clippedBBox.min().z(); z <= clippedBBox.max().z(); ++z) {
1313  const Index offset = offsetXY + (z & (DIM-1u));
1314  mBuffer.mData.set(offset, value);
1315  }
1316  }
1317  }
1318 }
1319 
1320 template<Index Log2Dim>
1321 inline void
1323 {
1324  mBuffer.fill(value);
1325 }
1326 
1327 
1328 ////////////////////////////////////////
1329 
1330 
1331 template<Index Log2Dim>
1332 template<typename DenseT>
1333 inline void
1334 LeafNode<ValueMask, Log2Dim>::copyToDense(const CoordBBox& bbox, DenseT& dense) const
1335 {
1336  using DenseValueType = typename DenseT::ValueType;
1337 
1338  const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1339  const Coord& min = dense.bbox().min();
1340  DenseValueType* t0 = dense.data() + zStride * (bbox.min()[2] - min[2]); // target array
1341  const Int32 n0 = bbox.min()[2] & (DIM-1u);
1342  for (Int32 x = bbox.min()[0], ex = bbox.max()[0] + 1; x < ex; ++x) {
1343  DenseValueType* t1 = t0 + xStride * (x - min[0]);
1344  const Int32 n1 = n0 + ((x & (DIM-1u)) << 2*LOG2DIM);
1345  for (Int32 y = bbox.min()[1], ey = bbox.max()[1] + 1; y < ey; ++y) {
1346  DenseValueType* t2 = t1 + yStride * (y - min[1]);
1347  Int32 n2 = n1 + ((y & (DIM-1u)) << LOG2DIM);
1348  for (Int32 z = bbox.min()[2], ez = bbox.max()[2] + 1; z < ez; ++z, t2 += zStride) {
1349  *t2 = DenseValueType(mBuffer.mData.isOn(n2++));
1350  }
1351  }
1352  }
1353 }
1354 
1355 
1356 template<Index Log2Dim>
1357 template<typename DenseT>
1358 inline void
1360  bool background, bool tolerance)
1361 {
1362  using DenseValueType = typename DenseT::ValueType;
1363  struct Local {
1364  inline static bool toBool(const DenseValueType& v) { return !math::isZero(v); }
1365  };
1366 
1367  const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1368  const Coord& min = dense.bbox().min();
1369  const DenseValueType* s0 = dense.data() + zStride * (bbox.min()[2] - min[2]); // source
1370  const Int32 n0 = bbox.min()[2] & (DIM-1u);
1371  for (Int32 x = bbox.min()[0], ex = bbox.max()[0] + 1; x < ex; ++x) {
1372  const DenseValueType* s1 = s0 + xStride * (x - min[0]);
1373  const Int32 n1 = n0 + ((x & (DIM-1u)) << 2*LOG2DIM);
1374  for (Int32 y = bbox.min()[1], ey = bbox.max()[1] + 1; y < ey; ++y) {
1375  const DenseValueType* s2 = s1 + yStride * (y - min[1]);
1376  Int32 n2 = n1 + ((y & (DIM-1u)) << LOG2DIM);
1377  for (Int32 z = bbox.min()[2], ez = bbox.max()[2]+1; z < ez; ++z, ++n2, s2 += zStride) {
1378  // Note: if tolerance is true (i.e., 1), then all boolean values compare equal.
1379  if (tolerance || (background == Local::toBool(*s2))) {
1380  mBuffer.mData.set(n2, background);
1381  } else {
1382  mBuffer.mData.set(n2, Local::toBool(*s2));
1383  }
1384  }
1385  }
1386  }
1387 }
1388 
1389 
1390 ////////////////////////////////////////
1391 
1392 
1393 template<Index Log2Dim>
1394 template<typename CombineOp>
1395 inline void
1397 {
1399  for (Index i = 0; i < SIZE; ++i) {
1400  bool result = false, aVal = mBuffer.mData.isOn(i), bVal = other.mBuffer.mData.isOn(i);
1401  op(args.setARef(aVal)
1402  .setAIsActive(aVal)
1403  .setBRef(bVal)
1404  .setBIsActive(bVal)
1405  .setResultRef(result));
1406  mBuffer.mData.set(i, result);
1407  }
1408 }
1409 
1410 
1411 template<Index Log2Dim>
1412 template<typename CombineOp>
1413 inline void
1414 LeafNode<ValueMask, Log2Dim>::combine(bool value, bool valueIsActive, CombineOp& op)
1415 {
1417  args.setBRef(value).setBIsActive(valueIsActive);
1418  for (Index i = 0; i < SIZE; ++i) {
1419  bool result = false, aVal = mBuffer.mData.isOn(i);
1420  op(args.setARef(aVal)
1421  .setAIsActive(aVal)
1422  .setResultRef(result));
1423  mBuffer.mData.set(i, result);
1424  }
1425 }
1426 
1427 
1428 ////////////////////////////////////////
1429 
1430 
1431 template<Index Log2Dim>
1432 template<typename CombineOp, typename OtherType>
1433 inline void
1435  bool valueIsActive, CombineOp& op)
1436 {
1438  args.setBRef(value).setBIsActive(valueIsActive);
1439  for (Index i = 0; i < SIZE; ++i) {
1440  bool result = false, aVal = other.mBuffer.mData.isOn(i);
1441  op(args.setARef(aVal)
1442  .setAIsActive(aVal)
1443  .setResultRef(result));
1444  mBuffer.mData.set(i, result);
1445  }
1446 }
1447 
1448 
1449 template<Index Log2Dim>
1450 template<typename CombineOp, typename OtherNodeT>
1451 inline void
1452 LeafNode<ValueMask, Log2Dim>::combine2(bool value, const OtherNodeT& other,
1453  bool valueIsActive, CombineOp& op)
1454 {
1456  args.setARef(value).setAIsActive(valueIsActive);
1457  for (Index i = 0; i < SIZE; ++i) {
1458  bool result = false, bVal = other.mBuffer.mData.isOn(i);
1459  op(args.setBRef(bVal)
1460  .setBIsActive(bVal)
1461  .setResultRef(result));
1462  mBuffer.mData.set(i, result);
1463  }
1464 }
1465 
1466 
1467 template<Index Log2Dim>
1468 template<typename CombineOp, typename OtherNodeT>
1469 inline void
1470 LeafNode<ValueMask, Log2Dim>::combine2(const LeafNode& b0, const OtherNodeT& b1, CombineOp& op)
1471 {
1473  for (Index i = 0; i < SIZE; ++i) {
1474  bool result = false, b0Val = b0.mBuffer.mData.isOn(i), b1Val = b1.mBuffer.mData.isOn(i);
1475  op(args.setARef(b0Val)
1476  .setAIsActive(b0Val)
1477  .setBRef(b1Val)
1478  .setBIsActive(b1Val)
1479  .setResultRef(result));
1480  mBuffer.mData.set(i, result);
1481  }
1482 }
1483 
1484 
1485 } // namespace tree
1486 } // namespace OPENVDB_VERSION_NAME
1487 } // namespace openvdb
1488 
1489 #endif // OPENVDB_TREE_LEAF_NODE_MASK_HAS_BEEN_INCLUDED
void setTransientData(Index32 transientData)
Set the transient data value.
Definition: LeafNodeMask.h:175
static Index dim()
Return the number of voxels in each dimension.
Definition: LeafNodeMask.h:102
LeafNode specialization for values of type ValueMask that encodes both the active states and the bool...
Definition: LeafNodeMask.h:30
ValueIter< MaskOnIter, LeafNode, const bool > ValueOnIter
Definition: LeafNodeMask.h:632
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNodeMask.h:338
void stealNodes(ArrayT &, const ValueType &, bool)
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:519
void topologyUnion(const LeafNode< OtherType, Log2Dim > &other, const bool preserveTiles=false)
Union this node's set of active values with the active values of the other node, whose ValueType may ...
Definition: LeafNode.h:1679
ValueIter< MaskOffIter, LeafNode, const bool > ValueOffIter
Definition: LeafNodeMask.h:634
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:568
OPENVDB_API const void * getGridBackgroundValuePtr(std::ios_base &)
Return a pointer to the background value of the grid currently being read from or written to the give...
bool allocate()
Allocate memory for this node's buffer if it has not already been allocated.
Definition: LeafNodeMask.h:140
const NodeMaskType & valueMask() const
Definition: LeafNode.h:856
bool getItem(Index pos, void *&child, NonConstValueT &value) const
Definition: LeafNodeMask.h:617
void readBuffers(std::istream &is, bool fromHalf=false)
Read buffers from a stream.
Definition: LeafNode.h:1304
const bool & getLastValue() const
Return a const reference to the last entry in the buffer.
Definition: LeafNodeMask.h:406
ValueIter< MaskDenseIter, const LeafNode, const bool > ValueAllCIter
Definition: LeafNodeMask.h:637
void setValueAndCache(const Coord &xyz, bool val, AccessorT &)
Change the value of the voxel at the given coordinates and mark it as active.
Definition: LeafNodeMask.h:343
ChildIter< MaskOffIterator, LeafNode, ChildOff > ChildOffIter
Definition: LeafNode.h:292
void setValueOnly(const Coord &xyz, const ValueType &val)
Set the value of the voxel at the given coordinates but don't change its active state.
Definition: LeafNode.h:1103
void readTopology(std::istream &is, bool fromHalf=false)
Read in just the topology.
Definition: LeafNode.h:1268
void setActiveState(Index offset, bool on)
Set the active state of the voxel at the given offset but don't change its value. ...
Definition: LeafNodeMask.h:231
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:1045
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition: LeafNode.h:417
const NodeT * probeConstNode(const Coord &) const
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:517
void getNodes(ArrayT &) const
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:518
const GLdouble * v
Definition: glcorearb.h:837
static Index size()
Return the total number of voxels represented by this LeafNode.
Definition: LeafNodeMask.h:104
const LeafNode * probeConstLeaf(const Coord &) const
Return a pointer to this node.
Definition: LeafNodeMask.h:549
Buffer mBuffer
Bitmask representing the values AND state of voxels.
Definition: LeafNodeMask.h:710
bool isConstant(ValueType &firstValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
Definition: LeafNode.h:1475
GLsizei const GLchar *const * string
Definition: glcorearb.h:814
GLsizei const GLfloat * value
Definition: glcorearb.h:824
const LeafNode * probeConstLeafAndCache(const Coord &, AccessorT &) const
Return a pointer to this node.
Definition: LeafNodeMask.h:551
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
Index pos() const
Identical to offset.
Definition: Iterator.h:60
LeafNode * touchLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNodeMask.h:531
bool isAllocated() const
Return true if memory for this node's buffer has been allocated.
Definition: LeafNodeMask.h:136
GLint level
Definition: glcorearb.h:108
Coord mOrigin
Global grid index coordinates (x,y,z) of the local origin of this node.
Definition: LeafNodeMask.h:712
Index64 memUsage() const
Return the memory in bytes occupied by this node.
Definition: LeafNode.h:1429
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:239
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:29
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
ChildIter< MaskOnIterator, const LeafNode, ChildOn > ChildOnCIter
Definition: LeafNode.h:291
**But if you need a or simply need to know when the task has note that the like this
Definition: thread.h:617
GLint y
Definition: glcorearb.h:103
ChildIter< MaskOnIterator, LeafNode, ChildOn > ChildOnIter
Definition: LeafNode.h:290
ValueIter< MaskDenseIter, LeafNode, const bool > ValueAllIter
Definition: LeafNodeMask.h:636
void clip(const CoordBBox &, const ValueType &background)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: LeafNode.h:1121
**But if you need a result
Definition: thread.h:613
static Index log2dim()
Return log2 of the size of the buffer storage.
Definition: LeafNodeMask.h:100
NodeT & parent() const
Return a reference to the node over which this iterator is iterating.
Definition: Iterator.h:50
void topologyIntersection(const LeafNode< OtherType, Log2Dim > &other, const ValueType &)
Intersect this node's set of active values with the active values of the other node, whose ValueType may be different. So a resulting voxel will be active only if both of the original voxels were active.
Definition: LeafNode.h:1687
void setValuesOn()
Mark all voxels as active but don't change their values.
Definition: LeafNodeMask.h:274
Tag dispatch class that distinguishes constructors during file input.
Definition: Types.h:689
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition: LeafNodeMask.h:239
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: LeafNode.h:1095
ValueIter< MaskOffIterator, const LeafNode, const ValueType, ValueOff > ValueOffCIter
Definition: LeafNode.h:287
const NodeT * probeConstNodeAndCache(const Coord &, AccessorT &) const
Return a pointer to this node.
Definition: LeafNodeMask.h:553
static Coord offsetToLocalCoord(Index n)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0...
Definition: LeafNode.h:1020
void nodeCount(std::vector< Index32 > &) const
no-op
Definition: LeafNodeMask.h:116
void writeBuffers(std::ostream &os, bool toHalf=false) const
Write buffers to a stream.
Definition: LeafNode.h:1402
ValueIter< MaskDenseIterator, LeafNode, const ValueType, ValueAll > ValueAllIter
Definition: LeafNode.h:288
void prune(const ValueType &=zeroVal< ValueType >())
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:508
static bool hasActiveTiles()
Return false since leaf nodes never contain tiles.
Definition: LeafNodeMask.h:284
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Definition: LeafNodeMask.h:281
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by this leaf node...
Definition: LeafNodeMask.h:153
std::shared_ptr< T > SharedPtr
Definition: Types.h:114
LeafNode * touchLeaf(const Coord &)
Return a pointer to this node.
Definition: LeafNodeMask.h:529
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNode.h:475
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: LeafNodeMask.h:159
void modifyValue(Index offset, const ModifyOp &op)
Apply a functor to the value of the voxel at the given offset and mark the voxel as active...
Definition: LeafNode.h:435
bool isDense() const
Return true if this node only contains active voxels.
Definition: LeafNodeMask.h:132
GLdouble n
Definition: glcorearb.h:2008
OffMaskIterator< NodeMask > OffIterator
Definition: NodeMasks.h:349
Index64 onVoxelCount() const
Return the number of active voxels.
Definition: LeafNodeMask.h:121
GLintptr offset
Definition: glcorearb.h:665
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
Definition: LeafNodeMask.h:156
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
Definition: NodeMasks.h:307
void swap(LeafBuffer &)
Exchange this buffer's values with the other buffer's values.
Definition: LeafBuffer.h:302
void addTile(Index level, const Coord &, const ValueType &, bool)
Definition: LeafNode.h:1580
BBox< Coord > CoordBBox
Definition: NanoVDB.h:2516
Index64 onVoxelCount() const
Return the number of voxels marked On.
Definition: LeafNode.h:140
const bool & getFirstValue() const
Return a const reference to the first entry in the buffer.
Definition: LeafNodeMask.h:402
NodeT * probeNodeAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNodeMask.h:536
ValueIter< MaskOnIter, const LeafNode, const bool > ValueOnCIter
Definition: LeafNodeMask.h:633
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
Definition: LeafNode.h:37
void topologyDifference(const LeafNode< OtherType, Log2Dim > &other, const ValueType &)
Difference this node's set of active values with the active values of the other node, whose ValueType may be different. So a resulting voxel will be active only if the original voxel is active in this LeafNode and inactive in the other LeafNode.
Definition: LeafNode.h:1696
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
const LeafNode * probeLeaf(const Coord &) const
Return a pointer to this node.
Definition: LeafNodeMask.h:546
ValueIter< MaskOnIterator, LeafNode, const ValueType, ValueOn > ValueOnIter
Definition: LeafNode.h:284
void copyToDense(const CoordBBox &bbox, DenseT &dense) const
Copy into a dense grid the values of the voxels that lie within a given bounding box.
Definition: LeafNode.h:1204
void modifyItem(Index n, const ModifyOp &op) const
Definition: LeafNode.h:240
const bool & getValueAndCache(const Coord &xyz, AccessorT &) const
Return the value of the voxel at the given coordinates.
Definition: LeafNodeMask.h:333
static Index getValueLevel(const Coord &)
Return the level (0) at which leaf node values reside.
Definition: LeafNodeMask.h:226
GLint GLuint mask
Definition: glcorearb.h:124
const NodeMaskType & getValueMask() const
Definition: LeafNode.h:854
static Index getLevel()
Return the level of this node, which by definition is zero for LeafNodes.
Definition: LeafNodeMask.h:108
bool operator!=(const LeafNode &other) const
Definition: LeafNode.h:201
constexpr enabler dummy
An instance to use in EnableIf.
Definition: CLI11.h:985
void getOrigin(Int32 &x, Int32 &y, Int32 &z) const
Return the grid index coordinates of this node's local origin.
Definition: LeafNodeMask.h:161
std::string str() const
Return a string representation of this node.
Definition: LeafNode.h:997
typename std::remove_const< UnsetItemT >::type NonConstValueType
Definition: Iterator.h:184
bool isEmpty() const
Return true if this node has no active voxels.
Definition: LeafNodeMask.h:130
ValueType medianAll(ValueType *tmp=nullptr) const
Computes the median value of all the active AND inactive voxels in this node.
Definition: LeafNode.h:1511
static Index32 nonLeafCount()
Return the non-leaf count for this node, which is zero.
Definition: LeafNodeMask.h:118
void setOn(Index32 n)
Set the nth bit on.
Definition: NodeMasks.h:452
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition: LeafNode.h:407
Index64 offVoxelCount() const
Return the number of voxels marked Off.
Definition: LeafNode.h:142
void swap(Buffer &other)
Exchange this node's data buffer with the given data buffer without changing the active states of the...
Definition: LeafNodeMask.h:194
GLint GLenum GLint x
Definition: glcorearb.h:409
void setValueOffAndCache(const Coord &xyz, bool value, AccessorT &)
Change the value of the voxel at the given coordinates and mark it as inactive.
Definition: LeafNodeMask.h:354
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: LeafNode.h:173
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: LeafNode.h:456
static Index32 leafCount()
Return the leaf count for this node, which is one.
Definition: LeafNodeMask.h:114
void denseFill(const CoordBBox &bbox, bool value, bool=false)
Set all voxels within an axis-aligned box to the specified value.
Definition: LeafNodeMask.h:292
that also have some descendant prim *whose name begins with which in turn has a child named baz where *the predicate active
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
Definition: Platform.h:140
void setValueOnly(Index offset, bool val)
Set the value of the voxel at the given offset but don't change its active state. ...
Definition: LeafNodeMask.h:236
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Definition: LeafNode.h:1034
Base class for sparse iterators over internal and leaf nodes.
Definition: Iterator.h:114
void combine2(const LeafNode &other, const OtherType &, bool valueIsActive, CombineOp &)
Definition: LeafNode.h:1760
Index32 transientData() const
Return the transient data value.
Definition: LeafNodeMask.h:173
Index medianOn(ValueType &value, ValueType *tmp=nullptr) const
Computes the median value of all the active voxels in this node.
Definition: LeafNode.h:1529
void modifyValueAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active...
Definition: LeafNodeMask.h:363
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by this leaf node...
Definition: LeafNode.h:167
const LeafNode * probeLeafAndCache(const Coord &, AccessorT &) const
Return a pointer to this node.
Definition: LeafNodeMask.h:548
Base class for dense iterators over internal and leaf nodes.
Definition: Iterator.h:178
void fill(const ValueType &)
Populate this buffer with a constant value.
Definition: LeafBuffer.h:274
bool isInactive() const
Return true if all of this node's values are inactive.
Definition: LeafNodeMask.h:440
DenseMaskIterator< NodeMask > DenseIterator
Definition: NodeMasks.h:350
Library and file format version numbers.
void negate()
Invert the bits of the voxels, i.e. states and values.
Definition: LeafNodeMask.h:447
bool probeValueAndCache(const Coord &xyz, bool &val, AccessorT &) const
Return true if the voxel at the given coordinates is active and return the voxel value in val...
Definition: LeafNodeMask.h:389
LeafNode * probeLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
Definition: LeafNodeMask.h:534
ValueIter< MaskOnIterator, const LeafNode, const ValueType, ValueOn > ValueOnCIter
Definition: LeafNode.h:285
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition: LeafNodeMask.h:249
void setItem(Index pos, const ValueT &value) const
Definition: LeafNode.h:228
NodeT * stealNode(const Coord &, const ValueType &, bool)
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:513
bool probeValue(const Coord &xyz, ValueType &val) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNode.h:1061
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
Definition: Types.h:623
void combine(const LeafNode &other, CombineOp &op)
Definition: LeafNode.h:1720
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: LeafNodeMask.h:371
Index64 offVoxelCount() const
Return the number of inactive voxels.
Definition: LeafNodeMask.h:123
static void getNodeLog2Dims(std::vector< Index > &dims)
Append the Log2Dim of this LeafNode to the specified vector.
Definition: LeafNodeMask.h:110
Index medianOff(ValueType &value, ValueType *tmp=nullptr) const
Computes the median value of all the inactive voxels in this node.
Definition: LeafNode.h:1553
void addTileAndCache(Index, const Coord &, const ValueType &, bool, AccessorT &)
Definition: LeafNode.h:1597
ValueIter< MaskDenseIterator, const LeafNode, const ValueType, ValueAll > ValueAllCIter
Definition: LeafNode.h:289
OnMaskIterator< NodeMask > OnIterator
Definition: NodeMasks.h:348
GLuint GLfloat * val
Definition: glcorearb.h:1608
void setValueOnlyAndCache(const Coord &xyz, bool val, AccessorT &)
Change the value of the voxel at the given coordinates but preserve its state.
Definition: LeafNodeMask.h:349
**If you just want to fire and args
Definition: thread.h:609
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: Types.h:621
ValueIter< MaskOffIter, const LeafNode, const bool > ValueOffCIter
Definition: LeafNodeMask.h:635
void addLeafAndCache(LeafNode *, AccessorT &)
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:511
NodeT * probeNode(const Coord &)
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:515
void setValueOn(Index offset)
Mark the voxel at the given offset as active but don't change its value.
Definition: LeafNodeMask.h:251
void copyFromDense(const CoordBBox &bbox, const DenseT &dense, const ValueType &background, const ValueType &tolerance)
Copy from a dense grid into this node the values of the voxels that lie within a given bounding box...
Definition: LeafNode.h:1231
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:141
static Index getChildDim()
Return the dimension of child nodes of this LeafNode, which is one for voxels.
Definition: LeafNodeMask.h:112
void setValuesOff()
Mark all voxels as inactive but don't change their values.
Definition: LeafNodeMask.h:276
Definition: core.h:1131
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:683
LeafNode * probeLeaf(const Coord &)
Return a pointer to this node.
Definition: LeafNodeMask.h:532
void setValue(Index i, const ValueType &)
Set the i'th value of this buffer to the specified value.
Definition: LeafBuffer.h:232
DenseIter< const LeafNode, const ValueType, ChildAll > ChildAllCIter
Definition: LeafNode.h:295
void setValueOff(Index offset)
Mark the voxel at the given offset as inactive but don't change its value.
Definition: LeafNodeMask.h:241
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition: LeafNodeMask.h:279
bool hasSameTopology(const LeafNode< OtherType, OtherLog2Dim > *other) const
Return true if the given node (which may have a different ValueType than this node) has the same acti...
Definition: LeafNode.h:1467
bool operator==(const LeafNode &other) const
Check for buffer, state and origin equivalence.
Definition: LeafNode.h:1419
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:119
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Definition: LeafNode.h:1449
static Index numValues()
Return the total number of voxels represented by this LeafNode.
Definition: LeafNodeMask.h:106
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition: LeafNode.h:1010
bool ValueType
Definition: NanoVDB.h:5729
static void evalNodeOrigin(Coord &xyz)
Compute the origin of the leaf node that contains the voxel with the given coordinates.
Definition: LeafNodeMask.h:707
ChildIter< MaskOffIterator, const LeafNode, ChildOff > ChildOffCIter
Definition: LeafNode.h:293
void setValue(const Coord &xyz, bool val)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Definition: LeafNodeMask.h:256
static Index getValueLevelAndCache(const Coord &, AccessorT &)
Return the LEVEL (=0) at which leaf node values reside.
Definition: LeafNodeMask.h:397
void addLeaf(LeafNode *)
This function exists only to enable template instantiation.
Definition: LeafNodeMask.h:509
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition: Math.h:337
void writeTopology(std::ostream &os, bool toHalf=false) const
Write out just the topology.
Definition: LeafNode.h:1276
DenseIter< LeafNode, ValueType, ChildAll > ChildAllIter
Definition: LeafNode.h:294
void resetBackground(bool, bool)
no-op since for this template specialization voxel values and states are indistinguishable.
Definition: LeafNodeMask.h:444
void getOrigin(Coord &origin) const
Return the grid index coordinates of this node's local origin.
Definition: LeafNodeMask.h:160
ValueIter< MaskOffIterator, LeafNode, const ValueType, ValueOff > ValueOffIter
Definition: LeafNode.h:286
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Set the active state of the voxel at the given coordinates without changing its value.
Definition: LeafNodeMask.h:380
void fill(const CoordBBox &bbox, const ValueType &, bool active=true)
Set all voxels within an axis-aligned box to the specified value and active state.
Definition: LeafNode.h:1161
Index32 transientData() const
Return the transient data value.
Definition: LeafNode.h:187