8 #ifndef OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED
9 #define OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED
18 #include <tbb/parallel_for.h>
31 template<
typename HeadType,
int HeadLevel>
struct NodeChain;
32 template<
typename,
typename>
struct SameRootConfig;
33 template<
typename,
typename,
bool>
struct RootNodeCopyHelper;
34 template<
typename,
typename,
typename,
bool>
struct RootNodeCombineHelper;
37 template<
typename ChildType>
46 static const Index LEVEL = 1 + ChildType::LEVEL;
50 static_assert(NodeChainType::Size == LEVEL + 1,
51 "wrong number of entries in RootNode node chain");
55 template<
typename OtherValueType>
63 template<
typename OtherNodeType>
83 template<
typename OtherChildType>
94 template<
typename OtherChildType>
96 const ValueType& background,
const ValueType& foreground,
TopologyCopy);
108 template<
typename OtherChildType>
120 template<
typename OtherChildType>
127 Tile(): value(
zeroVal<ValueType>()), active(false) {}
128 Tile(
const ValueType& v,
bool b): value(v), active(b) {}
138 NodeStruct(): child(nullptr) {}
139 NodeStruct(ChildType& c): child(&c) {}
140 NodeStruct(
const Tile& t): child(nullptr), tile(t) {}
141 NodeStruct(
const NodeStruct&) =
default;
142 NodeStruct& operator=(
const NodeStruct&) =
default;
145 bool isChild()
const {
return child !=
nullptr; }
146 bool isTile()
const {
return child ==
nullptr; }
147 bool isTileOff()
const {
return isTile() && !tile.active; }
148 bool isTileOn()
const {
return isTile() && tile.active; }
150 void set(ChildType& c) {
delete child; child = &c; }
151 void set(
const Tile& t) {
delete child; child =
nullptr; tile = t; }
152 ChildType& steal(
const Tile& t) { ChildType* c=child; child=
nullptr; tile=t;
return *c; }
155 using MapType = std::map<Coord, NodeStruct>;
156 using MapIter =
typename MapType::iterator;
157 using MapCIter =
typename MapType::const_iterator;
159 using CoordSet = std::set<Coord>;
160 using CoordSetIter =
typename CoordSet::iterator;
161 using CoordSetCIter =
typename CoordSet::const_iterator;
163 static void setTile(
const MapIter& i,
const Tile& t) { i->second.set(t); }
164 static void setChild(
const MapIter& i, ChildType& c) { i->second.set(c); }
165 static Tile& getTile(
const MapIter& i) {
return i->second.tile; }
166 static const Tile& getTile(
const MapCIter& i) {
return i->second.tile; }
167 static ChildType& getChild(
const MapIter& i) {
return *(i->second.child); }
168 static const ChildType& getChild(
const MapCIter& i) {
return *(i->second.child); }
169 static ChildType& stealChild(
const MapIter& i,
const Tile& t) {
return i->second.steal(t);}
170 static const ChildType& stealChild(
const MapCIter& i,
const Tile& t) {
return i->second.steal(t);}
172 static bool isChild(
const MapCIter& i) {
return i->second.isChild(); }
173 static bool isChild(
const MapIter& i) {
return i->second.isChild(); }
174 static bool isTile(
const MapCIter& i) {
return i->second.isTile(); }
175 static bool isTile(
const MapIter& i) {
return i->second.isTile(); }
176 static bool isTileOff(
const MapCIter& i) {
return i->second.isTileOff(); }
177 static bool isTileOff(
const MapIter& i) {
return i->second.isTileOff(); }
178 static bool isTileOn(
const MapCIter& i) {
return i->second.isTileOn(); }
179 static bool isTileOn(
const MapIter& i) {
return i->second.isTileOn(); }
182 static inline bool test(
const MapIter&) {
return true; }
183 static inline bool test(
const MapCIter&) {
return true; }
186 static inline bool test(
const MapIter& i) {
return isTileOn(i); }
187 static inline bool test(
const MapCIter& i) {
return isTileOn(i); }
189 struct ValueOffPred {
190 static inline bool test(
const MapIter& i) {
return isTileOff(i); }
191 static inline bool test(
const MapCIter& i) {
return isTileOff(i); }
193 struct ValueAllPred {
194 static inline bool test(
const MapIter& i) {
return isTile(i); }
195 static inline bool test(
const MapCIter& i) {
return isTile(i); }
198 static inline bool test(
const MapIter& i) {
return isChild(i); }
199 static inline bool test(
const MapCIter& i) {
return isChild(i); }
201 struct ChildOffPred {
202 static inline bool test(
const MapIter& i) {
return isTile(i); }
203 static inline bool test(
const MapCIter& i) {
return isTile(i); }
206 template<
typename _RootNodeT,
typename _MapIterT,
typename FilterPredT>
210 using RootNodeT = _RootNodeT;
211 using MapIterT = _MapIterT;
215 return (mParentNode == other.mParentNode) && (mIter == other.mIter);
217 bool operator!=(
const BaseIter& other)
const {
return !(*
this == other); }
219 RootNodeT* getParentNode()
const {
return mParentNode; }
221 RootNodeT& parent()
const
223 if (!mParentNode)
OPENVDB_THROW(ValueError,
"iterator references a null parent node");
227 bool test()
const { assert(mParentNode);
return mIter != mParentNode->mTable.end(); }
228 operator bool()
const {
return this->test(); }
230 void increment() {
if (this->test()) { ++mIter; } this->skip(); }
231 bool next() { this->increment();
return this->test(); }
232 void increment(
Index n) {
for (
Index i = 0; i < n && this->next(); ++i) {} }
238 return !mParentNode ? 0U :
Index(std::distance(mParentNode->mTable.begin(), mIter));
241 bool isValueOn()
const {
return RootNodeT::isTileOn(mIter); }
242 bool isValueOff()
const {
return RootNodeT::isTileOff(mIter); }
243 void setValueOn(
bool on =
true)
const { mIter->second.tile.active = on; }
244 void setValueOff()
const { mIter->second.tile.active =
false; }
247 Coord getCoord()
const {
return mIter->first; }
249 void getCoord(Coord& xyz)
const { xyz = this->getCoord(); }
252 BaseIter(): mParentNode(nullptr) {}
253 BaseIter(RootNodeT& parent,
const MapIterT& iter): mParentNode(&parent), mIter(iter) {}
255 void skip() {
while (this->test() && !FilterPredT::test(mIter)) ++mIter; }
257 RootNodeT* mParentNode;
261 template<
typename RootNodeT,
typename MapIterT,
typename FilterPredT,
typename ChildNodeT>
262 class ChildIter:
public BaseIter<RootNodeT, MapIterT, FilterPredT>
265 using BaseT = BaseIter<RootNodeT, MapIterT, FilterPredT>;
266 using NodeType = RootNodeT;
267 using ValueType = NodeType;
268 using ChildNodeType = ChildNodeT;
269 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
270 using NonConstValueType =
typename std::remove_const<ValueType>::type;
271 using NonConstChildNodeType =
typename std::remove_const<ChildNodeType>::type;
275 ChildIter(RootNodeT& parent,
const MapIterT& iter): BaseT(parent, iter) { BaseT::skip(); }
277 ChildIter& operator++() { BaseT::increment();
return *
this; }
279 ChildNodeT& getValue()
const {
return getChild(mIter); }
280 ChildNodeT&
operator*()
const {
return this->getValue(); }
281 ChildNodeT* operator->()
const {
return &this->getValue(); }
284 template<
typename RootNodeT,
typename MapIterT,
typename FilterPredT,
typename ValueT>
285 class ValueIter:
public BaseIter<RootNodeT, MapIterT, FilterPredT>
288 using BaseT = BaseIter<RootNodeT, MapIterT, FilterPredT>;
289 using NodeType = RootNodeT;
290 using ValueType = ValueT;
291 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
292 using NonConstValueType =
typename std::remove_const<ValueT>::type;
296 ValueIter(RootNodeT& parent,
const MapIterT& iter): BaseT(parent, iter) { BaseT::skip(); }
298 ValueIter& operator++() { BaseT::increment();
return *
this; }
300 ValueT& getValue()
const {
return getTile(mIter).value; }
301 ValueT&
operator*()
const {
return this->getValue(); }
302 ValueT* operator->()
const {
return &(this->getValue()); }
304 void setValue(
const ValueT& v)
const { assert(isTile(mIter)); getTile(mIter).value = v; }
306 template<
typename ModifyOp>
307 void modifyValue(
const ModifyOp& op)
const
309 assert(isTile(mIter));
310 op(getTile(mIter).value);
314 template<
typename RootNodeT,
typename MapIterT,
typename ChildNodeT,
typename ValueT>
315 class DenseIter:
public BaseIter<RootNodeT, MapIterT, NullPred>
318 using BaseT = BaseIter<RootNodeT, MapIterT, NullPred>;
319 using NodeType = RootNodeT;
320 using ValueType = ValueT;
321 using ChildNodeType = ChildNodeT;
322 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
323 using NonConstValueType =
typename std::remove_const<ValueT>::type;
324 using NonConstChildNodeType =
typename std::remove_const<ChildNodeT>::type;
328 DenseIter(RootNodeT& parent,
const MapIterT& iter): BaseT(parent, iter) {}
330 DenseIter& operator++() { BaseT::increment();
return *
this; }
332 bool isChildNode()
const {
return isChild(mIter); }
334 ChildNodeT* probeChild(NonConstValueType& value)
const
336 if (isChild(mIter))
return &getChild(mIter);
337 value = getTile(mIter).value;
340 bool probeChild(ChildNodeT*& child, NonConstValueType& value)
const
342 child = this->probeChild(value);
343 return child !=
nullptr;
345 bool probeValue(NonConstValueType& value)
const {
return !this->probeChild(value); }
347 void setChild(ChildNodeT& c)
const { RootNodeT::setChild(mIter, c); }
348 void setChild(ChildNodeT* c)
const { assert(c !=
nullptr); RootNodeT::setChild(mIter, *c); }
349 void setValue(
const ValueT& v)
const
351 if (isTile(mIter)) getTile(mIter).value = v;
355 else stealChild(mIter, Tile(v,
true));
360 using ChildOnIter = ChildIter<RootNode, MapIter, ChildOnPred, ChildType>;
361 using ChildOnCIter = ChildIter<const RootNode, MapCIter, ChildOnPred, const ChildType>;
362 using ChildOffIter = ValueIter<RootNode, MapIter, ChildOffPred, const ValueType>;
363 using ChildOffCIter = ValueIter<const RootNode, MapCIter, ChildOffPred, ValueType>;
364 using ChildAllIter = DenseIter<RootNode, MapIter, ChildType, ValueType>;
365 using ChildAllCIter = DenseIter<const RootNode, MapCIter, const ChildType, const ValueType>;
367 using ValueOnIter = ValueIter<RootNode, MapIter, ValueOnPred, ValueType>;
368 using ValueOnCIter = ValueIter<const RootNode, MapCIter, ValueOnPred, const ValueType>;
369 using ValueOffIter = ValueIter<RootNode, MapIter, ValueOffPred, ValueType>;
370 using ValueOffCIter = ValueIter<const RootNode, MapCIter, ValueOffPred, const ValueType>;
371 using ValueAllIter = ValueIter<RootNode, MapIter, ValueAllPred, ValueType>;
372 using ValueAllCIter = ValueIter<const RootNode, MapCIter, ValueAllPred, const ValueType>;
403 void evalActiveBoundingBox(
CoordBBox& bbox,
bool visitVoxels =
true)
const;
420 void setBackground(
const ValueType& value,
bool updateChildNodes);
426 bool isBackgroundTile(
const Tile&)
const;
428 bool isBackgroundTile(
const MapIter&)
const;
430 bool isBackgroundTile(
const MapCIter&)
const;
434 size_t numBackgroundTiles()
const;
437 size_t eraseBackgroundTiles();
441 bool empty()
const {
return mTable.size() == numBackgroundTiles(); }
446 bool expand(
const Coord& xyz);
449 static void getNodeLog2Dims(std::vector<Index>& dims);
455 Index getWidth()
const {
return this->getMaxIndex()[0] - this->getMinIndex()[0]; }
456 Index getHeight()
const {
return this->getMaxIndex()[1] - this->getMinIndex()[1]; }
457 Index getDepth()
const {
return this->getMaxIndex()[2] - this->getMinIndex()[2]; }
460 Coord getMinIndex()
const;
462 Coord getMaxIndex()
const;
464 void getIndexRange(
CoordBBox& bbox)
const;
468 template<
typename OtherChildType>
472 template<
typename OtherChildType>
477 template<
typename OtherChildType>
485 Index64 onLeafVoxelCount()
const;
486 Index64 offLeafVoxelCount()
const;
488 void nodeCount(std::vector<Index32> &vec)
const;
490 bool isValueOn(
const Coord& xyz)
const;
493 bool hasActiveTiles()
const;
495 const ValueType& getValue(
const Coord& xyz)
const;
496 bool probeValue(
const Coord& xyz, ValueType& value)
const;
501 int getValueDepth(
const Coord& xyz)
const;
504 void setActiveState(
const Coord& xyz,
bool on);
506 void setValueOnly(
const Coord& xyz,
const ValueType& value);
508 void setValueOn(
const Coord& xyz,
const ValueType& value);
510 void setValueOff(
const Coord& xyz);
512 void setValueOff(
const Coord& xyz,
const ValueType& value);
516 template<
typename ModifyOp>
517 void modifyValue(
const Coord& xyz,
const ModifyOp& op);
519 template<
typename ModifyOp>
520 void modifyValueAndActiveState(
const Coord& xyz,
const ModifyOp& op);
523 void fill(
const CoordBBox& bbox,
const ValueType& value,
bool active =
true);
534 this->fill(bbox, value, active);
545 void denseFill(
const CoordBBox& bbox,
const ValueType& value,
bool active =
true);
555 void voxelizeActiveTiles(
bool threaded =
true);
562 template<
typename DenseT>
569 bool writeTopology(std::ostream&,
bool toHalf =
false)
const;
570 bool readTopology(std::istream&,
bool fromHalf =
false);
572 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
573 void readBuffers(std::istream&,
bool fromHalf =
false);
574 void readBuffers(std::istream&,
const CoordBBox&,
bool fromHalf =
false);
584 template<
typename AccessorT>
590 template<
typename AccessorT>
591 bool isValueOnAndCache(
const Coord& xyz, AccessorT&)
const;
597 template<
typename AccessorT>
598 void setValueAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
604 template<
typename AccessorT>
605 void setValueOnlyAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
612 template<
typename ModifyOp,
typename AccessorT>
613 void modifyValueAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
619 template<
typename ModifyOp,
typename AccessorT>
620 void modifyValueAndActiveStateAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
626 template<
typename AccessorT>
627 void setValueOffAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
633 template<
typename AccessorT>
634 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&);
641 template<
typename AccessorT>
642 bool probeValueAndCache(
const Coord& xyz,
ValueType& value, AccessorT&)
const;
649 template<
typename AccessorT>
650 int getValueDepthAndCache(
const Coord& xyz, AccessorT&)
const;
668 template<
typename AccessorT>
679 template<
typename NodeT>
680 NodeT* stealNode(
const Coord& xyz,
const ValueType& value,
bool state);
687 bool addChild(ChildType* child);
691 void addTile(
const Coord& xyz,
const ValueType& value,
bool state);
700 template<
typename AccessorT>
701 void addTileAndCache(
Index level,
const Coord& xyz,
const ValueType&,
bool state, AccessorT&);
712 template<
typename AccessorT>
716 template <
typename NodeT>
719 NodeT* probeNode(
const Coord& xyz);
720 template <
typename NodeT>
721 const NodeT* probeConstNode(
const Coord& xyz)
const;
725 template<
typename NodeT,
typename AccessorT>
728 NodeT* probeNodeAndCache(
const Coord& xyz, AccessorT& acc);
729 template<
typename NodeT,
typename AccessorT>
730 const NodeT* probeConstNodeAndCache(
const Coord& xyz, AccessorT& acc)
const;
742 template<
typename AccessorT>
746 template<
typename AccessorT>
748 template<
typename AccessorT>
758 template<
typename ArrayT>
void getNodes(ArrayT& array);
781 template<
typename ArrayT>
void getNodes(ArrayT& array)
const;
785 template<
typename ArrayT>
809 void stealNodes(ArrayT& array,
const ValueType& value,
bool state);
810 template<
typename ArrayT>
821 template<MergePolicy Policy>
void merge(
RootNode& other);
836 template<
typename OtherChildType>
852 template<
typename OtherChildType>
865 template<
typename OtherChildType>
868 template<
typename CombineOp>
871 template<
typename CombineOp,
typename OtherRootNode >
872 void combine2(
const RootNode& other0,
const OtherRootNode& other1,
873 CombineOp& op,
bool prune =
false);
880 template<
typename BBoxOp>
void visitActiveBBox(BBoxOp&)
const;
882 template<
typename VisitorOp>
void visit(VisitorOp&);
883 template<
typename VisitorOp>
void visit(VisitorOp&)
const;
885 template<
typename OtherRootNodeType,
typename VisitorOp>
886 void visit2(OtherRootNodeType& other, VisitorOp&);
887 template<
typename OtherRootNodeType,
typename VisitorOp>
888 void visit2(OtherRootNodeType& other, VisitorOp&)
const;
901 void resetTable(MapType& table) { mTable.swap(table); table.clear(); }
903 void resetTable(
const MapType&)
const {}
906 #if OPENVDB_ABI_VERSION_NUMBER < 8
907 Index getChildCount()
const;
909 Index getTileCount()
const;
910 Index getActiveTileCount()
const;
911 Index getInactiveTileCount()
const;
914 static Coord coordToKey(
const Coord& xyz) {
return xyz & ~(ChildType::DIM - 1); }
917 void insertKeys(CoordSet&)
const;
920 bool hasKey(
const Coord& key)
const {
return mTable.find(key) != mTable.end(); }
922 MapIter findKey(
const Coord& key) {
return mTable.find(key); }
925 MapCIter findKey(
const Coord& key)
const {
return mTable.find(key); }
928 MapIter findCoord(
const Coord& xyz) {
return mTable.find(coordToKey(xyz)); }
931 MapCIter findCoord(
const Coord& xyz)
const {
return mTable.find(coordToKey(xyz)); }
933 MapIter findOrAddCoord(
const Coord& xyz);
942 template<
typename OtherChildType>
943 static void enforceSameConfiguration(
const RootNode<OtherChildType>& other);
950 template<
typename OtherChildType>
951 static void enforceCompatibleValueTypes(
const RootNode<OtherChildType>& other);
953 template<
typename CombineOp,
typename OtherRootNode >
954 void doCombine2(
const RootNode&,
const OtherRootNode&, CombineOp&,
bool prune);
956 template<
typename RootNodeT,
typename VisitorOp,
typename ChildAllIterT>
957 static inline void doVisit(RootNodeT&, VisitorOp&);
959 template<
typename RootNodeT,
typename OtherRootNodeT,
typename VisitorOp,
960 typename ChildAllIterT,
typename OtherChildAllIterT>
961 static inline void doVisit2(RootNodeT&, OtherRootNodeT&, VisitorOp&);
965 ValueType mBackground;
992 template<
typename HeadT,
int HeadLevel>
995 using Type =
typename SubtreeT::template Append<HeadT>;
999 template<
typename HeadT>
1009 template<
typename ChildT1,
typename NodeT2>
1013 static const bool value =
false;
1016 template<
typename ChildT1,
typename ChildT2>
1018 static const bool value = ChildT1::template SameConfiguration<ChildT2>::value;
1026 template<
typename ChildT>
1034 template<
typename ChildT>
1042 template<
typename ChildT>
1043 template<
typename OtherChildType>
1051 enforceSameConfiguration(other);
1053 const Tile bgTile(backgd,
false), fgTile(foregd,
true);
1056 for (
typename OtherRootT::MapCIter i=other.mTable.begin(), e=other.mTable.end(); i != e; ++i) {
1057 mTable[i->first] = OtherRootT::isTile(i)
1058 ? NodeStruct(OtherRootT::isTileOn(i) ? fgTile : bgTile)
1059 : NodeStruct(*(
new ChildT(OtherRootT::getChild(i), backgd, foregd,
TopologyCopy())));
1064 template<
typename ChildT>
1065 template<
typename OtherChildType>
1073 enforceSameConfiguration(other);
1075 const Tile bgTile(backgd,
false), fgTile(backgd,
true);
1077 for (
typename OtherRootT::MapCIter i=other.mTable.begin(), e=other.mTable.end(); i != e; ++i) {
1078 mTable[i->first] = OtherRootT::isTile(i)
1079 ? NodeStruct(OtherRootT::isTileOn(i) ? fgTile : bgTile)
1080 : NodeStruct(*(
new ChildT(OtherRootT::getChild(i), backgd,
TopologyCopy())));
1091 template<
typename RootT,
typename OtherRootT,
bool Compatible = false>
1098 self.enforceSameConfiguration(other);
1099 self.enforceCompatibleValueTypes(other);
1101 std::ostringstream ostr;
1102 ostr <<
"cannot convert a " <<
typeid(OtherRootT).name()
1103 <<
" to a " <<
typeid(RootT).name();
1109 template<
typename RootT,
typename OtherRootT>
1114 using ValueT =
typename RootT::ValueType;
1115 using ChildT =
typename RootT::ChildNodeType;
1116 using NodeStruct =
typename RootT::NodeStruct;
1117 using Tile =
typename RootT::Tile;
1118 using OtherValueT =
typename OtherRootT::ValueType;
1119 using OtherMapCIter =
typename OtherRootT::MapCIter;
1120 using OtherTile =
typename OtherRootT::Tile;
1124 static inline ValueT convertValue(
const OtherValueT& val) {
return ValueT(val); }
1127 self.mBackground = Local::convertValue(other.mBackground);
1132 for (OtherMapCIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
1133 if (other.isTile(i)) {
1135 const OtherTile& otherTile = other.getTile(i);
1136 self.mTable[i->first] = NodeStruct(
1137 Tile(Local::convertValue(otherTile.value), otherTile.active));
1140 self.mTable[i->first] = NodeStruct(*(
new ChildT(other.getChild(i))));
1148 template<
typename ChildT>
1149 inline RootNode<ChildT>&
1152 if (&other !=
this) {
1153 mBackground = other.mBackground;
1158 for (MapCIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
1160 isTile(i) ? NodeStruct(getTile(i)) : NodeStruct(*(
new ChildT(getChild(i))));
1167 template<
typename ChildT>
1168 template<
typename OtherChildType>
1173 using OtherValueT =
typename OtherRootT::ValueType;
1183 template<
typename ChildT>
1189 if (updateChildNodes) {
1192 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1193 ChildT *child = iter->second.child;
1195 child->resetBackground(mBackground, background);
1197 Tile& tile = getTile(iter);
1198 if (tile.active)
continue;
1200 tile.value = background;
1207 mBackground = background;
1210 template<
typename ChildT>
1217 template<
typename ChildT>
1224 template<
typename ChildT>
1232 template<
typename ChildT>
1237 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1238 if (this->isBackgroundTile(i)) ++count;
1244 template<
typename ChildT>
1248 std::set<Coord> keysToErase;
1249 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1250 if (this->isBackgroundTile(i)) keysToErase.insert(i->first);
1252 for (std::set<Coord>::iterator i = keysToErase.begin(), e = keysToErase.end(); i != e; ++i) {
1255 return keysToErase.size();
1262 template<
typename ChildT>
1266 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1267 keys.insert(i->first);
1272 template<
typename ChildT>
1273 inline typename RootNode<ChildT>::MapIter
1274 RootNode<ChildT>::findOrAddCoord(
const Coord& xyz)
1276 const Coord key = coordToKey(xyz);
1277 std::pair<MapIter, bool> result = mTable.insert(
1278 typename MapType::value_type(key, NodeStruct(Tile(mBackground,
false))));
1279 return result.first;
1283 template<
typename ChildT>
1287 const Coord key = coordToKey(xyz);
1288 std::pair<MapIter, bool> result = mTable.insert(
1289 typename MapType::value_type(key, NodeStruct(Tile(mBackground,
false))));
1290 return result.second;
1297 template<
typename ChildT>
1302 ChildT::getNodeLog2Dims(dims);
1306 template<
typename ChildT>
1310 return mTable.empty() ?
Coord(0) : mTable.begin()->first;
1313 template<
typename ChildT>
1317 return mTable.empty() ?
Coord(0) : mTable.rbegin()->first +
Coord(ChildT::DIM - 1);
1321 template<
typename ChildT>
1325 bbox.
min() = this->getMinIndex();
1326 bbox.
max() = this->getMaxIndex();
1333 template<
typename ChildT>
1334 template<
typename OtherChildType>
1339 using OtherMapT =
typename OtherRootT::MapType;
1340 using OtherIterT =
typename OtherRootT::MapIter;
1341 using OtherCIterT =
typename OtherRootT::MapCIter;
1343 if (!hasSameConfiguration(other))
return false;
1346 OtherMapT copyOfOtherTable = other.mTable;
1349 for (MapCIter thisIter = mTable.begin(); thisIter != mTable.end(); ++thisIter) {
1350 if (this->isBackgroundTile(thisIter))
continue;
1353 OtherCIterT otherIter = other.findKey(thisIter->first);
1354 if (otherIter == other.mTable.end())
return false;
1357 if (isChild(thisIter)) {
1358 if (OtherRootT::isTile(otherIter))
return false;
1360 if (!getChild(thisIter).hasSameTopology(&OtherRootT::getChild(otherIter)))
return false;
1362 if (OtherRootT::isChild(otherIter))
return false;
1363 if (getTile(thisIter).active != OtherRootT::getTile(otherIter).active)
return false;
1370 copyOfOtherTable.erase(otherIter->first);
1373 for (OtherIterT i = copyOfOtherTable.begin(), e = copyOfOtherTable.end(); i != e; ++i) {
1380 template<
typename ChildT>
1381 template<
typename OtherChildType>
1385 std::vector<Index> thisDims, otherDims;
1388 return (thisDims == otherDims);
1392 template<
typename ChildT>
1393 template<
typename OtherChildType>
1397 std::vector<Index> thisDims, otherDims;
1400 if (thisDims != otherDims) {
1401 std::ostringstream ostr;
1402 ostr <<
"grids have incompatible configurations (" << thisDims[0];
1403 for (
size_t i = 1, N = thisDims.size(); i < N; ++i) ostr <<
" x " << thisDims[i];
1404 ostr <<
" vs. " << otherDims[0];
1405 for (
size_t i = 1, N = otherDims.size(); i < N; ++i) ostr <<
" x " << otherDims[i];
1412 template<
typename ChildT>
1413 template<
typename OtherChildType>
1417 using OtherValueType =
typename OtherChildType::ValueType;
1422 template<
typename ChildT>
1423 template<
typename OtherChildType>
1427 using OtherValueType =
typename OtherChildType::ValueType;
1429 std::ostringstream ostr;
1430 ostr <<
"values of type " << typeNameAsString<OtherValueType>()
1431 <<
" cannot be converted to type " << typeNameAsString<ValueType>();
1440 template<
typename ChildT>
1445 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1446 if (
const ChildT *child = iter->second.child) {
1447 sum += child->memUsage();
1454 template<
typename ChildT>
1458 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1459 delete i->second.child;
1465 template<
typename ChildT>
1469 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1470 if (
const ChildT *child = iter->second.child) {
1471 child->evalActiveBoundingBox(bbox, visitVoxels);
1472 }
else if (isTileOn(iter)) {
1473 bbox.
expand(iter->first, ChildT::DIM);
1479 #if OPENVDB_ABI_VERSION_NUMBER < 8
1480 template<
typename ChildT>
1483 return this->childCount();
1488 template<
typename ChildT>
1490 RootNode<ChildT>::getTileCount()
const
1493 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1494 if (isTile(i)) ++sum;
1500 template<
typename ChildT>
1502 RootNode<ChildT>::getActiveTileCount()
const
1505 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1506 if (isTileOn(i)) ++sum;
1512 template<
typename ChildT>
1514 RootNode<ChildT>::getInactiveTileCount()
const
1517 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1518 if (isTileOff(i)) ++sum;
1524 template<
typename ChildT>
1529 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1530 if (isChild(i)) sum += getChild(i).leafCount();
1536 template<
typename ChildT>
1541 if (ChildT::LEVEL != 0) {
1542 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1543 if (isChild(i)) sum += getChild(i).nonLeafCount();
1550 template<
typename ChildT>
1555 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1556 if (isChild(i)) ++sum;
1562 template<
typename ChildT>
1567 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1569 sum += getChild(i).onVoxelCount();
1570 }
else if (isTileOn(i)) {
1571 sum += ChildT::NUM_VOXELS;
1578 template<
typename ChildT>
1583 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1585 sum += getChild(i).offVoxelCount();
1586 }
else if (isTileOff(i) && !this->isBackgroundTile(i)) {
1587 sum += ChildT::NUM_VOXELS;
1594 template<
typename ChildT>
1599 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1600 if (isChild(i)) sum += getChild(i).onLeafVoxelCount();
1606 template<
typename ChildT>
1611 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1612 if (isChild(i)) sum += getChild(i).offLeafVoxelCount();
1617 template<
typename ChildT>
1622 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1624 sum += getChild(i).onTileCount();
1625 }
else if (isTileOn(i)) {
1632 template<
typename ChildT>
1636 assert(vec.size() > LEVEL);
1638 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1641 getChild(i).nodeCount(vec);
1645 vec[ChildNodeType::LEVEL] = sum;
1651 template<
typename ChildT>
1655 MapCIter iter = this->findCoord(xyz);
1656 if (iter == mTable.end() || isTileOff(iter))
return false;
1657 return isTileOn(iter) ? true : getChild(iter).isValueOn(xyz);
1660 template<
typename ChildT>
1664 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1665 if (isChild(i) ? getChild(i).hasActiveTiles() : getTile(i).active)
return true;
1670 template<
typename ChildT>
1671 template<
typename AccessorT>
1675 MapCIter iter = this->findCoord(xyz);
1676 if (iter == mTable.end() || isTileOff(iter))
return false;
1677 if (isTileOn(iter))
return true;
1678 acc.insert(xyz, &getChild(iter));
1679 return getChild(iter).isValueOnAndCache(xyz, acc);
1683 template<
typename ChildT>
1684 inline const typename ChildT::ValueType&
1687 MapCIter iter = this->findCoord(xyz);
1688 return iter == mTable.end() ? mBackground
1689 : (isTile(iter) ? getTile(iter).value : getChild(iter).getValue(xyz));
1692 template<
typename ChildT>
1693 template<
typename AccessorT>
1694 inline const typename ChildT::ValueType&
1697 MapCIter iter = this->findCoord(xyz);
1698 if (iter == mTable.end())
return mBackground;
1699 if (isChild(iter)) {
1700 acc.insert(xyz, &getChild(iter));
1701 return getChild(iter).getValueAndCache(xyz, acc);
1703 return getTile(iter).value;
1707 template<
typename ChildT>
1711 MapCIter iter = this->findCoord(xyz);
1712 return iter == mTable.end() ? -1
1713 : (isTile(iter) ? 0 : int(LEVEL) - int(getChild(iter).getValueLevel(xyz)));
1716 template<
typename ChildT>
1717 template<
typename AccessorT>
1721 MapCIter iter = this->findCoord(xyz);
1722 if (iter == mTable.end())
return -1;
1723 if (isTile(iter))
return 0;
1724 acc.insert(xyz, &getChild(iter));
1725 return int(LEVEL) - int(getChild(iter).getValueLevelAndCache(xyz, acc));
1729 template<
typename ChildT>
1733 MapIter iter = this->findCoord(xyz);
1734 if (iter != mTable.end() && !isTileOff(iter)) {
1735 if (isTileOn(iter)) {
1736 setChild(iter, *
new ChildT(xyz, getTile(iter).value,
true));
1738 getChild(iter).setValueOff(xyz);
1743 template<
typename ChildT>
1747 ChildT* child =
nullptr;
1748 MapIter iter = this->findCoord(xyz);
1749 if (iter == mTable.end()) {
1751 child =
new ChildT(xyz, mBackground);
1752 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1756 }
else if (isChild(iter)) {
1757 child = &getChild(iter);
1758 }
else if (on != getTile(iter).active) {
1759 child =
new ChildT(xyz, getTile(iter).value, !on);
1760 setChild(iter, *child);
1762 if (child) child->setActiveState(xyz, on);
1765 template<
typename ChildT>
1766 template<
typename AccessorT>
1770 ChildT* child =
nullptr;
1771 MapIter iter = this->findCoord(xyz);
1772 if (iter == mTable.end()) {
1774 child =
new ChildT(xyz, mBackground);
1775 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1779 }
else if (isChild(iter)) {
1780 child = &getChild(iter);
1781 }
else if (on != getTile(iter).active) {
1782 child =
new ChildT(xyz, getTile(iter).value, !on);
1783 setChild(iter, *child);
1786 acc.insert(xyz, child);
1787 child->setActiveStateAndCache(xyz, on, acc);
1792 template<
typename ChildT>
1796 ChildT* child =
nullptr;
1797 MapIter iter = this->findCoord(xyz);
1798 if (iter == mTable.end()) {
1800 child =
new ChildT(xyz, mBackground);
1801 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1803 }
else if (isChild(iter)) {
1804 child = &getChild(iter);
1806 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1807 setChild(iter, *child);
1809 if (child) child->setValueOff(xyz, value);
1812 template<
typename ChildT>
1813 template<
typename AccessorT>
1817 ChildT* child =
nullptr;
1818 MapIter iter = this->findCoord(xyz);
1819 if (iter == mTable.end()) {
1821 child =
new ChildT(xyz, mBackground);
1822 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1824 }
else if (isChild(iter)) {
1825 child = &getChild(iter);
1827 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1828 setChild(iter, *child);
1831 acc.insert(xyz, child);
1832 child->setValueOffAndCache(xyz, value, acc);
1837 template<
typename ChildT>
1841 ChildT* child =
nullptr;
1842 MapIter iter = this->findCoord(xyz);
1843 if (iter == mTable.end()) {
1844 child =
new ChildT(xyz, mBackground);
1845 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1846 }
else if (isChild(iter)) {
1847 child = &getChild(iter);
1849 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1850 setChild(iter, *child);
1852 if (child) child->setValueOn(xyz, value);
1855 template<
typename ChildT>
1856 template<
typename AccessorT>
1860 ChildT* child =
nullptr;
1861 MapIter iter = this->findCoord(xyz);
1862 if (iter == mTable.end()) {
1863 child =
new ChildT(xyz, mBackground);
1864 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1865 }
else if (isChild(iter)) {
1866 child = &getChild(iter);
1868 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1869 setChild(iter, *child);
1872 acc.insert(xyz, child);
1873 child->setValueAndCache(xyz, value, acc);
1878 template<
typename ChildT>
1882 ChildT* child =
nullptr;
1883 MapIter iter = this->findCoord(xyz);
1884 if (iter == mTable.end()) {
1885 child =
new ChildT(xyz, mBackground);
1886 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1887 }
else if (isChild(iter)) {
1888 child = &getChild(iter);
1890 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1891 setChild(iter, *child);
1893 if (child) child->setValueOnly(xyz, value);
1896 template<
typename ChildT>
1897 template<
typename AccessorT>
1901 ChildT* child =
nullptr;
1902 MapIter iter = this->findCoord(xyz);
1903 if (iter == mTable.end()) {
1904 child =
new ChildT(xyz, mBackground);
1905 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1906 }
else if (isChild(iter)) {
1907 child = &getChild(iter);
1909 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1910 setChild(iter, *child);
1913 acc.insert(xyz, child);
1914 child->setValueOnlyAndCache(xyz, value, acc);
1919 template<
typename ChildT>
1920 template<
typename ModifyOp>
1924 ChildT* child =
nullptr;
1925 MapIter iter = this->findCoord(xyz);
1926 if (iter == mTable.end()) {
1927 child =
new ChildT(xyz, mBackground);
1928 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1929 }
else if (isChild(iter)) {
1930 child = &getChild(iter);
1934 bool createChild = isTileOff(iter);
1938 const ValueType& tileVal = getTile(iter).value;
1944 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1945 setChild(iter, *child);
1948 if (child) child->modifyValue(xyz, op);
1951 template<
typename ChildT>
1952 template<
typename ModifyOp,
typename AccessorT>
1956 ChildT* child =
nullptr;
1957 MapIter iter = this->findCoord(xyz);
1958 if (iter == mTable.end()) {
1959 child =
new ChildT(xyz, mBackground);
1960 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1961 }
else if (isChild(iter)) {
1962 child = &getChild(iter);
1966 bool createChild = isTileOff(iter);
1970 const ValueType& tileVal = getTile(iter).value;
1976 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1977 setChild(iter, *child);
1981 acc.insert(xyz, child);
1982 child->modifyValueAndCache(xyz, op, acc);
1987 template<
typename ChildT>
1988 template<
typename ModifyOp>
1992 ChildT* child =
nullptr;
1993 MapIter iter = this->findCoord(xyz);
1994 if (iter == mTable.end()) {
1995 child =
new ChildT(xyz, mBackground);
1996 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1997 }
else if (isChild(iter)) {
1998 child = &getChild(iter);
2000 const Tile& tile = getTile(iter);
2001 bool modifiedState = tile.active;
2003 op(modifiedVal, modifiedState);
2007 child =
new ChildT(xyz, tile.value, tile.active);
2008 setChild(iter, *child);
2011 if (child) child->modifyValueAndActiveState(xyz, op);
2014 template<
typename ChildT>
2015 template<
typename ModifyOp,
typename AccessorT>
2018 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
2020 ChildT* child =
nullptr;
2021 MapIter iter = this->findCoord(xyz);
2022 if (iter == mTable.end()) {
2023 child =
new ChildT(xyz, mBackground);
2024 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2025 }
else if (isChild(iter)) {
2026 child = &getChild(iter);
2028 const Tile& tile = getTile(iter);
2029 bool modifiedState = tile.active;
2031 op(modifiedVal, modifiedState);
2035 child =
new ChildT(xyz, tile.value, tile.active);
2036 setChild(iter, *child);
2040 acc.insert(xyz, child);
2041 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
2046 template<
typename ChildT>
2050 MapCIter iter = this->findCoord(xyz);
2051 if (iter == mTable.end()) {
2052 value = mBackground;
2054 }
else if (isChild(iter)) {
2055 return getChild(iter).probeValue(xyz, value);
2057 value = getTile(iter).value;
2058 return isTileOn(iter);
2061 template<
typename ChildT>
2062 template<
typename AccessorT>
2066 MapCIter iter = this->findCoord(xyz);
2067 if (iter == mTable.end()) {
2068 value = mBackground;
2070 }
else if (isChild(iter)) {
2071 acc.insert(xyz, &getChild(iter));
2072 return getChild(iter).probeValueAndCache(xyz, value, acc);
2074 value = getTile(iter).value;
2075 return isTileOn(iter);
2082 template<
typename ChildT>
2086 if (bbox.
empty())
return;
2091 for (
int x = bbox.
min().
x(); x <= bbox.
max().
x(); x = tileMax.
x() + 1) {
2093 for (
int y = bbox.
min().
y(); y <= bbox.
max().
y(); y = tileMax.
y() + 1) {
2095 for (
int z = bbox.
min().
z(); z <= bbox.
max().
z(); z = tileMax.
z() + 1) {
2099 Coord tileMin = coordToKey(xyz);
2100 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2106 ChildT* child =
nullptr;
2107 MapIter iter = this->findKey(tileMin);
2108 if (iter == mTable.end()) {
2111 child =
new ChildT(xyz, mBackground);
2112 mTable[tileMin] = NodeStruct(*child);
2113 }
else if (isTile(iter)) {
2116 const Tile& tile = getTile(iter);
2117 child =
new ChildT(xyz, tile.value, tile.active);
2118 mTable[tileMin] = NodeStruct(*child);
2119 }
else if (isChild(iter)) {
2120 child = &getChild(iter);
2125 child->fill(
CoordBBox(xyz, tmp), value, active);
2131 MapIter iter = this->findOrAddCoord(tileMin);
2132 setTile(iter, Tile(value, active));
2140 template<
typename ChildT>
2144 if (bbox.
empty())
return;
2146 if (active && mTable.empty()) {
2149 sparseFill(bbox, value, active);
2150 voxelizeActiveTiles(
true);
2156 Coord xyz, tileMin, tileMax;
2157 for (
int x = bbox.
min().
x(); x <= bbox.
max().
x(); x = tileMax.
x() + 1) {
2159 for (
int y = bbox.
min().
y(); y <= bbox.
max().
y(); y = tileMax.
y() + 1) {
2161 for (
int z = bbox.
min().
z(); z <= bbox.
max().
z(); z = tileMax.
z() + 1) {
2165 tileMin = coordToKey(xyz);
2166 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2170 const auto iter = findOrAddCoord(tileMin);
2175 const auto& tile = getTile(iter);
2176 auto* child =
new ChildT{tileMin, tile.value, tile.active};
2177 setChild(iter, *child);
2180 getChild(iter).denseFill(bbox, value, active);
2190 template<
typename ChildT>
2198 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2199 if (this->isTileOff(i))
continue;
2200 ChildT* child = i->second.child;
2201 if (child ==
nullptr) {
2204 child =
new ChildT{i->first, this->getTile(i).value,
true};
2205 i->second.child = child;
2207 child->voxelizeActiveTiles(threaded);
2215 template<
typename ChildT>
2216 template<
typename DenseT>
2220 using DenseValueType =
typename DenseT::ValueType;
2222 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2223 const Coord&
min = dense.bbox().min();
2225 for (
Coord xyz = bbox.
min(); xyz[0] <= bbox.
max()[0]; xyz[0] = nodeBBox.
max()[0] + 1) {
2226 for (xyz[1] = bbox.
min()[1]; xyz[1] <= bbox.
max()[1]; xyz[1] = nodeBBox.
max()[1] + 1) {
2227 for (xyz[2] = bbox.
min()[2]; xyz[2] <= bbox.
max()[2]; xyz[2] = nodeBBox.
max()[2] + 1) {
2235 MapCIter iter = this->findKey(nodeBBox.
min());
2236 if (iter != mTable.end() && isChild(iter)) {
2237 getChild(iter).copyToDense(sub, dense);
2239 const ValueType value = iter==mTable.end() ? mBackground : getTile(iter).value;
2241 DenseValueType* a0 = dense.data() + zStride*sub.
min()[2];
2242 for (
Int32 x=sub.
min()[0], ex=sub.
max()[0]+1; x<ex; ++x) {
2243 DenseValueType* a1 = a0 + x*xStride;
2244 for (
Int32 y=sub.
min()[1], ey=sub.
max()[1]+1; y<ey; ++y) {
2245 DenseValueType* a2 = a1 + y*yStride;
2246 for (
Int32 z=sub.
min()[2], ez=sub.
max()[2]+1; z<ez; ++z, a2 += zStride) {
2247 *a2 = DenseValueType(value);
2260 template<
typename ChildT>
2265 os.write(
reinterpret_cast<const char*
>(&mBackground),
sizeof(
ValueType));
2268 os.write(
reinterpret_cast<const char*
>(&truncatedVal),
sizeof(
ValueType));
2272 const Index numTiles = this->getTileCount(), numChildren = this->childCount();
2273 os.write(
reinterpret_cast<const char*
>(&numTiles),
sizeof(
Index));
2274 os.write(
reinterpret_cast<const char*
>(&numChildren),
sizeof(
Index));
2276 if (numTiles == 0 && numChildren == 0)
return false;
2279 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2280 if (isChild(i))
continue;
2281 os.write(
reinterpret_cast<const char*
>(i->first.asPointer()), 3 *
sizeof(
Int32));
2282 os.write(
reinterpret_cast<const char*
>(&getTile(i).value),
sizeof(
ValueType));
2283 os.write(
reinterpret_cast<const char*
>(&getTile(i).active),
sizeof(
bool));
2286 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2287 if (isTile(i))
continue;
2288 os.write(
reinterpret_cast<const char*
>(i->first.asPointer()), 3 *
sizeof(
Int32));
2289 getChild(i).writeTopology(os, toHalf);
2296 template<
typename ChildT>
2308 is.read(
reinterpret_cast<char*
>(&mBackground),
sizeof(
ValueType));
2310 is.read(
reinterpret_cast<char*
>(&inside),
sizeof(
ValueType));
2315 Coord rangeMin, rangeMax;
2317 is.read(
reinterpret_cast<char*
>(rangeMax.
asPointer()), 3 *
sizeof(
Int32));
2320 Index tableSize = 0, log2Dim[4] = { 0, 0, 0, 0 };
2322 for (
int i = 0; i < 3; ++i) {
2323 offset[i] = rangeMin[i] >> ChildT::TOTAL;
2324 rangeMin[i] = offset[i] << ChildT::TOTAL;
2326 tableSize += log2Dim[i];
2327 rangeMax[i] = (((1 << log2Dim[i]) + offset[i]) << ChildT::TOTAL) - 1;
2329 log2Dim[3] = log2Dim[1] + log2Dim[2];
2330 tableSize = 1U << tableSize;
2338 for (
Index i = 0; i < tableSize; ++i) {
2342 origin[0] = (n >> log2Dim[3]) + offset[0];
2343 n &= (1U << log2Dim[3]) - 1;
2344 origin[1] = (n >> log2Dim[2]) + offset[1];
2345 origin[2] = (n & ((1U << log2Dim[2]) - 1)) + offset[1];
2346 origin <<= ChildT::TOTAL;
2348 if (childMask.isOn(i)) {
2350 ChildT* child =
new ChildT(
PartialCreate(), origin, mBackground);
2351 child->readTopology(is);
2352 mTable[origin] = NodeStruct(*child);
2357 is.read(
reinterpret_cast<char*
>(&value),
sizeof(
ValueType));
2359 mTable[origin] = NodeStruct(Tile(value, valueMask.
isOn(i)));
2368 is.read(
reinterpret_cast<char*
>(&mBackground),
sizeof(
ValueType));
2371 Index numTiles = 0, numChildren = 0;
2372 is.read(
reinterpret_cast<char*
>(&numTiles),
sizeof(
Index));
2373 is.read(
reinterpret_cast<char*
>(&numChildren),
sizeof(
Index));
2375 if (numTiles == 0 && numChildren == 0)
return false;
2382 for (
Index n = 0; n < numTiles; ++n) {
2383 is.read(
reinterpret_cast<char*
>(vec), 3 *
sizeof(
Int32));
2384 is.read(
reinterpret_cast<char*
>(&value),
sizeof(
ValueType));
2385 is.read(
reinterpret_cast<char*
>(&active),
sizeof(
bool));
2386 mTable[
Coord(vec)] = NodeStruct(Tile(value, active));
2390 for (
Index n = 0; n < numChildren; ++n) {
2391 is.read(
reinterpret_cast<char*
>(vec), 3 *
sizeof(
Int32));
2393 ChildT* child =
new ChildT(
PartialCreate(), origin, mBackground);
2394 child->readTopology(is, fromHalf);
2395 mTable[
Coord(vec)] = NodeStruct(*child);
2402 template<
typename ChildT>
2406 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2407 if (isChild(i)) getChild(i).writeBuffers(os, toHalf);
2412 template<
typename ChildT>
2416 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2417 if (isChild(i)) getChild(i).readBuffers(is, fromHalf);
2422 template<
typename ChildT>
2426 const Tile bgTile(mBackground,
false);
2428 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2434 ChildT& child = getChild(i);
2435 child.readBuffers(is, clipBBox, fromHalf);
2439 this->
clip(clipBBox);
2446 template<
typename ChildT>
2450 const Tile bgTile(mBackground,
false);
2454 MapType copyOfTable(mTable);
2455 for (MapIter i = copyOfTable.begin(), e = copyOfTable.end(); i != e; ++i) {
2456 const Coord& xyz = i->first;
2460 setTile(this->findCoord(xyz), bgTile);
2462 }
else if (!clipBBox.
isInside(tileBBox)) {
2466 getChild(i).clip(clipBBox, mBackground);
2471 const Tile& origTile = getTile(i);
2472 setTile(this->findCoord(xyz), bgTile);
2473 this->sparseFill(tileBBox, origTile.value, origTile.active);
2486 template<
typename ChildT>
2492 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2493 if (this->isTile(i))
continue;
2494 this->getChild(i).prune(tolerance);
2495 if (this->getChild(i).isConstant(value, state, tolerance)) {
2496 this->setTile(i, Tile(value, state));
2499 this->eraseBackgroundTiles();
2506 template<
typename ChildT>
2507 template<
typename NodeT>
2511 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2512 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2514 MapIter iter = this->findCoord(xyz);
2515 if (iter == mTable.end() || isTile(iter))
return nullptr;
2516 return (std::is_same<NodeT, ChildT>::value)
2517 ?
reinterpret_cast<NodeT*
>(&stealChild(iter, Tile(value, state)))
2518 : getChild(iter).template stealNode<NodeT>(xyz, value, state);
2526 template<
typename ChildT>
2530 if (leaf ==
nullptr)
return;
2531 ChildT* child =
nullptr;
2532 const Coord& xyz = leaf->origin();
2533 MapIter iter = this->findCoord(xyz);
2534 if (iter == mTable.end()) {
2535 if (ChildT::LEVEL>0) {
2536 child =
new ChildT(xyz, mBackground,
false);
2538 child =
reinterpret_cast<ChildT*
>(leaf);
2540 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2541 }
else if (isChild(iter)) {
2542 if (ChildT::LEVEL>0) {
2543 child = &getChild(iter);
2545 child =
reinterpret_cast<ChildT*
>(leaf);
2546 setChild(iter, *child);
2549 if (ChildT::LEVEL>0) {
2550 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2552 child =
reinterpret_cast<ChildT*
>(leaf);
2554 setChild(iter, *child);
2556 child->addLeaf(leaf);
2560 template<
typename ChildT>
2561 template<
typename AccessorT>
2565 if (leaf ==
nullptr)
return;
2566 ChildT* child =
nullptr;
2567 const Coord& xyz = leaf->origin();
2568 MapIter iter = this->findCoord(xyz);
2569 if (iter == mTable.end()) {
2570 if (ChildT::LEVEL>0) {
2571 child =
new ChildT(xyz, mBackground,
false);
2573 child =
reinterpret_cast<ChildT*
>(leaf);
2575 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2576 }
else if (isChild(iter)) {
2577 if (ChildT::LEVEL>0) {
2578 child = &getChild(iter);
2580 child =
reinterpret_cast<ChildT*
>(leaf);
2581 setChild(iter, *child);
2584 if (ChildT::LEVEL>0) {
2585 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2587 child =
reinterpret_cast<ChildT*
>(leaf);
2589 setChild(iter, *child);
2591 acc.insert(xyz, child);
2592 child->addLeafAndCache(leaf, acc);
2595 template<
typename ChildT>
2599 if (!child)
return false;
2600 const Coord& xyz = child->origin();
2601 MapIter iter = this->findCoord(xyz);
2602 if (iter == mTable.end()) {
2603 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2605 setChild(iter, *child);
2610 template<
typename ChildT>
2614 MapIter iter = this->findCoord(xyz);
2615 if (iter == mTable.end()) {
2616 mTable[this->coordToKey(xyz)] = NodeStruct(Tile(value, state));
2618 setTile(iter, Tile(value, state));
2622 template<
typename ChildT>
2627 if (LEVEL >= level) {
2628 MapIter iter = this->findCoord(xyz);
2629 if (iter == mTable.end()) {
2630 if (LEVEL > level) {
2631 ChildT* child =
new ChildT(xyz, mBackground,
false);
2632 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2633 child->addTile(level, xyz, value, state);
2635 mTable[this->coordToKey(xyz)] = NodeStruct(Tile(value, state));
2637 }
else if (isChild(iter)) {
2638 if (LEVEL > level) {
2639 getChild(iter).addTile(level, xyz, value, state);
2641 setTile(iter, Tile(value, state));
2644 if (LEVEL > level) {
2645 ChildT* child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2646 setChild(iter, *child);
2647 child->addTile(level, xyz, value, state);
2649 setTile(iter, Tile(value, state));
2656 template<
typename ChildT>
2657 template<
typename AccessorT>
2660 bool state, AccessorT& acc)
2662 if (LEVEL >= level) {
2663 MapIter iter = this->findCoord(xyz);
2664 if (iter == mTable.end()) {
2665 if (LEVEL > level) {
2666 ChildT* child =
new ChildT(xyz, mBackground,
false);
2667 acc.insert(xyz, child);
2668 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2669 child->addTileAndCache(level, xyz, value, state, acc);
2671 mTable[this->coordToKey(xyz)] = NodeStruct(Tile(value, state));
2673 }
else if (isChild(iter)) {
2674 if (LEVEL > level) {
2675 ChildT* child = &getChild(iter);
2676 acc.insert(xyz, child);
2677 child->addTileAndCache(level, xyz, value, state, acc);
2679 setTile(iter, Tile(value, state));
2682 if (LEVEL > level) {
2683 ChildT* child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2684 acc.insert(xyz, child);
2685 setChild(iter, *child);
2686 child->addTileAndCache(level, xyz, value, state, acc);
2688 setTile(iter, Tile(value, state));
2698 template<
typename ChildT>
2699 inline typename ChildT::LeafNodeType*
2702 ChildT* child =
nullptr;
2703 MapIter iter = this->findCoord(xyz);
2704 if (iter == mTable.end()) {
2705 child =
new ChildT(xyz, mBackground,
false);
2706 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2707 }
else if (isChild(iter)) {
2708 child = &getChild(iter);
2710 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2711 setChild(iter, *child);
2713 return child->touchLeaf(xyz);
2717 template<
typename ChildT>
2718 template<
typename AccessorT>
2719 inline typename ChildT::LeafNodeType*
2722 ChildT* child =
nullptr;
2723 MapIter iter = this->findCoord(xyz);
2724 if (iter == mTable.end()) {
2725 child =
new ChildT(xyz, mBackground,
false);
2726 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2727 }
else if (isChild(iter)) {
2728 child = &getChild(iter);
2730 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2731 setChild(iter, *child);
2733 acc.insert(xyz, child);
2734 return child->touchLeafAndCache(xyz, acc);
2741 template<
typename ChildT>
2742 template<
typename NodeT>
2746 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2747 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2749 MapIter iter = this->findCoord(xyz);
2750 if (iter == mTable.end() || isTile(iter))
return nullptr;
2751 ChildT* child = &getChild(iter);
2752 return (std::is_same<NodeT, ChildT>::value)
2753 ?
reinterpret_cast<NodeT*
>(child)
2754 : child->template probeNode<NodeT>(xyz);
2759 template<
typename ChildT>
2760 template<
typename NodeT>
2764 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2765 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2767 MapCIter iter = this->findCoord(xyz);
2768 if (iter == mTable.end() || isTile(iter))
return nullptr;
2769 const ChildT* child = &getChild(iter);
2770 return (std::is_same<NodeT, ChildT>::value)
2771 ?
reinterpret_cast<const NodeT*
>(child)
2772 : child->template probeConstNode<NodeT>(xyz);
2777 template<
typename ChildT>
2778 inline typename ChildT::LeafNodeType*
2781 return this->
template probeNode<LeafNodeType>(xyz);
2785 template<
typename ChildT>
2786 inline const typename ChildT::LeafNodeType*
2789 return this->
template probeConstNode<LeafNodeType>(xyz);
2793 template<
typename ChildT>
2794 template<
typename AccessorT>
2795 inline typename ChildT::LeafNodeType*
2798 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
2802 template<
typename ChildT>
2803 template<
typename AccessorT>
2804 inline const typename ChildT::LeafNodeType*
2807 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
2811 template<
typename ChildT>
2812 template<
typename AccessorT>
2813 inline const typename ChildT::LeafNodeType*
2816 return this->probeConstLeafAndCache(xyz, acc);
2820 template<
typename ChildT>
2821 template<
typename NodeT,
typename AccessorT>
2825 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2826 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2828 MapIter iter = this->findCoord(xyz);
2829 if (iter == mTable.end() || isTile(iter))
return nullptr;
2830 ChildT* child = &getChild(iter);
2831 acc.insert(xyz, child);
2832 return (std::is_same<NodeT, ChildT>::value)
2833 ?
reinterpret_cast<NodeT*
>(child)
2834 : child->template probeNodeAndCache<NodeT>(xyz, acc);
2839 template<
typename ChildT>
2840 template<
typename NodeT,
typename AccessorT>
2844 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
2845 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2847 MapCIter iter = this->findCoord(xyz);
2848 if (iter == mTable.end() || isTile(iter))
return nullptr;
2849 const ChildT* child = &getChild(iter);
2850 acc.insert(xyz, child);
2851 return (std::is_same<NodeT, ChildT>::value)
2852 ?
reinterpret_cast<const NodeT*
>(child)
2853 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
2860 template<
typename ChildT>
2861 template<
typename ArrayT>
2865 using NodePtr =
typename ArrayT::value_type;
2866 static_assert(std::is_pointer<NodePtr>::value,
2867 "argument to getNodes() must be a pointer array");
2868 using NodeType =
typename std::remove_pointer<NodePtr>::type;
2869 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
2870 static_assert(NodeChainType::template Contains<NonConstNodeType>,
2871 "can't extract non-const nodes from a const tree");
2872 using ArrayChildT =
typename std::conditional<
2873 std::is_const<NodeType>::value,
const ChildT, ChildT>::type;
2875 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
2876 if (ChildT* child = iter->second.child) {
2878 if (std::is_same<NodePtr, ArrayChildT*>::value) {
2879 array.push_back(
reinterpret_cast<NodePtr
>(iter->second.child));
2881 child->getNodes(array);
2888 template<
typename ChildT>
2889 template<
typename ArrayT>
2893 using NodePtr =
typename ArrayT::value_type;
2894 static_assert(std::is_pointer<NodePtr>::value,
2895 "argument to getNodes() must be a pointer array");
2896 using NodeType =
typename std::remove_pointer<NodePtr>::type;
2897 static_assert(std::is_const<NodeType>::value,
2898 "argument to getNodes() must be an array of const node pointers");
2899 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
2900 static_assert(NodeChainType::template Contains<NonConstNodeType>,
2901 "can't extract non-const nodes from a const tree");
2903 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
2906 if (std::is_same<NodePtr, const ChildT*>::value) {
2907 array.push_back(
reinterpret_cast<NodePtr
>(iter->second.child));
2909 child->getNodes(array);
2918 template<
typename ChildT>
2919 template<
typename ArrayT>
2923 using NodePtr =
typename ArrayT::value_type;
2924 static_assert(std::is_pointer<NodePtr>::value,
2925 "argument to stealNodes() must be a pointer array");
2926 using NodeType =
typename std::remove_pointer<NodePtr>::type;
2927 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
2928 static_assert(NodeChainType::template Contains<NonConstNodeType>,
2929 "can't extract non-const nodes from a const tree");
2930 using ArrayChildT =
typename std::conditional<
2931 std::is_const<NodeType>::value,
const ChildT, ChildT>::type;
2933 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
2934 if (ChildT* child = iter->second.child) {
2936 if (std::is_same<NodePtr, ArrayChildT*>::value) {
2937 array.push_back(
reinterpret_cast<NodePtr
>(&stealChild(iter, Tile(value, state))));
2939 child->stealNodes(array, value, state);
2950 template<
typename ChildT>
2951 template<MergePolicy Policy>
2961 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
2962 MapIter j = mTable.find(i->first);
2963 if (other.isChild(i)) {
2964 if (j == mTable.end()) {
2965 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
2966 child.resetBackground(other.mBackground, mBackground);
2967 mTable[i->first] = NodeStruct(child);
2968 }
else if (isTile(j)) {
2970 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
2971 child.resetBackground(other.mBackground, mBackground);
2975 getChild(j).template merge<MERGE_ACTIVE_STATES>(getChild(i),
2976 other.mBackground, mBackground);
2978 }
else if (other.isTileOn(i)) {
2979 if (j == mTable.end()) {
2980 mTable[i->first] = i->second;
2981 }
else if (!isTileOn(j)) {
2983 setTile(j, Tile(other.getTile(i).value,
true));
2990 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
2991 MapIter j = mTable.find(i->first);
2992 if (other.isChild(i)) {
2993 if (j == mTable.end()) {
2994 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
2995 child.resetBackground(other.mBackground, mBackground);
2996 mTable[i->first] = NodeStruct(child);
2997 }
else if (isTile(j)) {
2998 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
2999 child.resetBackground(other.mBackground, mBackground);
3002 getChild(j).template merge<MERGE_NODES>(
3003 getChild(i), other.mBackground, mBackground);
3010 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3011 MapIter j = mTable.find(i->first);
3012 if (other.isChild(i)) {
3013 if (j == mTable.end()) {
3015 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3016 child.resetBackground(other.mBackground, mBackground);
3017 mTable[i->first] = NodeStruct(child);
3018 }
else if (isTile(j)) {
3020 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3021 child.resetBackground(other.mBackground, mBackground);
3022 const Tile tile = getTile(j);
3026 child.template merge<MERGE_ACTIVE_STATES_AND_NODES>(
3027 tile.value, tile.active);
3031 getChild(j).template merge<MERGE_ACTIVE_STATES_AND_NODES>(getChild(i),
3032 other.mBackground, mBackground);
3034 }
else if (other.isTileOn(i)) {
3035 if (j == mTable.end()) {
3037 mTable[i->first] = i->second;
3038 }
else if (isTileOff(j)) {
3040 setTile(j, Tile(other.getTile(i).value,
true));
3041 }
else if (isChild(j)) {
3043 const Tile& tile = getTile(i);
3044 getChild(j).template merge<MERGE_ACTIVE_STATES_AND_NODES>(
3045 tile.value, tile.active);
3062 template<
typename ChildT>
3063 template<
typename OtherChildType>
3068 using OtherCIterT =
typename OtherRootT::MapCIter;
3070 enforceSameConfiguration(other);
3072 for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3073 MapIter j = mTable.find(i->first);
3074 if (other.isChild(i)) {
3075 if (j == mTable.end()) {
3076 mTable[i->first] = NodeStruct(
3077 *(
new ChildT(other.getChild(i), mBackground,
TopologyCopy())));
3078 }
else if (this->isChild(j)) {
3079 this->getChild(j).topologyUnion(other.getChild(i));
3081 ChildT* child =
new ChildT(
3082 other.getChild(i), this->getTile(j).value,
TopologyCopy());
3083 if (this->isTileOn(j)) child->setValuesOn();
3084 this->setChild(j, *child);
3086 }
else if (other.isTileOn(i)) {
3087 if (j == mTable.end()) {
3088 mTable[i->first] = NodeStruct(Tile(mBackground,
true));
3089 }
else if (this->isChild(j)) {
3090 this->getChild(j).setValuesOn();
3091 }
else if (this->isTileOff(j)) {
3092 this->setTile(j, Tile(this->getTile(j).value,
true));
3098 template<
typename ChildT>
3099 template<
typename OtherChildType>
3104 using OtherCIterT =
typename OtherRootT::MapCIter;
3106 enforceSameConfiguration(other);
3108 std::set<Coord> tmp;
3109 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
3110 OtherCIterT j = other.mTable.find(i->first);
3111 if (this->isChild(i)) {
3112 if (j == other.mTable.end() || other.isTileOff(j)) {
3113 tmp.insert(i->first);
3114 }
else if (other.isChild(j)) {
3115 this->getChild(i).topologyIntersection(other.getChild(j), mBackground);
3117 }
else if (this->isTileOn(i)) {
3118 if (j == other.mTable.end() || other.isTileOff(j)) {
3119 this->setTile(i, Tile(this->getTile(i).value,
false));
3120 }
else if (other.isChild(j)) {
3122 new ChildT(other.getChild(j), this->getTile(i).value,
TopologyCopy());
3123 this->setChild(i, *child);
3127 for (std::set<Coord>::iterator i = tmp.begin(), e = tmp.end(); i != e; ++i) {
3128 MapIter it = this->findCoord(*i);
3129 setTile(it, Tile());
3134 template<
typename ChildT>
3135 template<
typename OtherChildType>
3140 using OtherCIterT =
typename OtherRootT::MapCIter;
3142 enforceSameConfiguration(other);
3144 for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3145 MapIter j = mTable.find(i->first);
3146 if (other.isChild(i)) {
3147 if (j == mTable.end() || this->isTileOff(j)) {
3149 }
else if (this->isChild(j)) {
3150 this->getChild(j).topologyDifference(other.getChild(i), mBackground);
3151 }
else if (this->isTileOn(j)) {
3153 ChildT* child =
new ChildT(j->first, this->getTile(j).value,
true);
3154 child->topologyDifference(other.getChild(i), mBackground);
3155 this->setChild(j, *child);
3157 }
else if (other.isTileOn(i)) {
3158 if (j == mTable.end() || this->isTileOff(j)) {
3160 }
else if (this->isChild(j)) {
3163 }
else if (this->isTileOn(j)) {
3164 this->setTile(j, Tile(this->getTile(j).value,
false));
3173 template<
typename ChildT>
3174 template<
typename CombineOp>
3181 this->insertKeys(keys);
3182 other.insertKeys(keys);
3184 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3185 MapIter iter = findOrAddCoord(*i), otherIter = other.findOrAddCoord(*i);
3186 if (isTile(iter) && isTile(otherIter)) {
3189 op(args.
setARef(getTile(iter).value)
3190 .setAIsActive(isTileOn(iter))
3191 .setBRef(getTile(otherIter).value)
3192 .setBIsActive(isTileOn(otherIter)));
3195 }
else if (isChild(iter) && isTile(otherIter)) {
3197 ChildT& child = getChild(iter);
3198 child.combine(getTile(otherIter).value, isTileOn(otherIter), op);
3200 }
else if (isTile(iter) && isChild(otherIter)) {
3205 ChildT& child = getChild(otherIter);
3206 child.combine(getTile(iter).value, isTileOn(iter), swappedOp);
3209 setChild(iter, stealChild(otherIter, Tile()));
3213 ChildT &child = getChild(iter), &otherChild = getChild(otherIter);
3214 child.combine(otherChild, op);
3216 if (
prune && isChild(iter)) getChild(iter).prune();
3221 mBackground = args.
result();
3233 template<
typename CombineOp,
typename RootT,
typename OtherRootT,
bool Compatible = false>
3236 static inline void combine2(RootT&
self,
const RootT&,
const OtherRootT& other1,
3241 self.enforceSameConfiguration(other1);
3242 self.enforceCompatibleValueTypes(other1);
3244 std::ostringstream ostr;
3245 ostr <<
"cannot combine a " <<
typeid(OtherRootT).name()
3246 <<
" into a " <<
typeid(RootT).name();
3252 template<
typename CombineOp,
typename RootT,
typename OtherRootT>
3255 static inline void combine2(RootT&
self,
const RootT& other0,
const OtherRootT& other1,
3256 CombineOp& op,
bool prune)
3258 self.doCombine2(other0, other1, op,
prune);
3263 template<
typename ChildT>
3264 template<
typename CombineOp,
typename OtherRootNode>
3267 CombineOp& op,
bool prune)
3269 using OtherValueType =
typename OtherRootNode::ValueType;
3273 *
this, other0, other1, op,
prune);
3277 template<
typename ChildT>
3278 template<
typename CombineOp,
typename OtherRootNode>
3281 CombineOp& op,
bool prune)
3283 enforceSameConfiguration(other1);
3285 using OtherValueT =
typename OtherRootNode::ValueType;
3286 using OtherTileT =
typename OtherRootNode::Tile;
3287 using OtherNodeStructT =
typename OtherRootNode::NodeStruct;
3288 using OtherMapCIterT =
typename OtherRootNode::MapCIter;
3293 other0.insertKeys(keys);
3294 other1.insertKeys(keys);
3296 const NodeStruct bg0(Tile(other0.mBackground,
false));
3297 const OtherNodeStructT bg1(OtherTileT(other1.mBackground,
false));
3299 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3300 MapIter thisIter = this->findOrAddCoord(*i);
3301 MapCIter iter0 = other0.findKey(*i);
3302 OtherMapCIterT iter1 = other1.findKey(*i);
3303 const NodeStruct& ns0 = (iter0 != other0.mTable.end()) ? iter0->second : bg0;
3304 const OtherNodeStructT& ns1 = (iter1 != other1.mTable.end()) ? iter1->second : bg1;
3305 if (ns0.isTile() && ns1.isTile()) {
3308 op(args.
setARef(ns0.tile.value)
3314 if (!isChild(thisIter)) {
3316 const Coord& childOrigin =
3317 ns0.isChild() ? ns0.child->origin() : ns1.child->origin();
3318 setChild(thisIter, *(
new ChildT(childOrigin, getTile(thisIter).value)));
3320 ChildT& child = getChild(thisIter);
3325 child.combine2(ns0.tile.value, *ns1.child, ns0.isTileOn(), op);
3326 }
else if (ns1.isTile()) {
3329 child.combine2(*ns0.child, ns1.tile.value, ns1.isTileOn(), op);
3333 child.combine2(*ns0.child, *ns1.child, op);
3336 if (
prune && isChild(thisIter)) getChild(thisIter).prune();
3340 op(args.
setARef(other0.mBackground).
setBRef(other1.mBackground));
3341 mBackground = args.
result();
3348 template<
typename ChildT>
3349 template<
typename BBoxOp>
3353 const bool descent = op.template descent<LEVEL>();
3354 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
3355 if (this->isTileOff(i))
continue;
3356 if (this->isChild(i) && descent) {
3357 this->getChild(i).visitActiveBBox(op);
3365 template<
typename ChildT>
3366 template<
typename VisitorOp>
3370 doVisit<RootNode, VisitorOp, ChildAllIter>(*
this, op);
3374 template<
typename ChildT>
3375 template<
typename VisitorOp>
3379 doVisit<const RootNode, VisitorOp, ChildAllCIter>(*
this, op);
3383 template<
typename ChildT>
3384 template<
typename RootNodeT,
typename VisitorOp,
typename ChildAllIterT>
3388 typename RootNodeT::ValueType val;
3389 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
3390 if (op(iter))
continue;
3391 if (
typename ChildAllIterT::ChildNodeType* child = iter.probeChild(val)) {
3401 template<
typename ChildT>
3402 template<
typename OtherRootNodeType,
typename VisitorOp>
3407 typename OtherRootNodeType::ChildAllIter>(*
this, other, op);
3411 template<
typename ChildT>
3412 template<
typename OtherRootNodeType,
typename VisitorOp>
3417 typename OtherRootNodeType::ChildAllCIter>(*
this, other, op);
3421 template<
typename ChildT>
3424 typename OtherRootNodeT,
3426 typename ChildAllIterT,
3427 typename OtherChildAllIterT>
3431 enforceSameConfiguration(other);
3433 typename RootNodeT::ValueType val;
3434 typename OtherRootNodeT::ValueType otherVal;
3439 RootNodeT copyOfSelf(
self.mBackground);
3440 copyOfSelf.mTable =
self.mTable;
3441 OtherRootNodeT copyOfOther(other.mBackground);
3442 copyOfOther.mTable = other.mTable;
3446 self.insertKeys(keys);
3447 other.insertKeys(keys);
3448 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3449 copyOfSelf.findOrAddCoord(*i);
3450 copyOfOther.findOrAddCoord(*i);
3453 ChildAllIterT iter = copyOfSelf.beginChildAll();
3454 OtherChildAllIterT otherIter = copyOfOther.beginChildAll();
3456 for ( ; iter && otherIter; ++iter, ++otherIter)
3458 const size_t skipBranch =
static_cast<size_t>(op(iter, otherIter));
3460 typename ChildAllIterT::ChildNodeType* child =
3461 (skipBranch & 1U) ?
nullptr : iter.probeChild(val);
3462 typename OtherChildAllIterT::ChildNodeType* otherChild =
3463 (skipBranch & 2U) ?
nullptr : otherIter.probeChild(otherVal);
3465 if (child !=
nullptr && otherChild !=
nullptr) {
3466 child->visit2Node(*otherChild, op);
3467 }
else if (child !=
nullptr) {
3468 child->visit2(otherIter, op);
3469 }
else if (otherChild !=
nullptr) {
3470 otherChild->visit2(iter, op,
true);
3475 copyOfSelf.eraseBackgroundTiles();
3476 copyOfOther.eraseBackgroundTiles();
3480 self.resetTable(copyOfSelf.mTable);
3481 other.resetTable(copyOfOther.mTable);
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: openvdb/Types.h:429
CombineArgs & setBIsActive(bool b)
Set the active state of the B value.
Definition: openvdb/Types.h:497
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: openvdb/Types.h:481
CombineArgs & setAIsActive(bool b)
Set the active state of the A value.
Definition: openvdb/Types.h:495
const AValueType & result() const
Get the output value.
Definition: openvdb/Types.h:473
bool resultIsActive() const
Definition: openvdb/Types.h:492
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
Definition: openvdb/Types.h:483
Tag dispatch class that distinguishes constructors during file input.
Definition: openvdb/Types.h:548
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: openvdb/Types.h:542
Definition: openvdb/Exceptions.h:64
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:249
const Coord & min() const
Definition: Coord.h:321
void translate(const Coord &t)
Translate this bounding box by (tx, ty, tz).
Definition: Coord.h:458
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:418
bool empty() const
Return true if this bounding box is empty (i.e., encloses no coordinates).
Definition: Coord.h:356
const Coord & max() const
Definition: Coord.h:322
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition: Coord.h:412
static CoordBBox inf()
Return an "infinite" bounding box, as defined by the Coord value range.
Definition: Coord.h:319
bool isInside(const Coord &xyz) const
Return true if point (x, y, z) is inside this bounding box.
Definition: Coord.h:400
void intersect(const CoordBBox &bbox)
Intersect this bounding box with the given bounding box.
Definition: Coord.h:444
static CoordBBox createCube(const Coord &min, ValueType dim)
Definition: Coord.h:313
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:26
Coord & setX(Int32 x)
Definition: Coord.h:80
Int32 y() const
Definition: Coord.h:132
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:92
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition: Coord.h:176
Coord & setY(Int32 y)
Definition: Coord.h:81
Int32 x() const
Definition: Coord.h:131
static bool lessThan(const Coord &a, const Coord &b)
Definition: Coord.h:209
Int32 z() const
Definition: Coord.h:133
const Int32 * asPointer() const
Definition: Coord.h:142
Coord & setZ(Int32 z)
Definition: Coord.h:82
void read(std::istream &is)
Definition: Coord.h:220
Definition: RootNode.h:39
static CoordBBox getNodeBoundingBox()
Return the bounding box of this RootNode, i.e., an infinite bounding box.
Definition: RootNode.h:406
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: RootNode.h:1858
DenseIter< RootNode, MapIter, ChildType, ValueType > ChildAllIter
Definition: RootNode.h:364
void visit(VisitorOp &)
Definition: RootNode.h:3368
static bool hasSameConfiguration(const RootNode< OtherChildType > &other)
Return false if the other node's dimensions don't match this node's.
Definition: RootNode.h:1383
int getValueDepth(const Coord &xyz) const
Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides.
Definition: RootNode.h:1709
RootNode & operator=(const RootNode< OtherChildType > &other)
Copy a root node of the same tree configuration as this node but a different ValueType.
ValueIter< const RootNode, MapCIter, ValueOffPred, const ValueType > ValueOffCIter
Definition: RootNode.h:370
RootNode(const RootNode &other)
Definition: RootNode.h:75
ChildOnCIter cbeginChildOn() const
Definition: RootNode.h:375
ChildOnCIter beginChildOn() const
Definition: RootNode.h:378
ChildOnIter beginChildOn()
Definition: RootNode.h:381
Index getDepth() const
Definition: RootNode.h:457
bool isValueOn(const Coord &xyz) const
Definition: RootNode.h:1653
ValueIter< const RootNode, MapCIter, ValueOnPred, const ValueType > ValueOnCIter
Definition: RootNode.h:368
void getIndexRange(CoordBBox &bbox) const
Return the current index range. Both min and max are inclusive.
Definition: RootNode.h:1323
void copyToDense(const CoordBBox &bbox, DenseT &dense) const
Copy into a dense grid the values of all voxels, both active and inactive, that intersect a given bou...
Definition: RootNode.h:2218
const ValueType & background() const
Return this node's background value.
Definition: RootNode.h:423
RootNode & operator=(const RootNode &other)
Copy a root node of the same type as this node.
Definition: RootNode.h:1150
Coord getMaxIndex() const
Return the largest index of the current tree.
Definition: RootNode.h:1315
ValueOffCIter cbeginValueOff() const
Definition: RootNode.h:386
void addLeafAndCache(LeafNodeType *leaf, AccessorT &)
Same as addLeaf() but, if necessary, update the given accessor with pointers to the nodes along the p...
Definition: RootNode.h:2563
static Index getChildDim()
Definition: RootNode.h:450
Index32 nonLeafCount() const
Definition: RootNode.h:1538
void combine(RootNode &other, CombineOp &, bool prune=false)
Definition: RootNode.h:3176
bool addChild(ChildType *child)
Add the given child node at the root level. If a child node with the same origin already exists,...
Definition: RootNode.h:2597
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition: RootNode.h:2863
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: RootNode.h:2509
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition: RootNode.h:2192
ValueIter< RootNode, MapIter, ValueOffPred, ValueType > ValueOffIter
Definition: RootNode.h:369
ValueIter< RootNode, MapIter, ValueAllPred, ValueType > ValueAllIter
Definition: RootNode.h:371
Index64 onLeafVoxelCount() const
Definition: RootNode.h:1596
void clip(const CoordBBox &)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: RootNode.h:2448
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition: RootNode.h:2779
static bool hasCompatibleValueType(const RootNode< OtherChildType > &other)
Definition: RootNode.h:1415
ValueAllCIter cbeginValueAll() const
Definition: RootNode.h:387
NodeT * probeNodeAndCache(const Coord &xyz, AccessorT &acc)
Same as probeNode() but, if necessary, update the given accessor with pointers to the nodes along the...
Definition: RootNode.h:2823
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: RootNode.h:2488
typename NodeChain< RootNode, LEVEL >::Type NodeChainType
NodeChainType is a list of this tree's node types, from LeafNodeType to RootNode.
Definition: RootNode.h:49
bool isBackgroundTile(const Tile &) const
Return true if the given tile is inactive and has the background value.
Definition: RootNode.h:1212
typename ChildType::LeafNodeType LeafNodeType
Definition: RootNode.h:42
size_t eraseBackgroundTiles()
Remove all background tiles.
Definition: RootNode.h:1246
void topologyDifference(const RootNode< OtherChildType > &other)
Difference this tree's set of active values with the active values of the other tree,...
Definition: RootNode.h:3137
ValueIter< RootNode, MapIter, ValueOnPred, ValueType > ValueOnIter
Definition: RootNode.h:367
ValueOnCIter beginValueOn() const
Definition: RootNode.h:388
void topologyUnion(const RootNode< OtherChildType > &other)
Union this tree's set of active values with the active values of the other tree, whose ValueType may ...
Definition: RootNode.h:3065
void merge(RootNode &other)
Efficiently merge another tree into this tree using one of several schemes.
Definition: RootNode.h:2953
ChildIter< RootNode, MapIter, ChildOnPred, ChildType > ChildOnIter
Definition: RootNode.h:360
Index64 offLeafVoxelCount() const
Definition: RootNode.h:1608
Index getWidth() const
Definition: RootNode.h:455
Index getTableSize() const
Return the number of entries in this node's table.
Definition: RootNode.h:453
void combine2(const RootNode &other0, const OtherRootNode &other1, CombineOp &op, bool prune=false)
Definition: RootNode.h:3266
const LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc) const
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: RootNode.h:1990
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: RootNode.h:1899
size_t numBackgroundTiles() const
Return the number of background tiles.
Definition: RootNode.h:1234
ValueIter< const RootNode, MapCIter, ChildOffPred, ValueType > ChildOffCIter
Definition: RootNode.h:363
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates but don't change its active state.
Definition: RootNode.h:1880
bool empty() const
Return true if this node's table is either empty or contains only background tiles.
Definition: RootNode.h:441
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Definition: RootNode.h:2787
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: RootNode.h:2084
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() but, if necessary, update the given accessor with pointers to the nodes along the...
ValueOffCIter beginValueOff() const
Definition: RootNode.h:389
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: RootNode.h:1815
void addLeaf(LeafNodeType *leaf)
Add the given leaf node to this tree, creating a new branch if necessary. If a leaf node with the sam...
Definition: RootNode.h:2528
ChildAllCIter cbeginChildAll() const
Definition: RootNode.h:377
void addTile(const Coord &xyz, const ValueType &value, bool state)
Add a tile containing voxel (x, y, z) at the root level, deleting the existing branch if necessary.
Definition: RootNode.h:2612
ChildAllIter beginChildAll()
Definition: RootNode.h:383
static Index getLevel()
Definition: RootNode.h:448
bool writeTopology(std::ostream &, bool toHalf=false) const
Definition: RootNode.h:2262
ValueIter< const RootNode, MapCIter, ValueAllPred, const ValueType > ValueAllCIter
Definition: RootNode.h:372
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Definition: RootNode.h:1673
const NodeT * probeConstNodeAndCache(const Coord &xyz, AccessorT &acc) const
Definition: RootNode.h:2842
bool probeValue(const Coord &xyz, ValueType &value) const
Definition: RootNode.h:2048
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don't change its value.
Definition: RootNode.h:1745
ValueOnIter beginValueOn()
Definition: RootNode.h:391
void modifyValueAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: RootNode.h:1954
void visit2(OtherRootNodeType &other, VisitorOp &)
Definition: RootNode.h:3404
ChildOffCIter cbeginChildOff() const
Definition: RootNode.h:376
ChildOffIter beginChildOff()
Definition: RootNode.h:382
Index64 onVoxelCount() const
Definition: RootNode.h:1564
LeafNodeType * touchLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as touchLeaf() but, if necessary, update the given accessor with pointers to the nodes along the...
ChildOffCIter beginChildOff() const
Definition: RootNode.h:379
void addTileAndCache(Index level, const Coord &xyz, const ValueType &, bool state, AccessorT &)
Same as addTile() but, if necessary, update the given accessor with pointers to the nodes along the p...
Definition: RootNode.h:2659
typename ChildType::ValueType ValueType
Definition: RootNode.h:43
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition: RootNode.h:1731
void writeBuffers(std::ostream &, bool toHalf=false) const
Definition: RootNode.h:2404
ValueOnCIter cbeginValueOn() const
Definition: RootNode.h:385
Index32 leafCount() const
Definition: RootNode.h:1526
const LeafNodeType * probeConstLeafAndCache(const Coord &xyz, AccessorT &acc) const
Index32 childCount() const
Definition: RootNode.h:1552
Index64 onTileCount() const
Definition: RootNode.h:1619
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: RootNode.h:1922
void visitActiveBBox(BBoxOp &) const
Call the templated functor BBoxOp with bounding box information for all active tiles and leaf nodes i...
Definition: RootNode.h:3351
~RootNode()
Definition: RootNode.h:123
Index64 offVoxelCount() const
Definition: RootNode.h:1580
LeafNodeType * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition: RootNode.h:2700
typename ChildType::BuildType BuildType
Definition: RootNode.h:44
void setBackground(const ValueType &value, bool updateChildNodes)
Change inactive tiles or voxels with a value equal to +/- the old background to the specified value (...
Definition: RootNode.h:1185
DenseIter< const RootNode, MapCIter, const ChildType, const ValueType > ChildAllCIter
Definition: RootNode.h:365
bool hasSameTopology(const RootNode< OtherChildType > &other) const
Return true if the given tree has the same node and active value topology as this tree (but possibly ...
Definition: RootNode.h:1336
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: RootNode.h:2142
ChildAllCIter beginChildAll() const
Definition: RootNode.h:380
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Definition: RootNode.h:1768
const LeafNodeType * probeLeaf(const Coord &xyz) const
void topologyIntersection(const RootNode< OtherChildType > &other)
Intersects this tree's set of active values with the active values of the other tree,...
Definition: RootNode.h:3101
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: RootNode.h:2921
Index getHeight() const
Definition: RootNode.h:456
void clear()
Definition: RootNode.h:1456
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Definition: RootNode.h:2064
const NodeT * probeConstNode(const Coord &xyz) const
Definition: RootNode.h:2762
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Expand the specified bbox so it includes the active tiles of this root node as well as all the active...
Definition: RootNode.h:1467
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
static void getNodeLog2Dims(std::vector< Index > &dims)
Definition: RootNode.h:1299
RootNode(const RootNode< OtherChildType > &other)
Construct a new tree that reproduces the topology and active states of a tree of a different ValueTyp...
Definition: RootNode.h:84
ValueOffIter beginValueOff()
Definition: RootNode.h:392
ValueIter< RootNode, MapIter, ChildOffPred, const ValueType > ChildOffIter
Definition: RootNode.h:362
void sparseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Definition: RootNode.h:532
Coord getMinIndex() const
Return the smallest index of the current tree.
Definition: RootNode.h:1308
ChildType ChildNodeType
Definition: RootNode.h:41
bool hasActiveTiles() const
Return true if this root node, or any of its child nodes, have active tiles.
Definition: RootNode.h:1662
int getValueDepthAndCache(const Coord &xyz, AccessorT &) const
Definition: RootNode.h:1719
const ValueType & getValue(const Coord &xyz) const
Definition: RootNode.h:1685
void nodeCount(std::vector< Index32 > &vec) const
Definition: RootNode.h:1634
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
Definition: RootNode.h:1442
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active.
Definition: RootNode.h:1839
void stealNodes(ArrayT &array)
Definition: RootNode.h:811
bool expand(const Coord &xyz)
Expand this node's table so that (x, y, z) is included in the index range.
Definition: RootNode.h:1285
void readBuffers(std::istream &, bool fromHalf=false)
Definition: RootNode.h:2414
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: RootNode.h:2017
ValueAllCIter beginValueAll() const
Definition: RootNode.h:390
NodeT * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists,...
Definition: RootNode.h:2744
bool readTopology(std::istream &, bool fromHalf=false)
Definition: RootNode.h:2298
ChildIter< const RootNode, MapCIter, ChildOnPred, const ChildType > ChildOnCIter
Definition: RootNode.h:361
ValueAllIter beginValueAll()
Definition: RootNode.h:393
friend class RootNode
Definition: RootNode.h:893
Definition: NodeMasks.h:1067
bool isOn(Index32 i) const
Definition: NodeMasks.h:1331
void load(std::istream &is)
Definition: NodeMasks.h:1372
T truncateRealToHalf(const T &val)
Return the given value truncated to 16-bit float precision.
Definition: Compression.h:216
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
OPENVDB_API void setGridBackgroundValuePtr(std::ios_base &, const void *background)
Specify (a pointer to) the background value of the grid currently being read from or written to the g...
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
Definition: Math.h:407
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Multiply m0 by m1 and return the resulting matrix.
Definition: Mat3.h:611
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:444
bool operator!=(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Inequality operator, does exact floating point comparisons.
Definition: Vec3.h:485
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:477
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:127
Index32 FindHighestOn(Index32 v)
Return the most significant on bit of the given 32-bit value.
Definition: NodeMasks.h:159
Index32 Index
Definition: openvdb/Types.h:32
uint32_t Index32
Definition: openvdb/Types.h:30
@ OPENVDB_FILE_VERSION_ROOTNODE_MAP
Definition: version.h:184
int32_t Int32
Definition: openvdb/Types.h:34
uint64_t Index64
Definition: openvdb/Types.h:31
@ MERGE_ACTIVE_STATES
Definition: openvdb/Types.h:367
@ MERGE_NODES
Definition: openvdb/Types.h:368
@ MERGE_ACTIVE_STATES_AND_NODES
Definition: openvdb/Types.h:369
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:69
ValueType combine(const ValueType &v0, const ValueType &v1, const ValueType &v2, const openvdb::Vec3d &w)
Combine different value types.
Definition: AttributeTransferUtil.h:140
Definition: openvdb/Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:74
CanConvertType<FromType, ToType>::value is true if a value of type ToType can be constructed from a v...
Definition: openvdb/Types.h:263
Definition: openvdb/Types.h:520
A list of types (not necessarily unique)
Definition: TypeList.h:366
NodeChain<RootNodeType, RootNodeType::LEVEL>::Type is a openvdb::TypeList that lists the types of the...
Definition: RootNode.h:993
typename NodeChain< typename HeadT::ChildNodeType, HeadLevel-1 >::Type SubtreeT
Definition: RootNode.h:994
typename SubtreeT::template Append< HeadT > Type
Definition: RootNode.h:995
static void combine2(RootT &self, const RootT &other0, const OtherRootT &other1, CombineOp &op, bool prune)
Definition: RootNode.h:3255
Definition: RootNode.h:3235
static void combine2(RootT &self, const RootT &, const OtherRootT &other1, CombineOp &, bool)
Definition: RootNode.h:3236
static void copyWithValueConversion(RootT &self, const OtherRootT &other)
Definition: RootNode.h:1112
Definition: RootNode.h:1093
static void copyWithValueConversion(RootT &self, const OtherRootT &other)
Definition: RootNode.h:1094
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of a RootNod...
Definition: RootNode.h:64
ValueConverter<T>::Type is the type of a RootNode having the same child hierarchy as this node but a ...
Definition: RootNode.h:56
Definition: RootNode.h:1012
Library and file format version numbers.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:101
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:153