8#ifndef OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
9#define OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
16#include <openvdb/version.h>
20#include <tbb/parallel_for.h>
30template<
typename, Index,
typename>
struct SameInternalConfig;
33template<
typename _ChildNodeType, Index Log2Dim>
37 using ChildNodeType = _ChildNodeType;
38 using LeafNodeType =
typename ChildNodeType::LeafNodeType;
39 using ValueType =
typename ChildNodeType::ValueType;
40 using BuildType =
typename ChildNodeType::BuildType;
41 using UnionType = NodeUnion<ValueType, ChildNodeType>;
42 using NodeMaskType = util::NodeMask<Log2Dim>;
46 TOTAL = Log2Dim + ChildNodeType::TOTAL,
48 NUM_VALUES = 1 << (3 * Log2Dim),
49 LEVEL = 1 + ChildNodeType::LEVEL;
51 NUM_VOXELS = uint64_t(1) << (3 * TOTAL);
55 template<
typename OtherValueType>
56 struct ValueConverter {
57 using Type = InternalNode<
typename ChildNodeType::template ValueConverter<
58 OtherValueType>::Type, Log2Dim>;
64 template<
typename OtherNodeType>
65 struct SameConfiguration {
66 static const bool value =
67 SameInternalConfig<ChildNodeType, Log2Dim, OtherNodeType>::value;
77 explicit InternalNode(
const ValueType& offValue);
83 InternalNode(
const Coord& origin,
const ValueType& fillValue,
bool active =
false);
85 InternalNode(PartialCreate,
const Coord&,
const ValueType& fillValue,
bool active =
false);
90 InternalNode(
const InternalNode&);
95 template<
typename OtherChildNodeType>
96 explicit InternalNode(
const InternalNode<OtherChildNodeType, Log2Dim>& other);
101 template<
typename OtherChildNodeType>
102 InternalNode(
const InternalNode<OtherChildNodeType, Log2Dim>& other,
103 const ValueType& background, TopologyCopy);
108 template<
typename OtherChildNodeType>
109 InternalNode(
const InternalNode<OtherChildNodeType, Log2Dim>& other,
110 const ValueType& offValue,
const ValueType& onValue, TopologyCopy);
115 using MaskOnIterator =
typename NodeMaskType::OnIterator;
116 using MaskOffIterator =
typename NodeMaskType::OffIterator;
117 using MaskDenseIterator =
typename NodeMaskType::DenseIterator;
120 struct ValueOn {};
struct ValueOff {};
struct ValueAll {};
121 struct ChildOn {};
struct ChildOff {};
struct ChildAll {};
127 template<
typename NodeT,
typename ChildT,
typename MaskIterT,
typename TagT>
128 struct ChildIter:
public SparseIteratorBase<
129 MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>
132 ChildIter(
const MaskIterT& iter, NodeT* parent): SparseIteratorBase<
133 MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>(iter, parent) {}
135 ChildT& getItem(Index pos)
const
138 return *(this->parent().getChildNode(pos));
142 void setItem(Index pos,
const ChildT& c)
const { this->parent().resetChildNode(pos, &c); }
148 template<
typename NodeT,
typename ValueT,
typename MaskIterT,
typename TagT>
149 struct ValueIter:
public SparseIteratorBase<
150 MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>
153 ValueIter(
const MaskIterT& iter, NodeT* parent): SparseIteratorBase<
154 MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>(iter, parent) {}
156 const ValueT& getItem(Index pos)
const {
return this->parent().mNodes[pos].getValue(); }
159 void setItem(Index pos,
const ValueT& v)
const { this->parent().mNodes[pos].setValue(v); }
162 template<
typename ModifyOp>
163 void modifyItem(Index pos,
const ModifyOp& op)
const
165 op(this->parent().mNodes[pos].getValue());
170 template<
typename NodeT,
typename ChildT,
typename ValueT,
typename TagT>
171 struct DenseIter:
public DenseIteratorBase<
172 MaskDenseIterator, DenseIter<NodeT, ChildT, ValueT, TagT>, NodeT, ChildT, ValueT>
174 using BaseT = DenseIteratorBase<MaskDenseIterator, DenseIter, NodeT, ChildT, ValueT>;
175 using NonConstValueT =
typename BaseT::NonConstValueType;
178 DenseIter(
const MaskDenseIterator& iter, NodeT* parent):
179 DenseIteratorBase<MaskDenseIterator, DenseIter, NodeT, ChildT, ValueT>(iter, parent) {}
181 bool getItem(Index pos, ChildT*& child, NonConstValueT& value)
const
183 if (this->parent().isChildMaskOn(pos)) {
184 child = this->parent().getChildNode(pos);
188 value = this->parent().mNodes[pos].getValue();
193 void setItem(Index pos, ChildT* child)
const
195 this->parent().resetChildNode(pos, child);
199 void unsetItem(Index pos,
const ValueT& value)
const
201 this->parent().unsetChildNode(pos, value);
207 using ChildOnIter = ChildIter<InternalNode, ChildNodeType, MaskOnIterator, ChildOn>;
208 using ChildOnCIter = ChildIter<const InternalNode,const ChildNodeType,MaskOnIterator,ChildOn>;
209 using ChildOffIter = ValueIter<InternalNode, const ValueType, MaskOffIterator, ChildOff>;
210 using ChildOffCIter = ValueIter<const InternalNode,const ValueType,MaskOffIterator,ChildOff>;
211 using ChildAllIter = DenseIter<InternalNode, ChildNodeType, ValueType, ChildAll>;
212 using ChildAllCIter = DenseIter<const InternalNode,const ChildNodeType, ValueType, ChildAll>;
214 using ValueOnIter = ValueIter<InternalNode, const ValueType, MaskOnIterator, ValueOn>;
215 using ValueOnCIter = ValueIter<const InternalNode, const ValueType, MaskOnIterator, ValueOn>;
216 using ValueOffIter = ValueIter<InternalNode, const ValueType, MaskOffIterator, ValueOff>;
217 using ValueOffCIter = ValueIter<const InternalNode,const ValueType,MaskOffIterator,ValueOff>;
218 using ValueAllIter = ValueIter<InternalNode, const ValueType, MaskOffIterator, ValueAll>;
219 using ValueAllCIter = ValueIter<const InternalNode,const ValueType,MaskOffIterator,ValueAll>;
221 ChildOnCIter cbeginChildOn()
const {
return ChildOnCIter(mChildMask.beginOn(),
this); }
222 ChildOffCIter cbeginChildOff()
const {
return ChildOffCIter(mChildMask.beginOff(),
this); }
223 ChildAllCIter cbeginChildAll()
const {
return ChildAllCIter(mChildMask.beginDense(),
this); }
224 ChildOnCIter beginChildOn()
const {
return cbeginChildOn(); }
225 ChildOffCIter beginChildOff()
const {
return cbeginChildOff(); }
226 ChildAllCIter beginChildAll()
const {
return cbeginChildAll(); }
227 ChildOnIter beginChildOn() {
return ChildOnIter(mChildMask.beginOn(),
this); }
228 ChildOffIter beginChildOff() {
return ChildOffIter(mChildMask.beginOff(),
this); }
229 ChildAllIter beginChildAll() {
return ChildAllIter(mChildMask.beginDense(),
this); }
231 ValueOnCIter cbeginValueOn()
const {
return ValueOnCIter(mValueMask.beginOn(),
this); }
233 ValueOffCIter cbeginValueOff()
const {
return ValueOffCIter(mValueMask.beginOff(),
this); }
234 ValueAllCIter cbeginValueAll()
const {
return ValueAllCIter(mChildMask.beginOff(),
this); }
235 ValueOnCIter beginValueOn()
const {
return cbeginValueOn(); }
237 ValueOffCIter beginValueOff()
const {
return cbeginValueOff(); }
238 ValueAllCIter beginValueAll()
const {
return cbeginValueAll(); }
239 ValueOnIter beginValueOn() {
return ValueOnIter(mValueMask.beginOn(),
this); }
241 ValueOffIter beginValueOff() {
return ValueOffIter(mValueMask.beginOff(),
this); }
242 ValueAllIter beginValueAll() {
return ValueAllIter(mChildMask.beginOff(),
this); }
247 static Index dim() {
return DIM; }
253 static void getNodeLog2Dims(std::vector<Index>& dims);
257 static Index getChildDim() {
return ChildNodeType::DIM; }
260 static Index coordToOffset(
const Coord& xyz);
263 static void offsetToLocalCoord(Index n, Coord& xyz);
265 Coord offsetToGlobalCoord(Index n)
const;
268 const Coord& origin()
const {
return mOrigin; }
270 void setOrigin(
const Coord& origin) { mOrigin = origin; }
273 Index32 transientData()
const {
return mTransientData; }
275 void setTransientData(Index32 transientData) { mTransientData = transientData; }
279 void nodeCount(std::vector<Index64> &vec)
const;
281 void nodeCount(std::vector<Index32> &vec) const;
282 Index32 childCount() const;
283 Index64 onVoxelCount() const;
284 Index64 offVoxelCount() const;
285 Index64 onLeafVoxelCount() const;
286 Index64 offLeafVoxelCount() const;
287 Index64 onTileCount() const;
290 Index64 memUsage() const;
296 void evalActiveBoundingBox(CoordBBox& bbox,
bool visitVoxels = true) const;
300 CoordBBox getNodeBoundingBox()
const {
return CoordBBox::createCube(mOrigin, DIM); }
303 bool isEmpty()
const {
return mChildMask.isOff(); }
310 bool isConstant(ValueType& firstValue,
bool& state,
311 const ValueType& tolerance = zeroVal<ValueType>())
const;
327 bool isConstant(ValueType& minValue, ValueType& maxValue,
328 bool& state,
const ValueType& tolerance = zeroVal<ValueType>())
const;
331 bool isInactive()
const {
return this->isChildMaskOff() && this->isValueMaskOff(); }
334 bool isValueOn(
const Coord& xyz)
const;
336 bool isValueOn(Index offset)
const {
OPENVDB_ASSERT(offset < NUM_VALUES);
return mValueMask.isOn(offset); }
338 bool isValueOff(
const Coord& xyz)
const;
340 bool isValueOff(Index offset)
const {
OPENVDB_ASSERT(offset < NUM_VALUES);
return mValueMask.isOff(offset); }
343 bool hasActiveTiles()
const;
345 const ValueType& getValue(
const Coord& xyz)
const;
346 bool probeValue(
const Coord& xyz, ValueType& value)
const;
350 Index getValueLevel(
const Coord& xyz)
const;
354 const ValueType& getFirstValue()
const;
357 const ValueType& getLastValue()
const;
360 void setActiveState(
const Coord& xyz,
bool on);
362 void setValueOnly(
const Coord& xyz,
const ValueType& value);
364 void setValueOn(
const Coord& xyz);
366 void setValueOn(
const Coord& xyz,
const ValueType& value);
368 void setValueOff(
const Coord& xyz);
370 void setValueOff(
const Coord& xyz,
const ValueType& value);
374 template<
typename ModifyOp>
375 void modifyValue(
const Coord& xyz,
const ModifyOp& op);
377 template<
typename ModifyOp>
378 void modifyValueAndActiveState(
const Coord& xyz,
const ModifyOp& op);
384 template<
typename AccessorT>
385 const ValueType& getValueAndCache(
const Coord& xyz, AccessorT&)
const;
391 template<
typename AccessorT>
392 bool isValueOnAndCache(
const Coord& xyz, AccessorT&)
const;
398 template<
typename AccessorT>
399 void setValueAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
405 template<
typename AccessorT>
406 void setValueOnlyAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
413 template<
typename ModifyOp,
typename AccessorT>
414 void modifyValueAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
420 template<
typename ModifyOp,
typename AccessorT>
421 void modifyValueAndActiveStateAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
427 template<
typename AccessorT>
428 void setValueOffAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
434 template<
typename AccessorT>
435 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&);
442 template<
typename AccessorT>
443 bool probeValueAndCache(
const Coord& xyz, ValueType& value, AccessorT&)
const;
451 template<
typename AccessorT>
452 Index getValueLevelAndCache(
const Coord& xyz, AccessorT&)
const;
460 void writeTopology(std::ostream&,
bool toHalf =
false)
const;
461 void readTopology(std::istream&,
bool fromHalf =
false);
462 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
463 void readBuffers(std::istream&,
bool fromHalf =
false);
464 void readBuffers(std::istream&,
const CoordBBox&,
bool fromHalf =
false);
479 const ValueType& getValueUnsafe(Index offset)
const;
483 bool getValueUnsafe(Index offset, ValueType& value)
const;
488 ChildNodeType* getChildUnsafe(Index offset);
492 const ChildNodeType* getConstChildUnsafe(Index offset)
const;
496 const ChildNodeType* getChildUnsafe(Index offset)
const;
501 void setActiveStateUnsafe(Index offset,
bool on);
505 void setValueOnlyUnsafe(Index offset,
const ValueType& value);
509 void setValueOnUnsafe(Index offset);
513 void setValueOnUnsafe(Index offset,
const ValueType& value);
517 void setValueOffUnsafe(Index offset);
521 void setValueOffUnsafe(Index offset,
const ValueType& value);
526 void setValueMaskUnsafe(
const NodeMaskType& mask);
531 void setChildUnsafe(Index offset, ChildNodeType* child);
535 void resetChildUnsafe(Index offset, ChildNodeType* child);
539 ChildNodeType* stealChildUnsafe(Index offset,
const ValueType& value,
bool active);
543 void deleteChildUnsafe(Index offset,
const ValueType& value,
bool active);
560 void fill(
const CoordBBox& bbox,
const ValueType& value,
bool active =
true);
569 void denseFill(
const CoordBBox& bbox,
const ValueType& value,
bool active =
true);
574 void voxelizeActiveTiles(
bool threaded =
true);
583 template<
typename DenseT>
584 void copyToDense(
const CoordBBox& bbox, DenseT& dense)
const;
588 template<MergePolicy Policy>
589 void merge(InternalNode& other,
const ValueType& background,
const ValueType& otherBackground);
593 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive);
607 template<
typename OtherChildNodeType>
608 void topologyUnion(
const InternalNode<OtherChildNodeType, Log2Dim>& other,
const bool preserveTiles =
false);
623 template<
typename OtherChildNodeType>
624 void topologyIntersection(
const InternalNode<OtherChildNodeType, Log2Dim>& other,
625 const ValueType& background);
638 template<
typename OtherChildNodeType>
639 void topologyDifference(
const InternalNode<OtherChildNodeType, Log2Dim>& other,
640 const ValueType& background);
642 template<
typename CombineOp>
643 void combine(InternalNode& other, CombineOp&);
644 template<
typename CombineOp>
645 void combine(
const ValueType& value,
bool valueIsActive, CombineOp&);
647 template<
typename CombineOp,
typename OtherNodeType >
648 void combine2(
const InternalNode& other0,
const OtherNodeType& other1, CombineOp&);
649 template<
typename CombineOp,
typename OtherNodeType >
650 void combine2(
const ValueType& value,
const OtherNodeType& other,
bool valIsActive, CombineOp&);
651 template<
typename CombineOp,
typename OtherValueType>
652 void combine2(
const InternalNode& other,
const OtherValueType&,
bool valIsActive, CombineOp&);
655 void clip(
const CoordBBox&,
const ValueType& background);
660 void prune(
const ValueType& tolerance = zeroVal<ValueType>());
664 void addLeaf(LeafNodeType* leaf);
668 template<
typename AccessorT>
669 void addLeafAndCache(LeafNodeType* leaf, AccessorT&);
679 template<
typename NodeT>
680 NodeT* stealNode(
const Coord& xyz,
const ValueType& value,
bool state);
688 bool addChild(ChildNodeType* child);
692 void addTile(Index level,
const Coord& xyz,
const ValueType& value,
bool state);
695 void addTile(Index offset,
const ValueType& value,
bool state);
699 template<
typename AccessorT>
700 void addTileAndCache(Index level,
const Coord& xyz,
const ValueType&,
bool state, AccessorT&);
705 template<
typename NodeType> NodeType* probeNode(
const Coord& xyz);
706 template<
typename NodeType>
const NodeType* probeConstNode(
const Coord& xyz)
const;
707 template<
typename NodeType>
const NodeType* probeNode(
const Coord& xyz)
const {
return this->probeConstNode<NodeType>(xyz); }
713 ChildNodeType* probeChild(
const Coord& xyz);
714 const ChildNodeType* probeConstChild(
const Coord& xyz)
const;
715 const ChildNodeType* probeChild(
const Coord& xyz)
const {
return this->probeConstChild(xyz); }
721 ChildNodeType* probeChild(
const Coord& xyz, ValueType& value,
bool& active);
722 const ChildNodeType* probeConstChild(
const Coord& xyz, ValueType& value,
bool& active)
const;
723 const ChildNodeType* probeChild(
const Coord& xyz, ValueType& value,
bool& active)
const {
return this->probeConstChild(xyz, value, active); }
731 ChildNodeType* probeChildUnsafe(Index offset);
732 const ChildNodeType* probeConstChildUnsafe(Index offset)
const;
733 const ChildNodeType* probeChildUnsafe(Index offset)
const {
return this->probeConstChildUnsafe(offset); }
741 ChildNodeType* probeChildUnsafe(Index offset, ValueType& value,
bool& active);
742 const ChildNodeType* probeConstChildUnsafe(Index offset, ValueType& value,
bool& active)
const;
743 const ChildNodeType* probeChildUnsafe(Index offset, ValueType& value,
bool& active)
const {
return this->probeConstChildUnsafe(offset, value, active); }
749 template<
typename NodeType,
typename AccessorT>
750 NodeType* probeNodeAndCache(
const Coord& xyz, AccessorT&);
751 template<
typename NodeType,
typename AccessorT>
752 const NodeType* probeConstNodeAndCache(
const Coord& xyz, AccessorT&)
const;
758 LeafNodeType* probeLeaf(
const Coord& xyz);
759 const LeafNodeType* probeConstLeaf(
const Coord& xyz)
const;
760 const LeafNodeType* probeLeaf(
const Coord& xyz)
const;
766 template<
typename AccessorT>
767 LeafNodeType* probeLeafAndCache(
const Coord& xyz, AccessorT& acc);
768 template<
typename AccessorT>
769 const LeafNodeType* probeConstLeafAndCache(
const Coord& xyz, AccessorT& acc)
const;
770 template<
typename AccessorT>
771 const LeafNodeType* probeLeafAndCache(
const Coord& xyz, AccessorT& acc)
const;
780 LeafNodeType* touchLeaf(
const Coord& xyz);
784 template<
typename AccessorT>
785 LeafNodeType* touchLeafAndCache(
const Coord& xyz, AccessorT&);
810 template<
typename ArrayT>
811 void getNodes(ArrayT& array);
812 template<
typename ArrayT>
813 void getNodes(ArrayT& array)
const;
839 template<
typename ArrayT>
840 void stealNodes(ArrayT& array,
const ValueType& value,
bool state);
844 void resetBackground(
const ValueType& oldBackground,
const ValueType& newBackground);
848 template<
typename OtherChildNodeType, Index OtherLog2Dim>
849 bool hasSameTopology(
const InternalNode<OtherChildNodeType, OtherLog2Dim>* other)
const;
855 friend class IteratorBase<MaskOnIterator, InternalNode>;
856 friend class IteratorBase<MaskOffIterator, InternalNode>;
857 friend class IteratorBase<MaskDenseIterator, InternalNode>;
862 template<
typename, Index>
friend class InternalNode;
866 bool isValueMaskOn(Index n)
const {
return mValueMask.isOn(n); }
867 bool isValueMaskOn()
const {
return mValueMask.isOn(); }
868 bool isValueMaskOff(Index n)
const {
return mValueMask.isOff(n); }
869 bool isValueMaskOff()
const {
return mValueMask.isOff(); }
870 bool isChildMaskOn(Index n)
const {
return mChildMask.isOn(n); }
871 bool isChildMaskOff(Index n)
const {
return mChildMask.isOff(n); }
872 bool isChildMaskOff()
const {
return mChildMask.isOff(); }
873 const NodeMaskType& getValueMask()
const {
return mValueMask; }
874 const NodeMaskType& getChildMask()
const {
return mChildMask; }
875 NodeMaskType getValueOffMask()
const
877 NodeMaskType mask = mValueMask;
882 const UnionType* getTable()
const {
return mNodes; }
887 void setValueMask(Index n,
bool on) { mValueMask.set(n, mChildMask.isOn(n) ?
false : on); }
890 void makeChildNodeEmpty(Index n,
const ValueType& value);
891 void setChildNode( Index i, ChildNodeType* child);
892 void resetChildNode(Index i, ChildNodeType* child);
893 ChildNodeType* unsetChildNode(Index i,
const ValueType& value);
899 ChildNodeType* getChildNode(Index n);
900 const ChildNodeType* getChildNode(Index n)
const;
905 struct VoxelizeActiveTiles;
906 template<
typename OtherInternalNode>
struct DeepCopy;
907 template<
typename OtherInternalNode>
struct TopologyCopy1;
908 template<
typename OtherInternalNode>
struct TopologyCopy2;
909 template<
typename OtherInternalNode>
struct TopologyUnion;
910 template<
typename OtherInternalNode>
struct TopologyDifference;
911 template<
typename OtherInternalNode>
struct TopologyIntersection;
914 UnionType mNodes[NUM_VALUES];
915 NodeMaskType mChildMask, mValueMask;
929template<
typename ChildT1, Index Dim1,
typename NodeT2>
930struct SameInternalConfig {
931 static const bool value =
false;
934template<
typename ChildT1, Index Dim1,
typename ChildT2>
935struct SameInternalConfig<ChildT1, Dim1, InternalNode<ChildT2, Dim1> > {
936 static const bool value = ChildT1::template SameConfiguration<ChildT2>::value;
944template<
typename ChildT, Index Log2Dim>
946InternalNode<ChildT, Log2Dim>::InternalNode(
const ValueType& background)
948 for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(background);
952template<
typename ChildT, Index Log2Dim>
954InternalNode<ChildT, Log2Dim>::InternalNode(
const Coord& origin,
const ValueType& val,
bool active):
955 mOrigin(origin[0] & ~(DIM - 1),
956 origin[1] & ~(DIM - 1),
957 origin[2] & ~(DIM - 1))
959 if (active) mValueMask.setOn();
960 for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(val);
966template<
typename ChildT, Index Log2Dim>
968InternalNode<ChildT, Log2Dim>::InternalNode(PartialCreate,
969 const Coord& origin,
const ValueType& val,
bool active)
970 : mOrigin(origin[0] & ~(DIM-1), origin[1] & ~(DIM-1), origin[2] & ~(DIM-1))
972 if (active) mValueMask.setOn();
973 for (Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(val);
976template<
typename ChildT, Index Log2Dim>
977template<
typename OtherInternalNode>
978struct InternalNode<ChildT, Log2Dim>::DeepCopy
980 DeepCopy(
const OtherInternalNode* source, InternalNode* target) : s(source), t(target) {
981 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
984 void operator()(
const tbb::blocked_range<Index> &r)
const {
985 for (Index i = r.begin(), end=r.end(); i!=end; ++i) {
986 if (s->mChildMask.isOff(i)) {
987 t->mNodes[i].setValue(ValueType(s->mNodes[i].getValue()));
989 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild())));
993 const OtherInternalNode* s;
997template<
typename ChildT, Index Log2Dim>
999InternalNode<ChildT, Log2Dim>::InternalNode(
const InternalNode& other)
1000 : mChildMask(other.mChildMask)
1001 , mValueMask(other.mValueMask)
1002 , mOrigin(other.mOrigin)
1003 , mTransientData(other.mTransientData)
1005 DeepCopy<InternalNode<ChildT, Log2Dim> > tmp(&other,
this);
1010template<
typename ChildT, Index Log2Dim>
1011template<
typename OtherChildNodeType>
1013InternalNode<ChildT, Log2Dim>::InternalNode(
const InternalNode<OtherChildNodeType, Log2Dim>& other)
1014 : mChildMask(other.mChildMask)
1015 , mValueMask(other.mValueMask)
1016 , mOrigin(other.mOrigin)
1017 , mTransientData(other.mTransientData)
1019 DeepCopy<InternalNode<OtherChildNodeType, Log2Dim> > tmp(&other,
this);
1022template<
typename ChildT, Index Log2Dim>
1023template<
typename OtherInternalNode>
1024struct InternalNode<ChildT, Log2Dim>::TopologyCopy1
1026 TopologyCopy1(
const OtherInternalNode* source, InternalNode* target,
1027 const ValueType& background) : s(source), t(target), b(background) {
1028 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
1031 void operator()(
const tbb::blocked_range<Index> &r)
const {
1032 for (Index i = r.begin(), end=r.end(); i!=end; ++i) {
1033 if (s->isChildMaskOn(i)) {
1034 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild()),
1035 b, TopologyCopy()));
1037 t->mNodes[i].setValue(b);
1041 const OtherInternalNode* s;
1046template<
typename ChildT, Index Log2Dim>
1047template<
typename OtherChildNodeType>
1049InternalNode<ChildT, Log2Dim>::InternalNode(
const InternalNode<OtherChildNodeType, Log2Dim>& other,
1050 const ValueType& background, TopologyCopy)
1051 : mChildMask(other.mChildMask)
1052 , mValueMask(other.mValueMask)
1053 , mOrigin(other.mOrigin)
1054 , mTransientData(other.mTransientData)
1056 TopologyCopy1<InternalNode<OtherChildNodeType, Log2Dim> > tmp(&other,
this, background);
1059template<
typename ChildT, Index Log2Dim>
1060template<
typename OtherInternalNode>
1061struct InternalNode<ChildT, Log2Dim>::TopologyCopy2
1063 TopologyCopy2(
const OtherInternalNode* source, InternalNode* target,
1064 const ValueType& offValue,
const ValueType& onValue)
1065 : s(source), t(target), offV(offValue), onV(onValue) {
1066 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
1068 void operator()(
const tbb::blocked_range<Index> &r)
const {
1069 for (Index i = r.begin(), end=r.end(); i!=end; ++i) {
1070 if (s->isChildMaskOn(i)) {
1071 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild()),
1072 offV, onV, TopologyCopy()));
1074 t->mNodes[i].setValue(s->isValueMaskOn(i) ? onV : offV);
1078 const OtherInternalNode* s;
1080 const ValueType &offV, &onV;
1083template<
typename ChildT, Index Log2Dim>
1084template<
typename OtherChildNodeType>
1086InternalNode<ChildT, Log2Dim>::InternalNode(
const InternalNode<OtherChildNodeType, Log2Dim>& other,
1087 const ValueType& offValue,
1088 const ValueType& onValue, TopologyCopy)
1089 : mChildMask(other.mChildMask)
1090 , mValueMask(other.mValueMask)
1091 , mOrigin(other.mOrigin)
1092 , mTransientData(other.mTransientData)
1094 TopologyCopy2<InternalNode<OtherChildNodeType, Log2Dim> > tmp(&other,
this, offValue, onValue);
1098template<
typename ChildT, Index Log2Dim>
1100InternalNode<ChildT, Log2Dim>::~InternalNode()
1102 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1103 delete mNodes[iter.pos()].getChild();
1111template<
typename ChildT, Index Log2Dim>
1113InternalNode<ChildT, Log2Dim>::leafCount()
const
1115 if (ChildNodeType::getLevel() == 0)
return mChildMask.countOn();
1117 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1118 sum += iter->leafCount();
1123template<
typename ChildT, Index Log2Dim>
1125InternalNode<ChildT, Log2Dim>::nodeCount(std::vector<Index64> &vec)
const
1128 const auto count = mChildMask.countOn();
1129 if (ChildNodeType::LEVEL > 0 && count > 0) {
1130 for (
auto iter = this->cbeginChildOn(); iter; ++iter) iter->nodeCount(vec);
1132 vec[ChildNodeType::LEVEL] += count;
1135template<
typename ChildT, Index Log2Dim>
1137InternalNode<ChildT, Log2Dim>::nodeCount(std::vector<Index32> &vec)
const
1140 const auto count = mChildMask.countOn();
1141 if (ChildNodeType::LEVEL > 0 && count > 0) {
1142 for (
auto iter = this->cbeginChildOn(); iter; ++iter) {
1144 iter->nodeCount(vec);
1148 vec[ChildNodeType::LEVEL] += count;
1152template<
typename ChildT, Index Log2Dim>
1154InternalNode<ChildT, Log2Dim>::nonLeafCount()
const
1157 if (ChildNodeType::getLevel() == 0)
return sum;
1158 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1159 sum += iter->nonLeafCount();
1165template<
typename ChildT, Index Log2Dim>
1167InternalNode<ChildT, Log2Dim>::childCount()
const
1169 return this->getChildMask().countOn();
1173template<
typename ChildT, Index Log2Dim>
1175InternalNode<ChildT, Log2Dim>::onVoxelCount()
const
1177 Index64 sum = ChildT::NUM_VOXELS * mValueMask.countOn();
1178 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1179 sum += iter->onVoxelCount();
1185template<
typename ChildT, Index Log2Dim>
1187InternalNode<ChildT, Log2Dim>::offVoxelCount()
const
1189 Index64 sum = ChildT::NUM_VOXELS * (NUM_VALUES-mValueMask.countOn()-mChildMask.countOn());
1190 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1191 sum += iter->offVoxelCount();
1197template<
typename ChildT, Index Log2Dim>
1199InternalNode<ChildT, Log2Dim>::onLeafVoxelCount()
const
1202 for (ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1203 sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount();
1209template<
typename ChildT, Index Log2Dim>
1211InternalNode<ChildT, Log2Dim>::offLeafVoxelCount()
const
1214 for (ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1215 sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount();
1220template<
typename ChildT, Index Log2Dim>
1222InternalNode<ChildT, Log2Dim>::onTileCount()
const
1224 Index64 sum = mValueMask.countOn();
1225 for (ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) {
1226 sum += iter->onTileCount();
1231template<
typename ChildT, Index Log2Dim>
1233InternalNode<ChildT, Log2Dim>::memUsage()
const
1235 Index64 sum = NUM_VALUES *
sizeof(UnionType) + mChildMask.memUsage()
1236 + mValueMask.memUsage() +
sizeof(mOrigin);
1237 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1238 sum += iter->memUsage();
1244template<
typename ChildT, Index Log2Dim>
1246InternalNode<ChildT, Log2Dim>::evalActiveBoundingBox(CoordBBox& bbox,
bool visitVoxels)
const
1248 if (bbox.isInside(this->getNodeBoundingBox()))
return;
1250 for (ValueOnCIter i = this->cbeginValueOn(); i; ++i) {
1251 bbox.expand(i.getCoord(), ChildT::DIM);
1253 for (ChildOnCIter i = this->cbeginChildOn(); i; ++i) {
1254 i->evalActiveBoundingBox(bbox, visitVoxels);
1262template<
typename ChildT, Index Log2Dim>
1264InternalNode<ChildT, Log2Dim>::prune(
const ValueType& tolerance)
1267 ValueType value = zeroVal<ValueType>();
1268 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1269 const Index i = iter.pos();
1270 ChildT* child = mNodes[i].getChild();
1271 child->prune(tolerance);
1272 if (child->isConstant(value, state, tolerance)) {
1274 mChildMask.setOff(i);
1275 mValueMask.set(i, state);
1276 mNodes[i].setValue(value);
1285template<
typename ChildT, Index Log2Dim>
1286template<
typename NodeT>
1288InternalNode<ChildT, Log2Dim>::stealNode(
const Coord& xyz,
const ValueType& value,
bool state)
1290 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1291 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1293 const Index n = this->coordToOffset(xyz);
1294 if (mChildMask.isOff(n))
return nullptr;
1295 ChildT* child = mNodes[n].getChild();
1296 if (std::is_same<NodeT, ChildT>::value) {
1297 mChildMask.setOff(n);
1298 mValueMask.set(n, state);
1299 mNodes[n].setValue(value);
1301 return (std::is_same<NodeT, ChildT>::value)
1302 ?
reinterpret_cast<NodeT*
>(child)
1303 : child->template stealNode<NodeT>(xyz, value, state);
1311template<
typename ChildT, Index Log2Dim>
1312template<
typename NodeT>
1314InternalNode<ChildT, Log2Dim>::probeNode(
const Coord& xyz)
1316 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1317 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1319 const Index n = this->coordToOffset(xyz);
1320 if (mChildMask.isOff(n))
return nullptr;
1321 ChildT* child = mNodes[n].getChild();
1322 return (std::is_same<NodeT, ChildT>::value)
1323 ?
reinterpret_cast<NodeT*
>(child)
1324 : child->template probeNode<NodeT>(xyz);
1329template<
typename ChildT, Index Log2Dim>
1330template<
typename NodeT,
typename AccessorT>
1332InternalNode<ChildT, Log2Dim>::probeNodeAndCache(
const Coord& xyz, AccessorT& acc)
1334 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1335 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1337 const Index n = this->coordToOffset(xyz);
1338 if (mChildMask.isOff(n))
return nullptr;
1339 ChildT* child = mNodes[n].getChild();
1340 acc.insert(xyz, child);
1341 return (std::is_same<NodeT, ChildT>::value)
1342 ?
reinterpret_cast<NodeT*
>(child)
1343 : child->template probeNodeAndCache<NodeT>(xyz, acc);
1348template<
typename ChildT, Index Log2Dim>
1349template<
typename NodeT>
1351InternalNode<ChildT, Log2Dim>::probeConstNode(
const Coord& xyz)
const
1353 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1354 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1356 const Index n = this->coordToOffset(xyz);
1357 if (mChildMask.isOff(n))
return nullptr;
1358 const ChildT* child = mNodes[n].getChild();
1359 return (std::is_same<NodeT, ChildT>::value)
1360 ?
reinterpret_cast<const NodeT*
>(child)
1361 : child->template probeConstNode<NodeT>(xyz);
1366template<
typename ChildT, Index Log2Dim>
1367template<
typename NodeT,
typename AccessorT>
1369InternalNode<ChildT, Log2Dim>::probeConstNodeAndCache(
const Coord& xyz, AccessorT& acc)
const
1371 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1372 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1374 const Index n = this->coordToOffset(xyz);
1375 if (mChildMask.isOff(n))
return nullptr;
1376 const ChildT* child = mNodes[n].getChild();
1377 acc.insert(xyz, child);
1378 return (std::is_same<NodeT, ChildT>::value)
1379 ?
reinterpret_cast<const NodeT*
>(child)
1380 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
1388template<
typename ChildT, Index Log2Dim>
1390InternalNode<ChildT, Log2Dim>::probeChild(
const Coord& xyz)
1392 const Index n = this->coordToOffset(xyz);
1393 return this->probeChildUnsafe(n);
1396template<
typename ChildT, Index Log2Dim>
1398InternalNode<ChildT, Log2Dim>::probeConstChild(
const Coord& xyz)
const
1400 const Index n = this->coordToOffset(xyz);
1401 return this->probeConstChildUnsafe(n);
1404template<
typename ChildT, Index Log2Dim>
1406InternalNode<ChildT, Log2Dim>::probeChild(
const Coord& xyz, ValueType& value,
bool& active)
1408 const Index n = this->coordToOffset(xyz);
1409 return this->probeChildUnsafe(n, value, active);
1412template<
typename ChildT, Index Log2Dim>
1414InternalNode<ChildT, Log2Dim>::probeConstChild(
const Coord& xyz, ValueType& value,
bool& active)
const
1416 const Index n = this->coordToOffset(xyz);
1417 return this->probeConstChildUnsafe(n, value, active);
1420template<
typename ChildT, Index Log2Dim>
1422InternalNode<ChildT, Log2Dim>::probeChildUnsafe(Index offset)
1425 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1429template<
typename ChildT, Index Log2Dim>
1431InternalNode<ChildT, Log2Dim>::probeConstChildUnsafe(Index offset)
const
1434 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1438template<
typename ChildT, Index Log2Dim>
1440InternalNode<ChildT, Log2Dim>::probeChildUnsafe(Index offset, ValueType& value,
bool& active)
1443 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1444 value = mNodes[offset].getValue();
1445 active = mValueMask.isOn(offset);
1449template<
typename ChildT, Index Log2Dim>
1451InternalNode<ChildT, Log2Dim>::probeConstChildUnsafe(Index offset, ValueType& value,
bool& active)
const
1454 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1455 value = mNodes[offset].getValue();
1456 active = mValueMask.isOn(offset);
1464template<
typename ChildT, Index Log2Dim>
1465inline typename ChildT::LeafNodeType*
1466InternalNode<ChildT, Log2Dim>::probeLeaf(
const Coord& xyz)
1468 return this->
template probeNode<LeafNodeType>(xyz);
1472template<
typename ChildT, Index Log2Dim>
1473template<
typename AccessorT>
1474inline typename ChildT::LeafNodeType*
1475InternalNode<ChildT, Log2Dim>::probeLeafAndCache(
const Coord& xyz, AccessorT& acc)
1477 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
1481template<
typename ChildT, Index Log2Dim>
1482template<
typename AccessorT>
1483inline const typename ChildT::LeafNodeType*
1484InternalNode<ChildT, Log2Dim>::probeLeafAndCache(
const Coord& xyz, AccessorT& acc)
const
1486 return this->probeConstLeafAndCache(xyz, acc);
1490template<
typename ChildT, Index Log2Dim>
1491inline const typename ChildT::LeafNodeType*
1492InternalNode<ChildT, Log2Dim>::probeConstLeaf(
const Coord& xyz)
const
1494 return this->
template probeConstNode<LeafNodeType>(xyz);
1498template<
typename ChildT, Index Log2Dim>
1499template<
typename AccessorT>
1500inline const typename ChildT::LeafNodeType*
1501InternalNode<ChildT, Log2Dim>::probeConstLeafAndCache(
const Coord& xyz, AccessorT& acc)
const
1503 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
1510template<
typename ChildT, Index Log2Dim>
1512InternalNode<ChildT, Log2Dim>::addLeaf(LeafNodeType* leaf)
1515 const Coord& xyz = leaf->origin();
1516 const Index n = this->coordToOffset(xyz);
1517 ChildT* child =
nullptr;
1518 if (mChildMask.isOff(n)) {
1519 if (ChildT::LEVEL>0) {
1520 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1522 child =
reinterpret_cast<ChildT*
>(leaf);
1524 this->setChildNode(n, child);
1526 if (ChildT::LEVEL>0) {
1527 child = mNodes[n].getChild();
1529 delete mNodes[n].getChild();
1530 child =
reinterpret_cast<ChildT*
>(leaf);
1531 mNodes[n].setChild(child);
1534 child->addLeaf(leaf);
1538template<
typename ChildT, Index Log2Dim>
1539template<
typename AccessorT>
1541InternalNode<ChildT, Log2Dim>::addLeafAndCache(LeafNodeType* leaf, AccessorT& acc)
1544 const Coord& xyz = leaf->origin();
1545 const Index n = this->coordToOffset(xyz);
1546 ChildT* child =
nullptr;
1547 if (mChildMask.isOff(n)) {
1548 if (ChildT::LEVEL>0) {
1549 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1550 acc.insert(xyz, child);
1552 child =
reinterpret_cast<ChildT*
>(leaf);
1554 this->setChildNode(n, child);
1556 if (ChildT::LEVEL>0) {
1557 child = mNodes[n].getChild();
1558 acc.insert(xyz, child);
1560 delete mNodes[n].getChild();
1561 child =
reinterpret_cast<ChildT*
>(leaf);
1562 mNodes[n].setChild(child);
1565 child->addLeafAndCache(leaf, acc);
1572template<
typename ChildT, Index Log2Dim>
1574InternalNode<ChildT, Log2Dim>::addChild(ChildT* child)
1577 const Coord& xyz = child->origin();
1579 if (Coord((xyz & ~(DIM-1))) != this->origin())
return false;
1581 const Index n = this->coordToOffset(xyz);
1583 this->resetChildNode(n, child);
1588template<
typename ChildT, Index Log2Dim>
1590InternalNode<ChildT, Log2Dim>::addTile(Index n,
const ValueType& value,
bool state)
1593 this->makeChildNodeEmpty(n, value);
1594 mValueMask.set(n, state);
1598template<
typename ChildT, Index Log2Dim>
1600InternalNode<ChildT, Log2Dim>::addTile(Index level,
const Coord& xyz,
1601 const ValueType& value,
bool state)
1603 if (LEVEL >= level) {
1604 const Index n = this->coordToOffset(xyz);
1605 if (mChildMask.isOff(n)) {
1606 if (LEVEL > level) {
1607 ChildT* child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1608 this->setChildNode(n, child);
1609 child->addTile(level, xyz, value, state);
1611 mValueMask.set(n, state);
1612 mNodes[n].setValue(value);
1615 ChildT* child = mNodes[n].getChild();
1616 if (LEVEL > level) {
1617 child->addTile(level, xyz, value, state);
1620 mChildMask.setOff(n);
1621 mValueMask.set(n, state);
1622 mNodes[n].setValue(value);
1629template<
typename ChildT, Index Log2Dim>
1630template<
typename AccessorT>
1632InternalNode<ChildT, Log2Dim>::addTileAndCache(Index level,
const Coord& xyz,
1633 const ValueType& value,
bool state, AccessorT& acc)
1635 if (LEVEL >= level) {
1636 const Index n = this->coordToOffset(xyz);
1637 if (mChildMask.isOff(n)) {
1638 if (LEVEL > level) {
1639 ChildT* child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1640 this->setChildNode(n, child);
1641 acc.insert(xyz, child);
1642 child->addTileAndCache(level, xyz, value, state, acc);
1644 mValueMask.set(n, state);
1645 mNodes[n].setValue(value);
1648 ChildT* child = mNodes[n].getChild();
1649 if (LEVEL > level) {
1650 acc.insert(xyz, child);
1651 child->addTileAndCache(level, xyz, value, state, acc);
1654 mChildMask.setOff(n);
1655 mValueMask.set(n, state);
1656 mNodes[n].setValue(value);
1666template<
typename ChildT, Index Log2Dim>
1667inline typename ChildT::LeafNodeType*
1668InternalNode<ChildT, Log2Dim>::touchLeaf(
const Coord& xyz)
1670 const Index n = this->coordToOffset(xyz);
1671 ChildT* child =
nullptr;
1672 if (mChildMask.isOff(n)) {
1673 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1674 this->setChildNode(n, child);
1676 child = mNodes[n].getChild();
1678 return child->touchLeaf(xyz);
1682template<
typename ChildT, Index Log2Dim>
1683template<
typename AccessorT>
1684inline typename ChildT::LeafNodeType*
1685InternalNode<ChildT, Log2Dim>::touchLeafAndCache(
const Coord& xyz, AccessorT& acc)
1687 const Index n = this->coordToOffset(xyz);
1688 if (mChildMask.isOff(n)) {
1689 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), mValueMask.isOn(n)));
1691 acc.insert(xyz, mNodes[n].getChild());
1692 return mNodes[n].getChild()->touchLeafAndCache(xyz, acc);
1699template<
typename ChildT, Index Log2Dim>
1701InternalNode<ChildT, Log2Dim>::isConstant(ValueType& firstValue,
bool& state,
1702 const ValueType& tolerance)
const
1704 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1706 firstValue = mNodes[0].getValue();
1707 for (Index i = 1; i < NUM_VALUES; ++i) {
1708 if (!math::isApproxEqual(mNodes[i].getValue(), firstValue, tolerance)) {
1719template<
typename ChildT, Index Log2Dim>
1721InternalNode<ChildT, Log2Dim>::isConstant(ValueType& minValue,
1722 ValueType& maxValue,
1724 const ValueType& tolerance)
const
1727 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1728 minValue = maxValue = mNodes[0].getValue();
1729 for (Index i = 1; i < NUM_VALUES; ++i) {
1730 const ValueType& v = mNodes[i].getValue();
1732 if ((maxValue - v) > tolerance)
return false;
1734 }
else if (v > maxValue) {
1735 if ((v - minValue) > tolerance)
return false;
1746template<
typename ChildT, Index Log2Dim>
1748InternalNode<ChildT, Log2Dim>::hasActiveTiles()
const
1753 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1754 if (iter->hasActiveTiles())
return true;
1761template<
typename ChildT, Index Log2Dim>
1763InternalNode<ChildT, Log2Dim>::isValueOn(
const Coord& xyz)
const
1765 const Index n = this->coordToOffset(xyz);
1766 return this->isChildMaskOff(n) ? this->isValueMaskOn(n)
1767 : mNodes[n].getChild()->isValueOn(xyz);
1770template<
typename ChildT, Index Log2Dim>
1772InternalNode<ChildT, Log2Dim>::isValueOff(
const Coord& xyz)
const
1774 const Index n = this->coordToOffset(xyz);
1775 return this->isChildMaskOff(n) ? this->isValueMaskOn(n)
1776 : mNodes[n].getChild()->isValueOff(xyz);
1779template<
typename ChildT, Index Log2Dim>
1780template<
typename AccessorT>
1782InternalNode<ChildT, Log2Dim>::isValueOnAndCache(
const Coord& xyz, AccessorT& acc)
const
1784 const Index n = this->coordToOffset(xyz);
1785 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1786 acc.insert(xyz, mNodes[n].getChild());
1787 return mNodes[n].getChild()->isValueOnAndCache(xyz, acc);
1791template<
typename ChildT, Index Log2Dim>
1792inline const typename ChildT::ValueType&
1793InternalNode<ChildT, Log2Dim>::getValue(
const Coord& xyz)
const
1795 const Index n = this->coordToOffset(xyz);
1796 return this->isChildMaskOff(n) ? mNodes[n].getValue()
1797 : mNodes[n].getChild()->getValue(xyz);
1800template<
typename ChildT, Index Log2Dim>
1801template<
typename AccessorT>
1802inline const typename ChildT::ValueType&
1803InternalNode<ChildT, Log2Dim>::getValueAndCache(
const Coord& xyz, AccessorT& acc)
const
1805 const Index n = this->coordToOffset(xyz);
1806 if (this->isChildMaskOn(n)) {
1807 acc.insert(xyz, mNodes[n].getChild());
1808 return mNodes[n].getChild()->getValueAndCache(xyz, acc);
1810 return mNodes[n].getValue();
1814template<
typename ChildT, Index Log2Dim>
1816InternalNode<ChildT, Log2Dim>::getValueLevel(
const Coord& xyz)
const
1818 const Index n = this->coordToOffset(xyz);
1819 return this->isChildMaskOff(n) ? LEVEL : mNodes[n].getChild()->getValueLevel(xyz);
1822template<
typename ChildT, Index Log2Dim>
1823template<
typename AccessorT>
1825InternalNode<ChildT, Log2Dim>::getValueLevelAndCache(
const Coord& xyz, AccessorT& acc)
const
1827 const Index n = this->coordToOffset(xyz);
1828 if (this->isChildMaskOn(n)) {
1829 acc.insert(xyz, mNodes[n].getChild());
1830 return mNodes[n].getChild()->getValueLevelAndCache(xyz, acc);
1836template<
typename ChildT, Index Log2Dim>
1838InternalNode<ChildT, Log2Dim>::probeValue(
const Coord& xyz, ValueType& value)
const
1840 const Index n = this->coordToOffset(xyz);
1841 if (this->isChildMaskOff(n)) {
1842 value = mNodes[n].getValue();
1843 return this->isValueMaskOn(n);
1845 return mNodes[n].getChild()->probeValue(xyz, value);
1848template<
typename ChildT, Index Log2Dim>
1849template<
typename AccessorT>
1851InternalNode<ChildT, Log2Dim>::probeValueAndCache(
const Coord& xyz,
1852 ValueType& value, AccessorT& acc)
const
1854 const Index n = this->coordToOffset(xyz);
1855 if (this->isChildMaskOn(n)) {
1856 acc.insert(xyz, mNodes[n].getChild());
1857 return mNodes[n].getChild()->probeValueAndCache(xyz, value, acc);
1859 value = mNodes[n].getValue();
1860 return this->isValueMaskOn(n);
1864template<
typename ChildT, Index Log2Dim>
1866InternalNode<ChildT, Log2Dim>::setValueOff(
const Coord& xyz)
1868 const Index n = this->coordToOffset(xyz);
1869 bool hasChild = this->isChildMaskOn(n);
1870 if (!hasChild && this->isValueMaskOn(n)) {
1874 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
true));
1876 if (hasChild) mNodes[n].getChild()->setValueOff(xyz);
1880template<
typename ChildT, Index Log2Dim>
1882InternalNode<ChildT, Log2Dim>::setValueOn(
const Coord& xyz)
1884 const Index n = this->coordToOffset(xyz);
1885 bool hasChild = this->isChildMaskOn(n);
1886 if (!hasChild && !this->isValueMaskOn(n)) {
1890 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
false));
1892 if (hasChild) mNodes[n].getChild()->setValueOn(xyz);
1896template<
typename ChildT, Index Log2Dim>
1898InternalNode<ChildT, Log2Dim>::setValueOff(
const Coord& xyz,
const ValueType& value)
1900 const Index n = InternalNode::coordToOffset(xyz);
1901 bool hasChild = this->isChildMaskOn(n);
1903 const bool active = this->isValueMaskOn(n);
1904 if (active || !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1909 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1912 if (hasChild) mNodes[n].getChild()->setValueOff(xyz, value);
1915template<
typename ChildT, Index Log2Dim>
1916template<
typename AccessorT>
1918InternalNode<ChildT, Log2Dim>::setValueOffAndCache(
const Coord& xyz,
1919 const ValueType& value, AccessorT& acc)
1921 const Index n = InternalNode::coordToOffset(xyz);
1922 bool hasChild = this->isChildMaskOn(n);
1924 const bool active = this->isValueMaskOn(n);
1925 if (active || !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1930 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1934 ChildT* child = mNodes[n].getChild();
1935 acc.insert(xyz, child);
1936 child->setValueOffAndCache(xyz, value, acc);
1941template<
typename ChildT, Index Log2Dim>
1943InternalNode<ChildT, Log2Dim>::setValueOn(
const Coord& xyz,
const ValueType& value)
1945 const Index n = this->coordToOffset(xyz);
1946 bool hasChild = this->isChildMaskOn(n);
1948 const bool active = this->isValueMaskOn(n);
1949 if (!active || !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1954 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1957 if (hasChild) mNodes[n].getChild()->setValueOn(xyz, value);
1960template<
typename ChildT, Index Log2Dim>
1961template<
typename AccessorT>
1963InternalNode<ChildT, Log2Dim>::setValueAndCache(
const Coord& xyz,
1964 const ValueType& value, AccessorT& acc)
1966 const Index n = this->coordToOffset(xyz);
1967 bool hasChild = this->isChildMaskOn(n);
1969 const bool active = this->isValueMaskOn(n);
1970 if (!active || !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1975 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1979 acc.insert(xyz, mNodes[n].getChild());
1980 mNodes[n].getChild()->setValueAndCache(xyz, value, acc);
1985template<
typename ChildT, Index Log2Dim>
1987InternalNode<ChildT, Log2Dim>::setValueOnly(
const Coord& xyz,
const ValueType& value)
1989 const Index n = this->coordToOffset(xyz);
1990 bool hasChild = this->isChildMaskOn(n);
1991 if (!hasChild && !math::isExactlyEqual(mNodes[n].getValue(), value)) {
1994 const bool active = this->isValueMaskOn(n);
1996 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1998 if (hasChild) mNodes[n].getChild()->setValueOnly(xyz, value);
2001template<
typename ChildT, Index Log2Dim>
2002template<
typename AccessorT>
2004InternalNode<ChildT, Log2Dim>::setValueOnlyAndCache(
const Coord& xyz,
2005 const ValueType& value, AccessorT& acc)
2007 const Index n = this->coordToOffset(xyz);
2008 bool hasChild = this->isChildMaskOn(n);
2009 if (!hasChild && !math::isExactlyEqual(mNodes[n].getValue(), value)) {
2012 const bool active = this->isValueMaskOn(n);
2014 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
2017 acc.insert(xyz, mNodes[n].getChild());
2018 mNodes[n].getChild()->setValueOnlyAndCache(xyz, value, acc);
2023template<
typename ChildT, Index Log2Dim>
2025InternalNode<ChildT, Log2Dim>::setActiveState(
const Coord& xyz,
bool on)
2027 const Index n = this->coordToOffset(xyz);
2028 bool hasChild = this->isChildMaskOn(n);
2030 if (on != this->isValueMaskOn(n)) {
2035 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
2038 if (hasChild) mNodes[n].getChild()->setActiveState(xyz, on);
2041template<
typename ChildT, Index Log2Dim>
2042template<
typename AccessorT>
2044InternalNode<ChildT, Log2Dim>::setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT& acc)
2046 const Index n = this->coordToOffset(xyz);
2047 bool hasChild = this->isChildMaskOn(n);
2049 if (on != this->isValueMaskOn(n)) {
2054 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
2058 ChildT* child = mNodes[n].getChild();
2059 acc.insert(xyz, child);
2060 child->setActiveStateAndCache(xyz, on, acc);
2065template<
typename ChildT, Index Log2Dim>
2067InternalNode<ChildT, Log2Dim>::setValuesOn()
2069 mValueMask = !mChildMask;
2070 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2071 mNodes[iter.pos()].getChild()->setValuesOn();
2076template<
typename ChildT, Index Log2Dim>
2077template<
typename ModifyOp>
2079InternalNode<ChildT, Log2Dim>::modifyValue(
const Coord& xyz,
const ModifyOp& op)
2081 const Index n = InternalNode::coordToOffset(xyz);
2082 bool hasChild = this->isChildMaskOn(n);
2086 const bool active = this->isValueMaskOn(n);
2087 bool createChild = !active;
2091 const ValueType& tileVal = mNodes[n].getValue();
2092 ValueType modifiedVal = tileVal;
2094 createChild = !math::isExactlyEqual(tileVal, modifiedVal);
2098 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
2101 if (hasChild) mNodes[n].getChild()->modifyValue(xyz, op);
2104template<
typename ChildT, Index Log2Dim>
2105template<
typename ModifyOp,
typename AccessorT>
2107InternalNode<ChildT, Log2Dim>::modifyValueAndCache(
const Coord& xyz,
const ModifyOp& op,
2110 const Index n = InternalNode::coordToOffset(xyz);
2111 bool hasChild = this->isChildMaskOn(n);
2115 const bool active = this->isValueMaskOn(n);
2116 bool createChild = !active;
2120 const ValueType& tileVal = mNodes[n].getValue();
2121 ValueType modifiedVal = tileVal;
2123 createChild = !math::isExactlyEqual(tileVal, modifiedVal);
2127 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
2131 ChildNodeType* child = mNodes[n].getChild();
2132 acc.insert(xyz, child);
2133 child->modifyValueAndCache(xyz, op, acc);
2138template<
typename ChildT, Index Log2Dim>
2139template<
typename ModifyOp>
2141InternalNode<ChildT, Log2Dim>::modifyValueAndActiveState(
const Coord& xyz,
const ModifyOp& op)
2143 const Index n = InternalNode::coordToOffset(xyz);
2144 bool hasChild = this->isChildMaskOn(n);
2146 const bool tileState = this->isValueMaskOn(n);
2147 const ValueType& tileVal = mNodes[n].getValue();
2148 bool modifiedState = !tileState;
2149 ValueType modifiedVal = tileVal;
2150 op(modifiedVal, modifiedState);
2153 if (modifiedState != tileState || !math::isExactlyEqual(modifiedVal, tileVal)) {
2155 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
2158 if (hasChild) mNodes[n].getChild()->modifyValueAndActiveState(xyz, op);
2161template<
typename ChildT, Index Log2Dim>
2162template<
typename ModifyOp,
typename AccessorT>
2164InternalNode<ChildT, Log2Dim>::modifyValueAndActiveStateAndCache(
2165 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
2167 const Index n = InternalNode::coordToOffset(xyz);
2168 bool hasChild = this->isChildMaskOn(n);
2170 const bool tileState = this->isValueMaskOn(n);
2171 const ValueType& tileVal = mNodes[n].getValue();
2172 bool modifiedState = !tileState;
2173 ValueType modifiedVal = tileVal;
2174 op(modifiedVal, modifiedState);
2177 if (modifiedState != tileState || !math::isExactlyEqual(modifiedVal, tileVal)) {
2179 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
2183 ChildNodeType* child = mNodes[n].getChild();
2184 acc.insert(xyz, child);
2185 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
2193template<
typename ChildT, Index Log2Dim>
2195InternalNode<ChildT, Log2Dim>::clip(
const CoordBBox& clipBBox,
const ValueType& background)
2197 CoordBBox nodeBBox = this->getNodeBoundingBox();
2198 if (!clipBBox.hasOverlap(nodeBBox)) {
2200 this->fill(nodeBBox, background,
false);
2201 }
else if (clipBBox.isInside(nodeBBox)) {
2210 for (Index pos = 0; pos < NUM_VALUES; ++pos) {
2211 const Coord xyz = this->offsetToGlobalCoord(pos);
2212 CoordBBox tileBBox(xyz, xyz.offsetBy(ChildT::DIM - 1));
2213 if (!clipBBox.hasOverlap(tileBBox)) {
2216 this->makeChildNodeEmpty(pos, background);
2217 mValueMask.setOff(pos);
2218 }
else if (!clipBBox.isInside(tileBBox)) {
2221 if (this->isChildMaskOn(pos)) {
2222 mNodes[pos].getChild()->clip(clipBBox, background);
2226 tileBBox.intersect(clipBBox);
2227 const ValueType val = mNodes[pos].getValue();
2228 const bool on = this->isValueMaskOn(pos);
2229 mNodes[pos].setValue(background);
2230 mValueMask.setOff(pos);
2231 this->fill(tileBBox, val, on);
2243template<
typename ChildT, Index Log2Dim>
2245InternalNode<ChildT, Log2Dim>::fill(
const CoordBBox& bbox,
const ValueType& value,
bool active)
2247 auto clippedBBox = this->getNodeBoundingBox();
2248 clippedBBox.intersect(bbox);
2249 if (!clippedBBox)
return;
2253 Coord xyz, tileMin, tileMax;
2254 for (
int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.x() + 1) {
2256 for (
int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.y() + 1) {
2258 for (
int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.z() + 1) {
2262 const Index n = this->coordToOffset(xyz);
2263 tileMin = this->offsetToGlobalCoord(n);
2264 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2266 if (xyz != tileMin || Coord::lessThan(clippedBBox.max(), tileMax)) {
2270 ChildT* child =
nullptr;
2271 if (this->isChildMaskOff(n)) {
2274 child =
new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)};
2275 this->setChildNode(n, child);
2277 child = mNodes[n].getChild();
2282 const Coord tmp = Coord::minComponent(clippedBBox.max(), tileMax);
2283 child->fill(CoordBBox(xyz, tmp), value, active);
2290 this->makeChildNodeEmpty(n, value);
2291 mValueMask.set(n, active);
2299template<
typename ChildT, Index Log2Dim>
2301InternalNode<ChildT, Log2Dim>::denseFill(
const CoordBBox& bbox,
const ValueType& value,
bool active)
2303 auto clippedBBox = this->getNodeBoundingBox();
2304 clippedBBox.intersect(bbox);
2305 if (!clippedBBox)
return;
2309 Coord xyz, tileMin, tileMax;
2310 for (
int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.x() + 1) {
2312 for (
int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.y() + 1) {
2314 for (
int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.z() + 1) {
2318 const auto n = this->coordToOffset(xyz);
2321 ChildT* child =
nullptr;
2322 if (this->isChildMaskOn(n)) {
2323 child = mNodes[n].getChild();
2327 child =
new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)};
2328 this->setChildNode(n, child);
2332 tileMin = this->offsetToGlobalCoord(n);
2333 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2336 child->denseFill(CoordBBox{xyz, clippedBBox.max()}, value, active);
2346template<
typename ChildT, Index Log2Dim>
2347template<
typename DenseT>
2349InternalNode<ChildT, Log2Dim>::copyToDense(
const CoordBBox& bbox, DenseT& dense)
const
2351 using DenseValueType =
typename DenseT::ValueType;
2353 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2354 const Coord&
min = dense.bbox().min();
2355 for (Coord xyz = bbox.min(), max; xyz[0] <= bbox.max()[0]; xyz[0] = max[0] + 1) {
2356 for (xyz[1] = bbox.min()[1]; xyz[1] <= bbox.max()[1]; xyz[1] = max[1] + 1) {
2357 for (xyz[2] = bbox.min()[2]; xyz[2] <= bbox.max()[2]; xyz[2] = max[2] + 1) {
2358 const Index n = this->coordToOffset(xyz);
2360 max = this->offsetToGlobalCoord(n).offsetBy(ChildT::DIM-1);
2363 CoordBBox sub(xyz, Coord::minComponent(bbox.max(), max));
2365 if (this->isChildMaskOn(n)) {
2366 mNodes[n].getChild()->copyToDense(sub, dense);
2368 const ValueType value = mNodes[n].getValue();
2369 sub.translate(-min);
2370 DenseValueType* a0 = dense.data() + zStride*sub.min()[2];
2371 for (Int32 x=sub.min()[0], ex=sub.max()[0]+1; x<ex; ++x) {
2372 DenseValueType* a1 = a0 + x*xStride;
2373 for (Int32 y=sub.min()[1], ey=sub.max()[1]+1; y<ey; ++y) {
2374 DenseValueType* a2 = a1 + y*yStride;
2375 for (Int32 z = sub.min()[2], ez = sub.max()[2]+1;
2376 z < ez; ++z, a2 += zStride)
2378 *a2 = DenseValueType(value);
2392template<
typename ChildT, Index Log2Dim>
2394InternalNode<ChildT, Log2Dim>::writeTopology(std::ostream& os,
bool toHalf)
const
2396 mChildMask.save(os);
2397 mValueMask.save(os);
2401 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[NUM_VALUES]);
2402 ValueType* values = valuePtr.get();
2403 const ValueType zero = zeroVal<ValueType>();
2404 for (Index i = 0; i < NUM_VALUES; ++i) {
2405 values[i] = (mChildMask.isOff(i) ? mNodes[i].getValue() : zero);
2408 io::writeCompressedValues(os, values, NUM_VALUES, mValueMask, mChildMask, toHalf);
2411 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2412 iter->writeTopology(os, toHalf);
2417template<
typename ChildT, Index Log2Dim>
2419InternalNode<ChildT, Log2Dim>::readTopology(std::istream& is,
bool fromHalf)
2421 io::checkFormatVersion(is);
2423 const ValueType background = (!io::getGridBackgroundValuePtr(is) ? zeroVal<ValueType>()
2426 mChildMask.load(is);
2427 mValueMask.load(is);
2429 const Index numValues = NUM_VALUES;
2433 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[numValues]);
2434 ValueType* values = valuePtr.get();
2435 io::readCompressedValues(is, values, numValues, mValueMask, fromHalf);
2438 for (ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2439 mNodes[iter.pos()].setValue(values[iter.pos()]);
2444 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2445 ChildNodeType* child =
new ChildNodeType(PartialCreate(), iter.getCoord(), background);
2446 mNodes[iter.pos()].setChild(child);
2447 child->readTopology(is, fromHalf);
2455template<
typename ChildT, Index Log2Dim>
2456inline const typename ChildT::ValueType&
2457InternalNode<ChildT, Log2Dim>::getFirstValue()
const
2459 return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].getValue());
2463template<
typename ChildT, Index Log2Dim>
2464inline const typename ChildT::ValueType&
2465InternalNode<ChildT, Log2Dim>::getLastValue()
const
2467 const Index n = NUM_VALUES - 1;
2468 return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].getValue());
2475template<
typename ChildT, Index Log2Dim>
2476inline const typename ChildT::ValueType&
2477InternalNode<ChildT, Log2Dim>::getValueUnsafe(Index n)
const
2481 return mNodes[n].getValue();
2484template<
typename ChildT, Index Log2Dim>
2486InternalNode<ChildT, Log2Dim>::getValueUnsafe(Index n, ValueType& value)
const
2490 value = mNodes[n].getValue();
2491 return mValueMask.isOn(n);
2494template<
typename ChildT, Index Log2Dim>
2496InternalNode<ChildT, Log2Dim>::getChildUnsafe(Index n)
2500 return mNodes[n].getChild();
2503template<
typename ChildT, Index Log2Dim>
2505InternalNode<ChildT, Log2Dim>::getConstChildUnsafe(Index n)
const
2509 return mNodes[n].getChild();
2512template<
typename ChildT, Index Log2Dim>
2514InternalNode<ChildT, Log2Dim>::getChildUnsafe(Index n)
const
2516 return this->getConstChildUnsafe(n);
2519template<
typename ChildT, Index Log2Dim>
2521InternalNode<ChildT, Log2Dim>::setActiveStateUnsafe(Index n,
bool on)
2525 mValueMask.set(n, on);
2528template<
typename ChildT, Index Log2Dim>
2530InternalNode<ChildT, Log2Dim>::setValueOnlyUnsafe(Index n,
const ValueType& value)
2534 mNodes[n].setValue(value);
2537template<
typename ChildT, Index Log2Dim>
2539InternalNode<ChildT, Log2Dim>::setValueOnUnsafe(Index n)
2543 mValueMask.setOn(n);
2546template<
typename ChildT, Index Log2Dim>
2548InternalNode<ChildT, Log2Dim>::setValueOnUnsafe(Index n,
const ValueType& value)
2552 mNodes[n].setValue(value);
2553 mValueMask.setOn(n);
2556template<
typename ChildT, Index Log2Dim>
2558InternalNode<ChildT, Log2Dim>::setValueOffUnsafe(Index n)
2562 mValueMask.setOff(n);
2565template<
typename ChildT, Index Log2Dim>
2567InternalNode<ChildT, Log2Dim>::setValueOffUnsafe(Index n,
const ValueType& value)
2571 mNodes[n].setValue(value);
2572 mValueMask.setOff(n);
2575template<
typename ChildT, Index Log2Dim>
2577InternalNode<ChildT, Log2Dim>::setValueMaskUnsafe(
const NodeMaskType& mask)
2583template<
typename ChildT, Index Log2Dim>
2585InternalNode<ChildT, Log2Dim>::setChildUnsafe(Index n, ChildNodeType* child)
2590 mNodes[n].setChild(child);
2591 mChildMask.setOn(n);
2592 mValueMask.setOff(n);
2595template<
typename ChildT, Index Log2Dim>
2597InternalNode<ChildT, Log2Dim>::resetChildUnsafe(Index n, ChildNodeType* child)
2603 delete mNodes[n].getChild();
2604 mNodes[n].setChild(child);
2607template<
typename ChildT, Index Log2Dim>
2609InternalNode<ChildT, Log2Dim>::stealChildUnsafe(Index n,
const ValueType& value,
bool active)
2614 auto* child = mNodes[n].getChild();
2615 mChildMask.setOff(n);
2616 mValueMask.set(n, active);
2617 mNodes[n].setValue(value);
2621template<
typename ChildT, Index Log2Dim>
2623InternalNode<ChildT, Log2Dim>::deleteChildUnsafe(Index n,
const ValueType& value,
bool active)
2626 delete this->stealChildUnsafe(n, value, active);
2633template<
typename ChildT, Index Log2Dim>
2635InternalNode<ChildT, Log2Dim>::negate()
2637 for (Index i = 0; i < NUM_VALUES; ++i) {
2638 if (this->isChildMaskOn(i)) {
2639 mNodes[i].getChild()->negate();
2641 mNodes[i].setValue(math::negative(mNodes[i].getValue()));
2651template<
typename ChildT, Index Log2Dim>
2652struct InternalNode<ChildT, Log2Dim>::VoxelizeActiveTiles
2654 VoxelizeActiveTiles(InternalNode &node) : mNode(&node) {
2656 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2658 node.mChildMask |= node.mValueMask;
2659 node.mValueMask.setOff();
2661 void operator()(
const tbb::blocked_range<Index> &r)
const
2663 for (Index i = r.begin(), end=r.end(); i!=end; ++i) {
2664 if (mNode->mChildMask.isOn(i)) {
2665 mNode->mNodes[i].getChild()->voxelizeActiveTiles(
true);
2666 }
else if (mNode->mValueMask.isOn(i)) {
2667 const Coord &ijk = mNode->offsetToGlobalCoord(i);
2668 ChildNodeType *child =
new ChildNodeType(ijk, mNode->mNodes[i].getValue(),
true);
2669 child->voxelizeActiveTiles(
true);
2670 mNode->mNodes[i].setChild(child);
2674 InternalNode* mNode;
2677template<
typename ChildT, Index Log2Dim>
2679InternalNode<ChildT, Log2Dim>::voxelizeActiveTiles(
bool threaded)
2682 VoxelizeActiveTiles tmp(*
this);
2684 for (ValueOnIter iter = this->beginValueOn(); iter; ++iter) {
2685 this->setChildNode(iter.pos(),
2686 new ChildNodeType(iter.getCoord(), iter.getValue(),
true));
2688 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter)
2689 iter->voxelizeActiveTiles(
false);
2697template<
typename ChildT, Index Log2Dim>
2698template<MergePolicy Policy>
2700InternalNode<ChildT, Log2Dim>::merge(InternalNode& other,
2701 const ValueType& background,
const ValueType& otherBackground)
2710 for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) {
2711 const Index n = iter.pos();
2712 if (mChildMask.isOn(n)) {
2714 mNodes[n].getChild()->template merge<MERGE_ACTIVE_STATES>(*iter,
2715 background, otherBackground);
2716 }
else if (mValueMask.isOff(n)) {
2721 ChildNodeType* child = other.mNodes[n].getChild();
2722 other.mChildMask.setOff(n);
2723 child->resetBackground(otherBackground, background);
2724 this->setChildNode(n, child);
2729 for (ValueOnCIter iter = other.cbeginValueOn(); iter; ++iter) {
2730 const Index n = iter.pos();
2731 if (mValueMask.isOff(n)) {
2733 this->makeChildNodeEmpty(n, iter.getValue());
2734 mValueMask.setOn(n);
2742 for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) {
2743 const Index n = iter.pos();
2744 if (mChildMask.isOn(n)) {
2746 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2752 ChildNodeType* child = other.mNodes[n].getChild();
2753 other.mChildMask.setOff(n);
2754 child->resetBackground(otherBackground, background);
2755 this->setChildNode(n, child);
2764 for (ChildOnIter iter = other.beginChildOn(); iter; ++iter) {
2765 const Index n = iter.pos();
2766 if (mChildMask.isOn(n)) {
2768 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2773 ChildNodeType* child = other.mNodes[n].getChild();
2774 other.mChildMask.setOff(n);
2775 child->resetBackground(otherBackground, background);
2776 if (mValueMask.isOn(n)) {
2778 child->template merge<Policy>(mNodes[n].getValue(),
true);
2779 mValueMask.setOff(n);
2781 mChildMask.setOn(n);
2782 mNodes[n].setChild(child);
2787 for (ValueOnCIter iter = other.cbeginValueOn(); iter; ++iter) {
2788 const Index n = iter.pos();
2789 if (mChildMask.isOn(n)) {
2791 mNodes[n].getChild()->template merge<Policy>(iter.getValue(),
true);
2792 }
else if (mValueMask.isOff(n)) {
2794 mNodes[n].setValue(iter.getValue());
2795 mValueMask.setOn(n);
2806template<
typename ChildT, Index Log2Dim>
2807template<MergePolicy Policy>
2809InternalNode<ChildT, Log2Dim>::merge(
const ValueType& tileValue,
bool tileActive)
2813 if (Policy != MERGE_ACTIVE_STATES_AND_NODES)
return;
2816 if (!tileActive)
return;
2819 for (ValueOffIter iter = this->beginValueOff(); iter; ++iter) {
2820 const Index n = iter.pos();
2821 if (mChildMask.isOn(n)) {
2823 mNodes[n].getChild()->template merge<Policy>(tileValue,
true);
2826 iter.setValue(tileValue);
2827 mValueMask.setOn(n);
2837template<
typename ChildT, Index Log2Dim>
2838template<
typename OtherInternalNode>
2839struct InternalNode<ChildT, Log2Dim>::TopologyUnion
2841 using W =
typename NodeMaskType::Word;
2842 struct A {
inline void operator()(W &tV,
const W& sV,
const W& tC)
const
2843 { tV = (tV | sV) & ~tC; }
2845 TopologyUnion(
const OtherInternalNode* source, InternalNode* target,
const bool preserveTiles)
2846 : s(source), t(target), mPreserveTiles(preserveTiles) {
2848 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2851 if (!mPreserveTiles) t->mChildMask |= s->mChildMask;
2852 else t->mChildMask |= (s->mChildMask & !t->mValueMask);
2855 t->mValueMask.foreach(s->mValueMask, t->mChildMask, op);
2858 void operator()(
const tbb::blocked_range<Index> &r)
const {
2859 for (Index i = r.begin(), end=r.end(); i!=end; ++i) {
2860 if (s->mChildMask.isOn(i)) {
2861 const typename OtherInternalNode::ChildNodeType& other = *(s->mNodes[i].getChild());
2862 if (t->mChildMask.isOn(i)) {
2863 t->mNodes[i].getChild()->topologyUnion(other, mPreserveTiles);
2865 if (!mPreserveTiles || t->mValueMask.isOff(i)) {
2866 ChildT* child =
new ChildT(other, t->mNodes[i].getValue(), TopologyCopy());
2867 if (t->mValueMask.isOn(i)) child->setValuesOn();
2868 t->mNodes[i].setChild(child);
2871 }
else if (s->mValueMask.isOn(i) && t->mChildMask.isOn(i)) {
2872 t->mNodes[i].getChild()->setValuesOn();
2876 const OtherInternalNode* s;
2878 const bool mPreserveTiles;
2881template<
typename ChildT, Index Log2Dim>
2882template<
typename OtherChildT>
2884InternalNode<ChildT, Log2Dim>::topologyUnion(
const InternalNode<OtherChildT, Log2Dim>& other,
const bool preserveTiles)
2886 TopologyUnion<InternalNode<OtherChildT, Log2Dim> > tmp(&other,
this, preserveTiles);
2889template<
typename ChildT, Index Log2Dim>
2890template<
typename OtherInternalNode>
2891struct InternalNode<ChildT, Log2Dim>::TopologyIntersection
2893 using W =
typename NodeMaskType::Word;
2894 struct A {
inline void operator()(W &tC,
const W& sC,
const W& sV,
const W& tV)
const
2895 { tC = (tC & (sC | sV)) | (tV & sC); }
2897 TopologyIntersection(
const OtherInternalNode* source, InternalNode* target,
2898 const ValueType& background) : s(source), t(target), b(background) {
2900 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2904 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op);
2906 t->mValueMask &= s->mValueMask;
2909 void operator()(
const tbb::blocked_range<Index> &r)
const {
2910 for (Index i = r.begin(), end=r.end(); i!=end; ++i) {
2911 if (t->mChildMask.isOn(i)) {
2912 ChildT* child = t->mNodes[i].getChild();
2913 if (s->mChildMask.isOn(i)) {
2914 child->topologyIntersection(*(s->mNodes[i].getChild()), b);
2915 }
else if (s->mValueMask.isOff(i)) {
2917 t->mNodes[i].setValue(b);
2919 }
else if (t->mValueMask.isOn(i) && s->mChildMask.isOn(i)) {
2920 t->mNodes[i].setChild(
new ChildT(*(s->mNodes[i].getChild()),
2921 t->mNodes[i].getValue(), TopologyCopy()));
2925 const OtherInternalNode* s;
2930template<
typename ChildT, Index Log2Dim>
2931template<
typename OtherChildT>
2933InternalNode<ChildT, Log2Dim>::topologyIntersection(
2934 const InternalNode<OtherChildT, Log2Dim>& other,
const ValueType& background)
2936 TopologyIntersection<InternalNode<OtherChildT, Log2Dim> > tmp(&other,
this, background);
2939template<
typename ChildT, Index Log2Dim>
2940template<
typename OtherInternalNode>
2941struct InternalNode<ChildT, Log2Dim>::TopologyDifference
2943 using W =
typename NodeMaskType::Word;
2944 struct A {
inline void operator()(W &tC,
const W& sC,
const W& sV,
const W& tV)
const
2945 { tC = (tC & (sC | ~sV)) | (tV & sC); }
2947 struct B {
inline void operator()(W &tV,
const W& sC,
const W& sV,
const W& tC)
const
2948 { tV &= ~((tC & sV) | (sC | sV)); }
2950 TopologyDifference(
const OtherInternalNode* source, InternalNode* target,
2951 const ValueType& background) : s(source), t(target), b(background) {
2953 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2956 const NodeMaskType oldChildMask(t->mChildMask);
2958 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op1);
2961 t->mValueMask.foreach(t->mChildMask, s->mValueMask, oldChildMask, op2);
2964 void operator()(
const tbb::blocked_range<Index> &r)
const {
2965 for (Index i = r.begin(), end=r.end(); i!=end; ++i) {
2966 if (t->mChildMask.isOn(i)) {
2967 ChildT* child = t->mNodes[i].getChild();
2968 if (s->mChildMask.isOn(i)) {
2969 child->topologyDifference(*(s->mNodes[i].getChild()), b);
2970 }
else if (s->mValueMask.isOn(i)) {
2972 t->mNodes[i].setValue(b);
2974 }
else if (t->mValueMask.isOn(i)) {
2975 if (s->mChildMask.isOn(i)) {
2976 const typename OtherInternalNode::ChildNodeType& other =
2977 *(s->mNodes[i].getChild());
2978 ChildT* child =
new ChildT(other.origin(), t->mNodes[i].getValue(),
true);
2979 child->topologyDifference(other, b);
2980 t->mNodes[i].setChild(child);
2985 const OtherInternalNode* s;
2990template<
typename ChildT, Index Log2Dim>
2991template<
typename OtherChildT>
2993InternalNode<ChildT, Log2Dim>::topologyDifference(
const InternalNode<OtherChildT, Log2Dim>& other,
2994 const ValueType& background)
2996 TopologyDifference<InternalNode<OtherChildT, Log2Dim> > tmp(&other,
this, background);
3003template<
typename ChildT, Index Log2Dim>
3004template<
typename CombineOp>
3006InternalNode<ChildT, Log2Dim>::combine(InternalNode& other, CombineOp& op)
3008 const ValueType zero = zeroVal<ValueType>();
3010 CombineArgs<ValueType> args;
3012 for (Index i = 0; i < NUM_VALUES; ++i) {
3013 if (this->isChildMaskOff(i) && other.isChildMaskOff(i)) {
3016 op(args.setARef(mNodes[i].getValue())
3017 .setAIsActive(isValueMaskOn(i))
3018 .setBRef(other.mNodes[i].getValue())
3019 .setBIsActive(other.isValueMaskOn(i)));
3020 mNodes[i].setValue(args.result());
3021 mValueMask.set(i, args.resultIsActive());
3022 }
else if (this->isChildMaskOn(i) && other.isChildMaskOff(i)) {
3024 ChildNodeType* child = mNodes[i].getChild();
3027 child->combine(other.mNodes[i].getValue(), other.isValueMaskOn(i), op);
3029 }
else if (this->isChildMaskOff(i) && other.isChildMaskOn(i)) {
3031 ChildNodeType* child = other.mNodes[i].getChild();
3037 SwappedCombineOp<ValueType, CombineOp> swappedOp(op);
3038 child->combine(mNodes[i].getValue(), isValueMaskOn(i), swappedOp);
3041 other.mChildMask.setOff(i);
3042 other.mNodes[i].setValue(zero);
3043 this->setChildNode(i, child);
3049 *child = mNodes[i].getChild(),
3050 *otherChild = other.mNodes[i].getChild();
3053 if (child && otherChild) {
3054 child->combine(*otherChild, op);
3061template<
typename ChildT, Index Log2Dim>
3062template<
typename CombineOp>
3064InternalNode<ChildT, Log2Dim>::combine(
const ValueType& value,
bool valueIsActive, CombineOp& op)
3066 CombineArgs<ValueType> args;
3068 for (Index i = 0; i < NUM_VALUES; ++i) {
3069 if (this->isChildMaskOff(i)) {
3071 op(args.setARef(mNodes[i].getValue())
3072 .setAIsActive(isValueMaskOn(i))
3074 .setBIsActive(valueIsActive));
3075 mNodes[i].setValue(args.result());
3076 mValueMask.set(i, args.resultIsActive());
3079 ChildNodeType* child = mNodes[i].getChild();
3081 if (child) child->combine(value, valueIsActive, op);
3090template<
typename ChildT, Index Log2Dim>
3091template<
typename CombineOp,
typename OtherNodeType>
3093InternalNode<ChildT, Log2Dim>::combine2(
const InternalNode& other0,
const OtherNodeType& other1,
3096 CombineArgs<ValueType, typename OtherNodeType::ValueType> args;
3098 for (Index i = 0; i < NUM_VALUES; ++i) {
3099 if (other0.isChildMaskOff(i) && other1.isChildMaskOff(i)) {
3100 op(args.setARef(other0.mNodes[i].getValue())
3101 .setAIsActive(other0.isValueMaskOn(i))
3102 .setBRef(other1.mNodes[i].getValue())
3103 .setBIsActive(other1.isValueMaskOn(i)));
3105 this->makeChildNodeEmpty(i, args.result());
3106 mValueMask.set(i, args.resultIsActive());
3108 if (this->isChildMaskOff(i)) {
3110 const Coord& childOrigin = other0.isChildMaskOn(i)
3111 ? other0.mNodes[i].getChild()->origin()
3112 : other1.mNodes[i].getChild()->origin();
3113 this->setChildNode(i,
new ChildNodeType(childOrigin, mNodes[i].getValue()));
3116 if (other0.isChildMaskOff(i)) {
3119 mNodes[i].getChild()->combine2(other0.mNodes[i].getValue(),
3120 *other1.mNodes[i].getChild(), other0.isValueMaskOn(i), op);
3121 }
else if (other1.isChildMaskOff(i)) {
3124 mNodes[i].getChild()->combine2(*other0.mNodes[i].getChild(),
3125 other1.mNodes[i].getValue(), other1.isValueMaskOn(i), op);
3129 mNodes[i].getChild()->combine2(*other0.mNodes[i].getChild(),
3130 *other1.mNodes[i].getChild(), op);
3137template<
typename ChildT, Index Log2Dim>
3138template<
typename CombineOp,
typename OtherNodeType>
3140InternalNode<ChildT, Log2Dim>::combine2(
const ValueType& value,
const OtherNodeType& other,
3141 bool valueIsActive, CombineOp& op)
3143 CombineArgs<ValueType, typename OtherNodeType::ValueType> args;
3145 for (Index i = 0; i < NUM_VALUES; ++i) {
3146 if (other.isChildMaskOff(i)) {
3147 op(args.setARef(value)
3148 .setAIsActive(valueIsActive)
3149 .setBRef(other.mNodes[i].getValue())
3150 .setBIsActive(other.isValueMaskOn(i)));
3152 this->makeChildNodeEmpty(i, args.result());
3153 mValueMask.set(i, args.resultIsActive());
3155 typename OtherNodeType::ChildNodeType* otherChild = other.mNodes[i].getChild();
3157 if (this->isChildMaskOff(i)) {
3160 this->setChildNode(i,
new ChildNodeType(*otherChild));
3164 mNodes[i].getChild()->combine2(value, *otherChild, valueIsActive, op);
3170template<
typename ChildT, Index Log2Dim>
3171template<
typename CombineOp,
typename OtherValueType>
3173InternalNode<ChildT, Log2Dim>::combine2(
const InternalNode& other,
const OtherValueType& value,
3174 bool valueIsActive, CombineOp& op)
3176 CombineArgs<ValueType, OtherValueType> args;
3178 for (Index i = 0; i < NUM_VALUES; ++i) {
3179 if (other.isChildMaskOff(i)) {
3180 op(args.setARef(other.mNodes[i].getValue())
3181 .setAIsActive(other.isValueMaskOn(i))
3183 .setBIsActive(valueIsActive));
3185 this->makeChildNodeEmpty(i, args.result());
3186 mValueMask.set(i, args.resultIsActive());
3188 ChildNodeType* otherChild = other.mNodes[i].getChild();
3190 if (this->isChildMaskOff(i)) {
3192 this->setChildNode(i,
3193 new ChildNodeType(otherChild->origin(), mNodes[i].getValue()));
3197 mNodes[i].getChild()->combine2(*otherChild, value, valueIsActive, op);
3206template<
typename ChildT, Index Log2Dim>
3208InternalNode<ChildT, Log2Dim>::writeBuffers(std::ostream& os,
bool toHalf)
const
3210 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3211 iter->writeBuffers(os, toHalf);
3216template<
typename ChildT, Index Log2Dim>
3218InternalNode<ChildT, Log2Dim>::readBuffers(std::istream& is,
bool fromHalf)
3220 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3221 iter->readBuffers(is, fromHalf);
3226template<
typename ChildT, Index Log2Dim>
3228InternalNode<ChildT, Log2Dim>::readBuffers(std::istream& is,
3229 const CoordBBox& clipBBox,
bool fromHalf)
3231 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3236 iter->readBuffers(is, clipBBox, fromHalf);
3240 ValueType background = zeroVal<ValueType>();
3241 if (
const void* bgPtr = io::getGridBackgroundValuePtr(is)) {
3242 background = *
static_cast<const ValueType*
>(bgPtr);
3244 this->
clip(clipBBox, background);
3251template<
typename ChildT, Index Log2Dim>
3253InternalNode<ChildT, Log2Dim>::getNodeLog2Dims(std::vector<Index>& dims)
3255 dims.push_back(Log2Dim);
3256 ChildNodeType::getNodeLog2Dims(dims);
3260template<
typename ChildT, Index Log2Dim>
3262InternalNode<ChildT, Log2Dim>::offsetToLocalCoord(Index n, Coord &xyz)
3265 xyz.setX(n >> 2*Log2Dim);
3266 n &= ((1<<2*Log2Dim)-1);
3267 xyz.setY(n >> Log2Dim);
3268 xyz.setZ(n & ((1<<Log2Dim)-1));
3272template<
typename ChildT, Index Log2Dim>
3274InternalNode<ChildT, Log2Dim>::coordToOffset(
const Coord& xyz)
3276 return (((xyz[0] & (DIM-1u)) >> ChildNodeType::TOTAL) << 2*Log2Dim)
3277 + (((xyz[1] & (DIM-1u)) >> ChildNodeType::TOTAL) << Log2Dim)
3278 + ((xyz[2] & (DIM-1u)) >> ChildNodeType::TOTAL);
3282template<
typename ChildT, Index Log2Dim>
3284InternalNode<ChildT, Log2Dim>::offsetToGlobalCoord(Index n)
const
3287 this->offsetToLocalCoord(n, local);
3288 local <<= ChildT::TOTAL;
3289 return local + this->origin();
3296template<
typename ChildT, Index Log2Dim>
3297template<
typename ArrayT>
3299InternalNode<ChildT, Log2Dim>::getNodes(ArrayT& array)
3301 using T =
typename ArrayT::value_type;
3302 static_assert(std::is_pointer<T>::value,
"argument to getNodes() must be a pointer array");
3303 using ArrayChildT =
typename std::conditional<
3304 std::is_const<typename std::remove_pointer<T>::type>::value,
const ChildT, ChildT>::type;
3305 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3307 if (std::is_same<T, ArrayChildT*>::value) {
3308 array.push_back(
reinterpret_cast<T
>(mNodes[iter.pos()].getChild()));
3310 iter->getNodes(array);
3316template<
typename ChildT, Index Log2Dim>
3317template<
typename ArrayT>
3319InternalNode<ChildT, Log2Dim>::getNodes(ArrayT& array)
const
3321 using T =
typename ArrayT::value_type;
3322 static_assert(std::is_pointer<T>::value,
"argument to getNodes() must be a pointer array");
3323 static_assert(std::is_const<typename std::remove_pointer<T>::type>::value,
3324 "argument to getNodes() must be an array of const node pointers");
3325 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3327 if (std::is_same<T, const ChildT*>::value) {
3328 array.push_back(
reinterpret_cast<T
>(mNodes[iter.pos()].getChild()));
3330 iter->getNodes(array);
3340template<
typename ChildT, Index Log2Dim>
3341template<
typename ArrayT>
3343InternalNode<ChildT, Log2Dim>::stealNodes(ArrayT& array,
const ValueType& value,
bool state)
3345 using T =
typename ArrayT::value_type;
3346 static_assert(std::is_pointer<T>::value,
"argument to stealNodes() must be a pointer array");
3347 using ArrayChildT =
typename std::conditional<
3348 std::is_const<typename std::remove_pointer<T>::type>::value,
const ChildT, ChildT>::type;
3350 for (ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3351 const Index n = iter.pos();
3352 if (std::is_same<T, ArrayChildT*>::value) {
3353 array.push_back(
reinterpret_cast<T
>(mNodes[n].getChild()));
3354 mValueMask.set(n, state);
3355 mNodes[n].setValue(value);
3357 iter->stealNodes(array, value, state);
3360 if (std::is_same<T, ArrayChildT*>::value) mChildMask.setOff();
3368template<
typename ChildT, Index Log2Dim>
3370InternalNode<ChildT, Log2Dim>::resetBackground(
const ValueType& oldBackground,
3371 const ValueType& newBackground)
3373 if (math::isExactlyEqual(oldBackground, newBackground))
return;
3374 for (Index i = 0; i < NUM_VALUES; ++i) {
3375 if (this->isChildMaskOn(i)) {
3376 mNodes[i].getChild()->resetBackground(oldBackground, newBackground);
3377 }
else if (this->isValueMaskOff(i)) {
3378 if (math::isApproxEqual(mNodes[i].getValue(), oldBackground)) {
3379 mNodes[i].setValue(newBackground);
3380 }
else if (math::isApproxEqual(mNodes[i].getValue(), math::negative(oldBackground))) {
3381 mNodes[i].setValue(math::negative(newBackground));
3387template<
typename ChildT, Index Log2Dim>
3388template<
typename OtherChildNodeType, Index OtherLog2Dim>
3390InternalNode<ChildT, Log2Dim>::hasSameTopology(
3391 const InternalNode<OtherChildNodeType, OtherLog2Dim>* other)
const
3393 if (Log2Dim != OtherLog2Dim || mChildMask != other->mChildMask ||
3394 mValueMask != other->mValueMask)
return false;
3395 for (ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3396 if (!iter->hasSameTopology(other->mNodes[iter.pos()].getChild()))
return false;
3402template<
typename ChildT, Index Log2Dim>
3404InternalNode<ChildT, Log2Dim>::resetChildNode(Index i, ChildNodeType* child)
3407 if (this->isChildMaskOn(i)) {
3408 delete mNodes[i].getChild();
3410 mChildMask.setOn(i);
3411 mValueMask.setOff(i);
3413 mNodes[i].setChild(child);
3416template<
typename ChildT, Index Log2Dim>
3418InternalNode<ChildT, Log2Dim>::setChildNode(Index i, ChildNodeType* child)
3422 mChildMask.setOn(i);
3423 mValueMask.setOff(i);
3424 mNodes[i].setChild(child);
3428template<
typename ChildT, Index Log2Dim>
3430InternalNode<ChildT, Log2Dim>::unsetChildNode(Index i,
const ValueType& value)
3432 if (this->isChildMaskOff(i)) {
3433 mNodes[i].setValue(value);
3436 ChildNodeType* child = mNodes[i].getChild();
3437 mChildMask.setOff(i);
3438 mNodes[i].setValue(value);
3443template<
typename ChildT, Index Log2Dim>
3445InternalNode<ChildT, Log2Dim>::makeChildNodeEmpty(Index n,
const ValueType& value)
3447 delete this->unsetChildNode(n, value);
3450template<
typename ChildT, Index Log2Dim>
3452InternalNode<ChildT, Log2Dim>::getChildNode(Index n)
3455 return mNodes[n].getChild();
3459template<
typename ChildT, Index Log2Dim>
3461InternalNode<ChildT, Log2Dim>::getChildNode(Index n)
const
3464 return mNodes[n].getChild();
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
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...
Level getLevel()
Return the current logging level.
Definition logging.h:141
Index32 Index
Definition Types.h:34
uint32_t Index32
Definition Types.h:32
uint64_t Index64
Definition Types.h:33
@ MERGE_ACTIVE_STATES
Definition Types.h:578
@ MERGE_NODES
Definition Types.h:579
@ MERGE_ACTIVE_STATES_AND_NODES
Definition Types.h:580
ValueType combine(const ValueType &v0, const ValueType &v1, const ValueType &v2, const openvdb::Vec3d &w)
Combine different value types.
Definition AttributeTransferUtil.h:141
Definition Exceptions.h:13
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218