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