8#ifndef OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED
9#define OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED
17#include <openvdb/version.h>
18#include <tbb/parallel_for.h>
31template<
typename HeadType,
int HeadLevel>
struct NodeChain;
32template<
typename,
typename>
struct SameRootConfig;
33template<
typename,
typename,
bool>
struct RootNodeCopyHelper;
34template<
typename,
typename,
typename,
bool>
struct RootNodeCombineHelper;
37template<
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>
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
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;
408#if OPENVDB_ABI_VERSION_NUMBER >= 9
427 void setBackground(
const ValueType&
value,
bool updateChildNodes);
433 bool isBackgroundTile(
const Tile&)
const;
436 bool isBackgroundTile(
const MapIter&)
const;
437 bool isBackgroundTile(
const MapCIter&)
const;
441 size_t numBackgroundTiles()
const;
444 size_t eraseBackgroundTiles();
448 bool empty()
const {
return mTable.size() == numBackgroundTiles(); }
453 bool expand(
const Coord& xyz);
456 static void getNodeLog2Dims(std::vector<Index>& dims);
462 Index getWidth()
const {
return this->getMaxIndex()[0] - this->getMinIndex()[0]; }
463 Index getHeight()
const {
return this->getMaxIndex()[1] - this->getMinIndex()[1]; }
464 Index getDepth()
const {
return this->getMaxIndex()[2] - this->getMinIndex()[2]; }
467 Coord getMinIndex()
const;
469 Coord getMaxIndex()
const;
471 void getIndexRange(
CoordBBox& bbox)
const;
475 template<
typename OtherChildType>
479 template<
typename OtherChildType>
484 template<
typename OtherChildType>
492 Index64 onLeafVoxelCount()
const;
493 Index64 offLeafVoxelCount()
const;
495 void nodeCount(std::vector<Index32> &vec)
const;
497 bool isValueOn(
const Coord& xyz)
const;
500 bool hasActiveTiles()
const;
502 const ValueType& getValue(
const Coord& xyz)
const;
503 bool probeValue(
const Coord& xyz, ValueType&
value)
const;
508 int getValueDepth(
const Coord& xyz)
const;
511 void setActiveState(
const Coord& xyz,
bool on);
513 void setValueOnly(
const Coord& xyz,
const ValueType&
value);
515 void setValueOn(
const Coord& xyz,
const ValueType&
value);
517 void setValueOff(
const Coord& xyz);
519 void setValueOff(
const Coord& xyz,
const ValueType&
value);
523 template<
typename ModifyOp>
524 void modifyValue(
const Coord& xyz,
const ModifyOp& op);
526 template<
typename ModifyOp>
527 void modifyValueAndActiveState(
const Coord& xyz,
const ModifyOp& op);
538 void fill(
const CoordBBox& bbox,
const ValueType&
value,
bool active =
true);
541 this->fill(bbox,
value, active);
552 void denseFill(
const CoordBBox& bbox,
const ValueType&
value,
bool active =
true);
562 void voxelizeActiveTiles(
bool threaded =
true);
569 template<
typename DenseT>
576 bool writeTopology(std::ostream&,
bool toHalf =
false)
const;
577 bool readTopology(std::istream&,
bool fromHalf =
false);
579 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
580 void readBuffers(std::istream&,
bool fromHalf =
false);
581 void readBuffers(std::istream&,
const CoordBBox&,
bool fromHalf =
false);
591 template<
typename AccessorT>
597 template<
typename AccessorT>
598 bool isValueOnAndCache(
const Coord& xyz, AccessorT&)
const;
604 template<
typename AccessorT>
611 template<
typename AccessorT>
619 template<
typename ModifyOp,
typename AccessorT>
620 void modifyValueAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
626 template<
typename ModifyOp,
typename AccessorT>
627 void modifyValueAndActiveStateAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
633 template<
typename AccessorT>
640 template<
typename AccessorT>
641 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&);
648 template<
typename AccessorT>
656 template<
typename AccessorT>
657 int getValueDepthAndCache(
const Coord& xyz, AccessorT&)
const;
675 template<
typename AccessorT>
686 template<
typename NodeT>
694 bool addChild(ChildType*
child);
707 template<
typename AccessorT>
708 void addTileAndCache(
Index level,
const Coord& xyz,
const ValueType&,
bool state, AccessorT&);
719 template<
typename AccessorT>
725 template <
typename NodeT>
726 NodeT* probeNode(
const Coord& xyz);
727 template <
typename NodeT>
728 const NodeT* probeConstNode(
const Coord& xyz)
const;
734 template<
typename NodeT,
typename AccessorT>
735 NodeT* probeNodeAndCache(
const Coord& xyz, AccessorT& acc);
736 template<
typename NodeT,
typename AccessorT>
737 const NodeT* probeConstNodeAndCache(
const Coord& xyz, AccessorT& acc)
const;
751 template<
typename AccessorT>
753 template<
typename AccessorT>
755 template<
typename AccessorT>
787 template<
typename ArrayT>
void getNodes(ArrayT& array);
788 template<
typename ArrayT>
void getNodes(ArrayT& array)
const;
815 template<
typename ArrayT>
816 void stealNodes(ArrayT& array,
const ValueType&
value,
bool state);
817 template<
typename ArrayT>
828 template<MergePolicy Policy>
void merge(
RootNode& other);
846 template<
typename OtherChildType>
862 template<
typename OtherChildType>
875 template<
typename OtherChildType>
878 template<
typename CombineOp>
881 template<
typename CombineOp,
typename OtherRootNode >
882 void combine2(
const RootNode& other0,
const OtherRootNode& other1,
883 CombineOp& op,
bool prune =
false);
890 template<
typename BBoxOp>
void visitActiveBBox(BBoxOp&)
const;
892 template<
typename VisitorOp>
void visit(VisitorOp&);
893 template<
typename VisitorOp>
void visit(VisitorOp&)
const;
895 template<
typename OtherRootNodeType,
typename VisitorOp>
896 void visit2(OtherRootNodeType& other, VisitorOp&);
897 template<
typename OtherRootNodeType,
typename VisitorOp>
898 void visit2(OtherRootNodeType& other, VisitorOp&)
const;
912 void resetTable(MapType& table) { mTable.swap(table); table.clear(); }
913 void resetTable(
const MapType&)
const {}
916#if OPENVDB_ABI_VERSION_NUMBER < 8
917 Index getChildCount()
const;
919 Index getTileCount()
const;
920 Index getActiveTileCount()
const;
921 Index getInactiveTileCount()
const;
924 static Coord coordToKey(
const Coord& xyz) {
return xyz & ~(ChildType::DIM - 1); }
927 void insertKeys(CoordSet&)
const;
930 bool hasKey(
const Coord& key)
const {
return mTable.find(key) != mTable.end(); }
934 MapIter findKey(
const Coord& key) {
return mTable.find(key); }
935 MapCIter findKey(
const Coord& key)
const {
return mTable.find(key); }
940 MapIter findCoord(
const Coord& xyz) {
return mTable.find(coordToKey(xyz)); }
941 MapCIter findCoord(
const Coord& xyz)
const {
return mTable.find(coordToKey(xyz)); }
946 MapIter findOrAddCoord(
const Coord& xyz);
952 template<
typename OtherChildType>
953 static void enforceSameConfiguration(
const RootNode<OtherChildType>& other);
960 template<
typename OtherChildType>
961 static void enforceCompatibleValueTypes(
const RootNode<OtherChildType>& other);
963 template<
typename CombineOp,
typename OtherRootNode >
964 void doCombine2(
const RootNode&,
const OtherRootNode&, CombineOp&,
bool prune);
966 template<
typename RootNodeT,
typename VisitorOp,
typename ChildAllIterT>
967 static inline void doVisit(RootNodeT&, VisitorOp&);
969 template<
typename RootNodeT,
typename OtherRootNodeT,
typename VisitorOp,
970 typename ChildAllIterT,
typename OtherChildAllIterT>
971 static inline void doVisit2(RootNodeT&, OtherRootNodeT&, VisitorOp&);
975 ValueType mBackground;
976#if OPENVDB_ABI_VERSION_NUMBER >= 9
1006template<
typename HeadT,
int HeadLevel>
1009 using Type =
typename SubtreeT::template Append<HeadT>;
1013template<
typename HeadT>
1025template<
typename ChildT1,
typename NodeT2>
1030template<
typename ChildT1,
typename ChildT2>
1040template<
typename ChildT>
1048template<
typename ChildT>
1056template<
typename ChildT>
1057template<
typename OtherChildType>
1061 : mBackground(backgd)
1062#if OPENVDB_ABI_VERSION_NUMBER >= 9
1063 , mTransientData(other.mTransientData)
1068 enforceSameConfiguration(other);
1070 const Tile bgTile(backgd,
false), fgTile(foregd,
true);
1073 for (
typename OtherRootT::MapCIter i=other.mTable.begin(), e=other.mTable.end(); i != e; ++i) {
1074 mTable[i->first] = OtherRootT::isTile(i)
1075 ? NodeStruct(OtherRootT::isTileOn(i) ? fgTile : bgTile)
1076 : NodeStruct(*(
new ChildT(OtherRootT::getChild(i), backgd, foregd,
TopologyCopy())));
1081template<
typename ChildT>
1082template<
typename OtherChildType>
1086 : mBackground(backgd)
1087#if OPENVDB_ABI_VERSION_NUMBER >= 9
1088 , mTransientData(other.mTransientData)
1093 enforceSameConfiguration(other);
1095 const Tile bgTile(backgd,
false), fgTile(backgd,
true);
1097 for (
typename OtherRootT::MapCIter i=other.mTable.begin(), e=other.mTable.end(); i != e; ++i) {
1098 mTable[i->first] = OtherRootT::isTile(i)
1099 ? NodeStruct(OtherRootT::isTileOn(i) ? fgTile : bgTile)
1100 : NodeStruct(*(
new ChildT(OtherRootT::getChild(i), backgd,
TopologyCopy())));
1111template<
typename RootT,
typename OtherRootT,
bool Compatible = false>
1118 self.enforceSameConfiguration(other);
1119 self.enforceCompatibleValueTypes(other);
1121 std::ostringstream ostr;
1122 ostr <<
"cannot convert a " <<
typeid(OtherRootT).name()
1123 <<
" to a " <<
typeid(RootT).name();
1129template<
typename RootT,
typename OtherRootT>
1134 using ValueT =
typename RootT::ValueType;
1135 using ChildT =
typename RootT::ChildNodeType;
1136 using NodeStruct =
typename RootT::NodeStruct;
1137 using Tile =
typename RootT::Tile;
1138 using OtherValueT =
typename OtherRootT::ValueType;
1139 using OtherMapCIter =
typename OtherRootT::MapCIter;
1140 using OtherTile =
typename OtherRootT::Tile;
1144 static inline ValueT convertValue(
const OtherValueT& val) {
return ValueT(val); }
1147 self.mBackground = Local::convertValue(other.mBackground);
1148#if OPENVDB_ABI_VERSION_NUMBER >= 9
1149 self.mTransientData = other.mTransientData;
1155 for (OtherMapCIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
1156 if (other.isTile(i)) {
1158 const OtherTile& otherTile = other.getTile(i);
1159 self.mTable[i->first] = NodeStruct(
1160 Tile(Local::convertValue(otherTile.value), otherTile.active));
1163 self.mTable[i->first] = NodeStruct(*(
new ChildT(other.getChild(i))));
1171template<
typename ChildT>
1172inline RootNode<ChildT>&
1175 if (&other !=
this) {
1176 mBackground = other.mBackground;
1177#if OPENVDB_ABI_VERSION_NUMBER >= 9
1178 mTransientData = other.mTransientData;
1184 for (MapCIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
1186 isTile(i) ? NodeStruct(getTile(i)) : NodeStruct(*(
new ChildT(getChild(i))));
1193template<
typename ChildT>
1194template<
typename OtherChildType>
1199 using OtherValueT =
typename OtherRootT::ValueType;
1209template<
typename ChildT>
1215 if (updateChildNodes) {
1218 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1219 ChildT *
child = iter->second.child;
1221 child->resetBackground(mBackground, background);
1223 Tile& tile = getTile(iter);
1224 if (tile.active)
continue;
1226 tile.value = background;
1233 mBackground = background;
1236template<
typename ChildT>
1243template<
typename ChildT>
1250template<
typename ChildT>
1258template<
typename ChildT>
1263 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1264 if (this->isBackgroundTile(i)) ++count;
1270template<
typename ChildT>
1274 std::set<Coord> keysToErase;
1275 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1276 if (this->isBackgroundTile(i)) keysToErase.insert(i->first);
1278 for (std::set<Coord>::iterator i = keysToErase.begin(), e = keysToErase.end(); i != e; ++i) {
1281 return keysToErase.size();
1288template<
typename ChildT>
1292 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1293 keys.insert(i->first);
1298template<
typename ChildT>
1299inline typename RootNode<ChildT>::MapIter
1300RootNode<ChildT>::findOrAddCoord(
const Coord& xyz)
1302 const Coord key = coordToKey(xyz);
1303 std::pair<MapIter, bool> result = mTable.insert(
1304 typename MapType::value_type(key, NodeStruct(Tile(mBackground,
false))));
1305 return result.first;
1309template<
typename ChildT>
1313 const Coord key = coordToKey(xyz);
1314 std::pair<MapIter, bool> result = mTable.insert(
1315 typename MapType::value_type(key, NodeStruct(Tile(mBackground,
false))));
1316 return result.second;
1323template<
typename ChildT>
1328 ChildT::getNodeLog2Dims(dims);
1332template<
typename ChildT>
1336 return mTable.empty() ?
Coord(0) : mTable.begin()->first;
1339template<
typename ChildT>
1343 return mTable.empty() ?
Coord(0) : mTable.rbegin()->first +
Coord(ChildT::DIM - 1);
1347template<
typename ChildT>
1351 bbox.
min() = this->getMinIndex();
1352 bbox.
max() = this->getMaxIndex();
1359template<
typename ChildT>
1360template<
typename OtherChildType>
1365 using OtherMapT =
typename OtherRootT::MapType;
1366 using OtherIterT =
typename OtherRootT::MapIter;
1367 using OtherCIterT =
typename OtherRootT::MapCIter;
1369 if (!hasSameConfiguration(other))
return false;
1372 OtherMapT copyOfOtherTable = other.mTable;
1375 for (MapCIter thisIter = mTable.begin(); thisIter != mTable.end(); ++thisIter) {
1376 if (this->isBackgroundTile(thisIter))
continue;
1379 OtherCIterT otherIter = other.findKey(thisIter->first);
1380 if (otherIter == other.mTable.end())
return false;
1383 if (isChild(thisIter)) {
1384 if (OtherRootT::isTile(otherIter))
return false;
1386 if (!getChild(thisIter).hasSameTopology(&OtherRootT::getChild(otherIter)))
return false;
1388 if (OtherRootT::isChild(otherIter))
return false;
1389 if (getTile(thisIter).active != OtherRootT::getTile(otherIter).active)
return false;
1396 copyOfOtherTable.erase(otherIter->first);
1399 for (OtherIterT i = copyOfOtherTable.begin(), e = copyOfOtherTable.end(); i != e; ++i) {
1406template<
typename ChildT>
1407template<
typename OtherChildType>
1411 std::vector<Index> thisDims, otherDims;
1414 return (thisDims == otherDims);
1418template<
typename ChildT>
1419template<
typename OtherChildType>
1423 std::vector<Index> thisDims, otherDims;
1426 if (thisDims != otherDims) {
1427 std::ostringstream ostr;
1428 ostr <<
"grids have incompatible configurations (" << thisDims[0];
1429 for (
size_t i = 1, N = thisDims.size(); i < N; ++i) ostr <<
" x " << thisDims[i];
1430 ostr <<
" vs. " << otherDims[0];
1431 for (
size_t i = 1, N = otherDims.size(); i < N; ++i) ostr <<
" x " << otherDims[i];
1438template<
typename ChildT>
1439template<
typename OtherChildType>
1443 using OtherValueType =
typename OtherChildType::ValueType;
1448template<
typename ChildT>
1449template<
typename OtherChildType>
1453 using OtherValueType =
typename OtherChildType::ValueType;
1455 std::ostringstream ostr;
1456 ostr <<
"values of type " << typeNameAsString<OtherValueType>()
1457 <<
" cannot be converted to type " << typeNameAsString<ValueType>();
1466template<
typename ChildT>
1471 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1472 if (
const ChildT *
child = iter->second.child) {
1473 sum +=
child->memUsage();
1480template<
typename ChildT>
1484 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1485 delete i->second.child;
1491template<
typename ChildT>
1495 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1496 if (
const ChildT *
child = iter->second.child) {
1497 child->evalActiveBoundingBox(bbox, visitVoxels);
1498 }
else if (isTileOn(iter)) {
1499 bbox.
expand(iter->first, ChildT::DIM);
1505#if OPENVDB_ABI_VERSION_NUMBER < 8
1506template<
typename ChildT>
1509 return this->childCount();
1514template<
typename ChildT>
1516RootNode<ChildT>::getTileCount()
const
1519 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1520 if (isTile(i)) ++sum;
1526template<
typename ChildT>
1528RootNode<ChildT>::getActiveTileCount()
const
1531 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1532 if (isTileOn(i)) ++sum;
1538template<
typename ChildT>
1540RootNode<ChildT>::getInactiveTileCount()
const
1543 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1544 if (isTileOff(i)) ++sum;
1550template<
typename ChildT>
1555 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1556 if (isChild(i)) sum += getChild(i).leafCount();
1562template<
typename ChildT>
1567 if (ChildT::LEVEL != 0) {
1568 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1569 if (isChild(i)) sum += getChild(i).nonLeafCount();
1576template<
typename ChildT>
1581 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1582 if (isChild(i)) ++sum;
1588template<
typename ChildT>
1593 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1595 sum += getChild(i).onVoxelCount();
1596 }
else if (isTileOn(i)) {
1597 sum += ChildT::NUM_VOXELS;
1604template<
typename ChildT>
1609 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1611 sum += getChild(i).offVoxelCount();
1612 }
else if (isTileOff(i) && !this->isBackgroundTile(i)) {
1613 sum += ChildT::NUM_VOXELS;
1620template<
typename ChildT>
1625 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1626 if (isChild(i)) sum += getChild(i).onLeafVoxelCount();
1632template<
typename ChildT>
1637 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1638 if (isChild(i)) sum += getChild(i).offLeafVoxelCount();
1643template<
typename ChildT>
1648 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1650 sum += getChild(i).onTileCount();
1651 }
else if (isTileOn(i)) {
1658template<
typename ChildT>
1662 assert(vec.size() > LEVEL);
1664 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1667 getChild(i).nodeCount(vec);
1671 vec[ChildNodeType::LEVEL] = sum;
1677template<
typename ChildT>
1681 MapCIter iter = this->findCoord(xyz);
1682 if (iter == mTable.end() || isTileOff(iter))
return false;
1683 return isTileOn(iter) ? true : getChild(iter).isValueOn(xyz);
1686template<
typename ChildT>
1690 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1691 if (isChild(i) ? getChild(i).hasActiveTiles() : getTile(i).active)
return true;
1696template<
typename ChildT>
1697template<
typename AccessorT>
1701 MapCIter iter = this->findCoord(xyz);
1702 if (iter == mTable.end() || isTileOff(iter))
return false;
1703 if (isTileOn(iter))
return true;
1704 acc.insert(xyz, &getChild(iter));
1705 return getChild(iter).isValueOnAndCache(xyz, acc);
1709template<
typename ChildT>
1710inline const typename ChildT::ValueType&
1713 MapCIter iter = this->findCoord(xyz);
1714 return iter == mTable.end() ? mBackground
1715 : (isTile(iter) ? getTile(iter).value : getChild(iter).getValue(xyz));
1718template<
typename ChildT>
1719template<
typename AccessorT>
1720inline const typename ChildT::ValueType&
1723 MapCIter iter = this->findCoord(xyz);
1724 if (iter == mTable.end())
return mBackground;
1725 if (isChild(iter)) {
1726 acc.insert(xyz, &getChild(iter));
1727 return getChild(iter).getValueAndCache(xyz, acc);
1729 return getTile(iter).value;
1733template<
typename ChildT>
1737 MapCIter iter = this->findCoord(xyz);
1738 return iter == mTable.end() ? -1
1739 : (isTile(iter) ? 0 : int(LEVEL) - int(getChild(iter).getValueLevel(xyz)));
1742template<
typename ChildT>
1743template<
typename AccessorT>
1747 MapCIter iter = this->findCoord(xyz);
1748 if (iter == mTable.end())
return -1;
1749 if (isTile(iter))
return 0;
1750 acc.insert(xyz, &getChild(iter));
1751 return int(LEVEL) - int(getChild(iter).getValueLevelAndCache(xyz, acc));
1755template<
typename ChildT>
1759 MapIter iter = this->findCoord(xyz);
1760 if (iter != mTable.end() && !isTileOff(iter)) {
1761 if (isTileOn(iter)) {
1762 setChild(iter, *
new ChildT(xyz, getTile(iter).
value,
true));
1764 getChild(iter).setValueOff(xyz);
1769template<
typename ChildT>
1773 ChildT*
child =
nullptr;
1774 MapIter iter = this->findCoord(xyz);
1775 if (iter == mTable.end()) {
1777 child =
new ChildT(xyz, mBackground);
1778 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
1782 }
else if (isChild(iter)) {
1783 child = &getChild(iter);
1784 }
else if (on != getTile(iter).active) {
1785 child =
new ChildT(xyz, getTile(iter).
value, !on);
1786 setChild(iter, *
child);
1791template<
typename ChildT>
1792template<
typename AccessorT>
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);
1805 }
else if (isChild(iter)) {
1806 child = &getChild(iter);
1807 }
else if (on != getTile(iter).active) {
1808 child =
new ChildT(xyz, getTile(iter).
value, !on);
1809 setChild(iter, *
child);
1812 acc.insert(xyz,
child);
1813 child->setActiveStateAndCache(xyz, on, acc);
1818template<
typename ChildT>
1822 ChildT*
child =
nullptr;
1823 MapIter iter = this->findCoord(xyz);
1824 if (iter == mTable.end()) {
1826 child =
new ChildT(xyz, mBackground);
1827 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
1829 }
else if (isChild(iter)) {
1830 child = &getChild(iter);
1832 child =
new ChildT(xyz, getTile(iter).
value, isTileOn(iter));
1833 setChild(iter, *
child);
1838template<
typename ChildT>
1839template<
typename AccessorT>
1843 ChildT*
child =
nullptr;
1844 MapIter iter = this->findCoord(xyz);
1845 if (iter == mTable.end()) {
1847 child =
new ChildT(xyz, mBackground);
1848 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
1850 }
else if (isChild(iter)) {
1851 child = &getChild(iter);
1853 child =
new ChildT(xyz, getTile(iter).
value, isTileOn(iter));
1854 setChild(iter, *
child);
1857 acc.insert(xyz,
child);
1863template<
typename ChildT>
1867 ChildT*
child =
nullptr;
1868 MapIter iter = this->findCoord(xyz);
1869 if (iter == mTable.end()) {
1870 child =
new ChildT(xyz, mBackground);
1871 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
1872 }
else if (isChild(iter)) {
1873 child = &getChild(iter);
1875 child =
new ChildT(xyz, getTile(iter).
value, isTileOn(iter));
1876 setChild(iter, *
child);
1881template<
typename ChildT>
1882template<
typename AccessorT>
1886 ChildT*
child =
nullptr;
1887 MapIter iter = this->findCoord(xyz);
1888 if (iter == mTable.end()) {
1889 child =
new ChildT(xyz, mBackground);
1890 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
1891 }
else if (isChild(iter)) {
1892 child = &getChild(iter);
1894 child =
new ChildT(xyz, getTile(iter).
value, isTileOn(iter));
1895 setChild(iter, *
child);
1898 acc.insert(xyz,
child);
1904template<
typename ChildT>
1908 ChildT*
child =
nullptr;
1909 MapIter iter = this->findCoord(xyz);
1910 if (iter == mTable.end()) {
1911 child =
new ChildT(xyz, mBackground);
1912 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
1913 }
else if (isChild(iter)) {
1914 child = &getChild(iter);
1916 child =
new ChildT(xyz, getTile(iter).
value, isTileOn(iter));
1917 setChild(iter, *
child);
1922template<
typename ChildT>
1923template<
typename AccessorT>
1927 ChildT*
child =
nullptr;
1928 MapIter iter = this->findCoord(xyz);
1929 if (iter == mTable.end()) {
1930 child =
new ChildT(xyz, mBackground);
1931 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
1932 }
else if (isChild(iter)) {
1933 child = &getChild(iter);
1935 child =
new ChildT(xyz, getTile(iter).
value, isTileOn(iter));
1936 setChild(iter, *
child);
1939 acc.insert(xyz,
child);
1940 child->setValueOnlyAndCache(xyz,
value, acc);
1945template<
typename ChildT>
1946template<
typename ModifyOp>
1950 ChildT*
child =
nullptr;
1951 MapIter iter = this->findCoord(xyz);
1952 if (iter == mTable.end()) {
1953 child =
new ChildT(xyz, mBackground);
1954 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
1955 }
else if (isChild(iter)) {
1956 child = &getChild(iter);
1960 bool createChild = isTileOff(iter);
1964 const ValueType& tileVal = getTile(iter).value;
1970 child =
new ChildT(xyz, getTile(iter).
value, isTileOn(iter));
1971 setChild(iter, *
child);
1977template<
typename ChildT>
1978template<
typename ModifyOp,
typename AccessorT>
1982 ChildT*
child =
nullptr;
1983 MapIter iter = this->findCoord(xyz);
1984 if (iter == mTable.end()) {
1985 child =
new ChildT(xyz, mBackground);
1986 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
1987 }
else if (isChild(iter)) {
1988 child = &getChild(iter);
1992 bool createChild = isTileOff(iter);
1996 const ValueType& tileVal = getTile(iter).value;
2002 child =
new ChildT(xyz, getTile(iter).
value, isTileOn(iter));
2003 setChild(iter, *
child);
2007 acc.insert(xyz,
child);
2008 child->modifyValueAndCache(xyz, op, acc);
2013template<
typename ChildT>
2014template<
typename ModifyOp>
2018 ChildT*
child =
nullptr;
2019 MapIter iter = this->findCoord(xyz);
2020 if (iter == mTable.end()) {
2021 child =
new ChildT(xyz, mBackground);
2022 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
2023 }
else if (isChild(iter)) {
2024 child = &getChild(iter);
2026 const Tile& tile = getTile(iter);
2027 bool modifiedState = tile.active;
2029 op(modifiedVal, modifiedState);
2033 child =
new ChildT(xyz, tile.value, tile.active);
2034 setChild(iter, *
child);
2037 if (
child)
child->modifyValueAndActiveState(xyz, op);
2040template<
typename ChildT>
2041template<
typename ModifyOp,
typename AccessorT>
2044 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
2046 ChildT*
child =
nullptr;
2047 MapIter iter = this->findCoord(xyz);
2048 if (iter == mTable.end()) {
2049 child =
new ChildT(xyz, mBackground);
2050 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
2051 }
else if (isChild(iter)) {
2052 child = &getChild(iter);
2054 const Tile& tile = getTile(iter);
2055 bool modifiedState = tile.active;
2057 op(modifiedVal, modifiedState);
2061 child =
new ChildT(xyz, tile.value, tile.active);
2062 setChild(iter, *
child);
2066 acc.insert(xyz,
child);
2067 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
2072template<
typename ChildT>
2076 MapCIter iter = this->findCoord(xyz);
2077 if (iter == mTable.end()) {
2078 value = mBackground;
2080 }
else if (isChild(iter)) {
2081 return getChild(iter).probeValue(xyz,
value);
2083 value = getTile(iter).value;
2084 return isTileOn(iter);
2087template<
typename ChildT>
2088template<
typename AccessorT>
2092 MapCIter iter = this->findCoord(xyz);
2093 if (iter == mTable.end()) {
2094 value = mBackground;
2096 }
else if (isChild(iter)) {
2097 acc.insert(xyz, &getChild(iter));
2098 return getChild(iter).probeValueAndCache(xyz,
value, acc);
2100 value = getTile(iter).value;
2101 return isTileOn(iter);
2108template<
typename ChildT>
2112 if (bbox.
empty())
return;
2117 for (
int x = bbox.
min().
x(); x <= bbox.
max().
x(); x = tileMax.
x() + 1) {
2119 for (
int y = bbox.
min().
y(); y <= bbox.
max().
y(); y = tileMax.
y() + 1) {
2121 for (
int z = bbox.
min().
z(); z <= bbox.
max().
z(); z = tileMax.
z() + 1) {
2125 Coord tileMin = coordToKey(xyz);
2126 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2132 ChildT*
child =
nullptr;
2133 MapIter iter = this->findKey(tileMin);
2134 if (iter == mTable.end()) {
2137 child =
new ChildT(xyz, mBackground);
2138 mTable[tileMin] = NodeStruct(*
child);
2139 }
else if (isTile(iter)) {
2142 const Tile& tile = getTile(iter);
2143 child =
new ChildT(xyz, tile.value, tile.active);
2144 mTable[tileMin] = NodeStruct(*
child);
2145 }
else if (isChild(iter)) {
2146 child = &getChild(iter);
2157 MapIter iter = this->findOrAddCoord(tileMin);
2158 setTile(iter, Tile(
value, active));
2166template<
typename ChildT>
2170 if (bbox.
empty())
return;
2172 if (active && mTable.empty()) {
2175 sparseFill(bbox,
value, active);
2176 voxelizeActiveTiles(
true);
2182 Coord xyz, tileMin, tileMax;
2183 for (
int x = bbox.
min().
x(); x <= bbox.
max().
x(); x = tileMax.
x() + 1) {
2185 for (
int y = bbox.
min().
y(); y <= bbox.
max().
y(); y = tileMax.
y() + 1) {
2187 for (
int z = bbox.
min().
z(); z <= bbox.
max().
z(); z = tileMax.
z() + 1) {
2191 tileMin = coordToKey(xyz);
2192 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2196 const auto iter = findOrAddCoord(tileMin);
2201 const auto& tile = getTile(iter);
2202 auto*
child =
new ChildT{tileMin, tile.value, tile.active};
2203 setChild(iter, *
child);
2206 getChild(iter).denseFill(bbox,
value, active);
2216template<
typename ChildT>
2224 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2225 if (this->isTileOff(i))
continue;
2226 ChildT*
child = i->second.child;
2227 if (
child ==
nullptr) {
2230 child =
new ChildT{i->first, this->getTile(i).value,
true};
2231 i->second.child =
child;
2233 child->voxelizeActiveTiles(threaded);
2241template<
typename ChildT>
2242template<
typename DenseT>
2246 using DenseValueType =
typename DenseT::ValueType;
2248 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2249 const Coord&
min = dense.bbox().min();
2251 for (
Coord xyz = bbox.
min(); xyz[0] <= bbox.
max()[0]; xyz[0] = nodeBBox.
max()[0] + 1) {
2252 for (xyz[1] = bbox.
min()[1]; xyz[1] <= bbox.
max()[1]; xyz[1] = nodeBBox.
max()[1] + 1) {
2253 for (xyz[2] = bbox.
min()[2]; xyz[2] <= bbox.
max()[2]; xyz[2] = nodeBBox.
max()[2] + 1) {
2261 MapCIter iter = this->findKey(nodeBBox.
min());
2262 if (iter != mTable.end() && isChild(iter)) {
2263 getChild(iter).copyToDense(sub, dense);
2265 const ValueType value = iter==mTable.end() ? mBackground : getTile(iter).value;
2267 DenseValueType* a0 = dense.data() + zStride*sub.
min()[2];
2268 for (
Int32 x=sub.
min()[0], ex=sub.
max()[0]+1; x<ex; ++x) {
2269 DenseValueType* a1 = a0 + x*xStride;
2270 for (
Int32 y=sub.
min()[1], ey=sub.
max()[1]+1; y<ey; ++y) {
2271 DenseValueType* a2 = a1 + y*yStride;
2272 for (
Int32 z=sub.
min()[2], ez=sub.
max()[2]+1; z<ez; ++z, a2 += zStride) {
2273 *a2 = DenseValueType(
value);
2286template<
typename ChildT>
2291 os.write(
reinterpret_cast<const char*
>(&mBackground),
sizeof(
ValueType));
2294 os.write(
reinterpret_cast<const char*
>(&truncatedVal),
sizeof(
ValueType));
2298 const Index numTiles = this->getTileCount(), numChildren = this->childCount();
2299 os.write(
reinterpret_cast<const char*
>(&numTiles),
sizeof(
Index));
2300 os.write(
reinterpret_cast<const char*
>(&numChildren),
sizeof(
Index));
2302 if (numTiles == 0 && numChildren == 0)
return false;
2305 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2306 if (isChild(i))
continue;
2307 os.write(
reinterpret_cast<const char*
>(i->first.asPointer()), 3 *
sizeof(
Int32));
2308 os.write(
reinterpret_cast<const char*
>(&getTile(i).
value),
sizeof(
ValueType));
2309 os.write(
reinterpret_cast<const char*
>(&getTile(i).active),
sizeof(
bool));
2312 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2313 if (isTile(i))
continue;
2314 os.write(
reinterpret_cast<const char*
>(i->first.asPointer()), 3 *
sizeof(
Int32));
2315 getChild(i).writeTopology(os, toHalf);
2322template<
typename ChildT>
2334 is.read(
reinterpret_cast<char*
>(&mBackground),
sizeof(
ValueType));
2336 is.read(
reinterpret_cast<char*
>(&inside),
sizeof(
ValueType));
2341 Coord rangeMin, rangeMax;
2343 is.read(
reinterpret_cast<char*
>(rangeMax.
asPointer()), 3 *
sizeof(
Int32));
2346 Index tableSize = 0, log2Dim[4] = { 0, 0, 0, 0 };
2348 for (
int i = 0; i < 3; ++i) {
2349 offset[i] = rangeMin[i] >> ChildT::TOTAL;
2350 rangeMin[i] = offset[i] << ChildT::TOTAL;
2352 tableSize += log2Dim[i];
2353 rangeMax[i] = (((1 << log2Dim[i]) + offset[i]) << ChildT::TOTAL) - 1;
2355 log2Dim[3] = log2Dim[1] + log2Dim[2];
2356 tableSize = 1U << tableSize;
2364 for (
Index i = 0; i < tableSize; ++i) {
2368 origin[0] = (n >> log2Dim[3]) + offset[0];
2369 n &= (1U << log2Dim[3]) - 1;
2370 origin[1] = (n >> log2Dim[2]) + offset[1];
2371 origin[2] = (n & ((1U << log2Dim[2]) - 1)) + offset[1];
2372 origin <<= ChildT::TOTAL;
2374 if (childMask.isOn(i)) {
2377 child->readTopology(is);
2378 mTable[origin] = NodeStruct(*
child);
2385 mTable[origin] = NodeStruct(Tile(
value, valueMask.
isOn(i)));
2394 is.read(
reinterpret_cast<char*
>(&mBackground),
sizeof(
ValueType));
2397 Index numTiles = 0, numChildren = 0;
2398 is.read(
reinterpret_cast<char*
>(&numTiles),
sizeof(
Index));
2399 is.read(
reinterpret_cast<char*
>(&numChildren),
sizeof(
Index));
2401 if (numTiles == 0 && numChildren == 0)
return false;
2408 for (
Index n = 0; n < numTiles; ++n) {
2409 is.read(
reinterpret_cast<char*
>(vec), 3 *
sizeof(
Int32));
2411 is.read(
reinterpret_cast<char*
>(&active),
sizeof(
bool));
2412 mTable[
Coord(vec)] = NodeStruct(Tile(
value, active));
2416 for (
Index n = 0; n < numChildren; ++n) {
2417 is.read(
reinterpret_cast<char*
>(vec), 3 *
sizeof(
Int32));
2420 child->readTopology(is, fromHalf);
2428template<
typename ChildT>
2432 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2433 if (isChild(i)) getChild(i).writeBuffers(os, toHalf);
2438template<
typename ChildT>
2442 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2443 if (isChild(i)) getChild(i).readBuffers(is, fromHalf);
2448template<
typename ChildT>
2452 const Tile bgTile(mBackground,
false);
2454 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2460 ChildT&
child = getChild(i);
2461 child.readBuffers(is, clipBBox, fromHalf);
2465 this->
clip(clipBBox);
2472template<
typename ChildT>
2476 const Tile bgTile(mBackground,
false);
2480 MapType copyOfTable(mTable);
2481 for (MapIter i = copyOfTable.begin(), e = copyOfTable.end(); i != e; ++i) {
2482 const Coord& xyz = i->first;
2486 setTile(this->findCoord(xyz), bgTile);
2488 }
else if (!clipBBox.
isInside(tileBBox)) {
2492 getChild(i).clip(clipBBox, mBackground);
2497 const Tile& origTile = getTile(i);
2498 setTile(this->findCoord(xyz), bgTile);
2499 this->sparseFill(tileBBox, origTile.value, origTile.active);
2512template<
typename ChildT>
2518 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2519 if (this->isTile(i))
continue;
2520 this->getChild(i).prune(tolerance);
2521 if (this->getChild(i).isConstant(
value, state, tolerance)) {
2522 this->setTile(i, Tile(
value, state));
2525 this->eraseBackgroundTiles();
2532template<
typename ChildT>
2533template<
typename NodeT>
2538 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2540 MapIter iter = this->findCoord(xyz);
2541 if (iter == mTable.end() || isTile(iter))
return nullptr;
2543 ?
reinterpret_cast<NodeT*
>(&stealChild(iter, Tile(
value, state)))
2544 : getChild(iter).template stealNode<NodeT>(xyz,
value, state);
2552template<
typename ChildT>
2556 if (leaf ==
nullptr)
return;
2557 ChildT*
child =
nullptr;
2558 const Coord& xyz = leaf->origin();
2559 MapIter iter = this->findCoord(xyz);
2560 if (iter == mTable.end()) {
2561 if (ChildT::LEVEL>0) {
2562 child =
new ChildT(xyz, mBackground,
false);
2564 child =
reinterpret_cast<ChildT*
>(leaf);
2566 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
2567 }
else if (isChild(iter)) {
2568 if (ChildT::LEVEL>0) {
2569 child = &getChild(iter);
2571 child =
reinterpret_cast<ChildT*
>(leaf);
2572 setChild(iter, *
child);
2575 if (ChildT::LEVEL>0) {
2576 child =
new ChildT(xyz, getTile(iter).
value, isTileOn(iter));
2578 child =
reinterpret_cast<ChildT*
>(leaf);
2580 setChild(iter, *
child);
2582 child->addLeaf(leaf);
2586template<
typename ChildT>
2587template<
typename AccessorT>
2591 if (leaf ==
nullptr)
return;
2592 ChildT*
child =
nullptr;
2593 const Coord& xyz = leaf->origin();
2594 MapIter iter = this->findCoord(xyz);
2595 if (iter == mTable.end()) {
2596 if (ChildT::LEVEL>0) {
2597 child =
new ChildT(xyz, mBackground,
false);
2599 child =
reinterpret_cast<ChildT*
>(leaf);
2601 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
2602 }
else if (isChild(iter)) {
2603 if (ChildT::LEVEL>0) {
2604 child = &getChild(iter);
2606 child =
reinterpret_cast<ChildT*
>(leaf);
2607 setChild(iter, *
child);
2610 if (ChildT::LEVEL>0) {
2611 child =
new ChildT(xyz, getTile(iter).
value, isTileOn(iter));
2613 child =
reinterpret_cast<ChildT*
>(leaf);
2615 setChild(iter, *
child);
2617 acc.insert(xyz,
child);
2618 child->addLeafAndCache(leaf, acc);
2621template<
typename ChildT>
2625 if (!
child)
return false;
2627 MapIter iter = this->findCoord(xyz);
2628 if (iter == mTable.end()) {
2629 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
2631 setChild(iter, *
child);
2636template<
typename ChildT>
2640 MapIter iter = this->findCoord(xyz);
2641 if (iter == mTable.end()) {
2642 mTable[this->coordToKey(xyz)] = NodeStruct(Tile(
value, state));
2644 setTile(iter, Tile(
value, state));
2648template<
typename ChildT>
2653 if (LEVEL >= level) {
2654 MapIter iter = this->findCoord(xyz);
2655 if (iter == mTable.end()) {
2656 if (LEVEL > level) {
2657 ChildT*
child =
new ChildT(xyz, mBackground,
false);
2658 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
2661 mTable[this->coordToKey(xyz)] = NodeStruct(Tile(
value, state));
2663 }
else if (isChild(iter)) {
2664 if (LEVEL > level) {
2665 getChild(iter).addTile(level, xyz,
value, state);
2667 setTile(iter, Tile(
value, state));
2670 if (LEVEL > level) {
2671 ChildT*
child =
new ChildT(xyz, getTile(iter).
value, isTileOn(iter));
2672 setChild(iter, *
child);
2675 setTile(iter, Tile(
value, state));
2682template<
typename ChildT>
2683template<
typename AccessorT>
2686 bool state, AccessorT& acc)
2688 if (LEVEL >= level) {
2689 MapIter iter = this->findCoord(xyz);
2690 if (iter == mTable.end()) {
2691 if (LEVEL > level) {
2692 ChildT*
child =
new ChildT(xyz, mBackground,
false);
2693 acc.insert(xyz,
child);
2694 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
2695 child->addTileAndCache(level, xyz,
value, state, acc);
2697 mTable[this->coordToKey(xyz)] = NodeStruct(Tile(
value, state));
2699 }
else if (isChild(iter)) {
2700 if (LEVEL > level) {
2701 ChildT*
child = &getChild(iter);
2702 acc.insert(xyz,
child);
2703 child->addTileAndCache(level, xyz,
value, state, acc);
2705 setTile(iter, Tile(
value, state));
2708 if (LEVEL > level) {
2709 ChildT*
child =
new ChildT(xyz, getTile(iter).
value, isTileOn(iter));
2710 acc.insert(xyz,
child);
2711 setChild(iter, *
child);
2712 child->addTileAndCache(level, xyz,
value, state, acc);
2714 setTile(iter, Tile(
value, state));
2724template<
typename ChildT>
2725inline typename ChildT::LeafNodeType*
2728 ChildT*
child =
nullptr;
2729 MapIter iter = this->findCoord(xyz);
2730 if (iter == mTable.end()) {
2731 child =
new ChildT(xyz, mBackground,
false);
2732 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
2733 }
else if (isChild(iter)) {
2734 child = &getChild(iter);
2736 child =
new ChildT(xyz, getTile(iter).
value, isTileOn(iter));
2737 setChild(iter, *
child);
2739 return child->touchLeaf(xyz);
2743template<
typename ChildT>
2744template<
typename AccessorT>
2745inline typename ChildT::LeafNodeType*
2748 ChildT*
child =
nullptr;
2749 MapIter iter = this->findCoord(xyz);
2750 if (iter == mTable.end()) {
2751 child =
new ChildT(xyz, mBackground,
false);
2752 mTable[this->coordToKey(xyz)] = NodeStruct(*
child);
2753 }
else if (isChild(iter)) {
2754 child = &getChild(iter);
2756 child =
new ChildT(xyz, getTile(iter).
value, isTileOn(iter));
2757 setChild(iter, *
child);
2759 acc.insert(xyz,
child);
2760 return child->touchLeafAndCache(xyz, acc);
2767template<
typename ChildT>
2768template<
typename NodeT>
2773 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2775 MapIter iter = this->findCoord(xyz);
2776 if (iter == mTable.end() || isTile(iter))
return nullptr;
2777 ChildT*
child = &getChild(iter);
2779 ?
reinterpret_cast<NodeT*
>(
child)
2780 :
child->template probeNode<NodeT>(xyz);
2785template<
typename ChildT>
2786template<
typename NodeT>
2791 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2793 MapCIter iter = this->findCoord(xyz);
2794 if (iter == mTable.end() || isTile(iter))
return nullptr;
2795 const ChildT*
child = &getChild(iter);
2797 ?
reinterpret_cast<const NodeT*
>(
child)
2798 :
child->template probeConstNode<NodeT>(xyz);
2803template<
typename ChildT>
2804inline typename ChildT::LeafNodeType*
2807 return this->
template probeNode<LeafNodeType>(xyz);
2811template<
typename ChildT>
2812inline const typename ChildT::LeafNodeType*
2815 return this->
template probeConstNode<LeafNodeType>(xyz);
2819template<
typename ChildT>
2820template<
typename AccessorT>
2821inline typename ChildT::LeafNodeType*
2824 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
2828template<
typename ChildT>
2829template<
typename AccessorT>
2830inline const typename ChildT::LeafNodeType*
2833 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
2837template<
typename ChildT>
2838template<
typename AccessorT>
2839inline const typename ChildT::LeafNodeType*
2842 return this->probeConstLeafAndCache(xyz, acc);
2846template<
typename ChildT>
2847template<
typename NodeT,
typename AccessorT>
2852 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2854 MapIter iter = this->findCoord(xyz);
2855 if (iter == mTable.end() || isTile(iter))
return nullptr;
2856 ChildT*
child = &getChild(iter);
2857 acc.insert(xyz,
child);
2859 ?
reinterpret_cast<NodeT*
>(
child)
2860 :
child->template probeNodeAndCache<NodeT>(xyz, acc);
2865template<
typename ChildT>
2866template<
typename NodeT,
typename AccessorT>
2871 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2873 MapCIter iter = this->findCoord(xyz);
2874 if (iter == mTable.end() || isTile(iter))
return nullptr;
2875 const ChildT*
child = &getChild(iter);
2876 acc.insert(xyz,
child);
2878 ?
reinterpret_cast<const NodeT*
>(
child)
2879 :
child->template probeConstNodeAndCache<NodeT>(xyz, acc);
2886template<
typename ChildT>
2887template<
typename ArrayT>
2891 using NodePtr =
typename ArrayT::value_type;
2893 "argument to getNodes() must be a pointer array");
2894 using NodeType =
typename std::remove_pointer<NodePtr>::type;
2895 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
2896 static_assert(NodeChainType::template Contains<NonConstNodeType>,
2897 "can't extract non-const nodes from a const tree");
2898 using ArrayChildT =
typename std::conditional<
2901 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
2902 if (ChildT*
child = iter->second.child) {
2905 array.push_back(
reinterpret_cast<NodePtr
>(iter->second.child));
2907 child->getNodes(array);
2914template<
typename ChildT>
2915template<
typename ArrayT>
2919 using NodePtr =
typename ArrayT::value_type;
2921 "argument to getNodes() must be a pointer array");
2922 using NodeType =
typename std::remove_pointer<NodePtr>::type;
2924 "argument to getNodes() must be an array of const node pointers");
2925 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
2926 static_assert(NodeChainType::template Contains<NonConstNodeType>,
2927 "can't extract non-const nodes from a const tree");
2929 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
2933 array.push_back(
reinterpret_cast<NodePtr
>(iter->second.child));
2935 child->getNodes(array);
2944template<
typename ChildT>
2945template<
typename ArrayT>
2949 using NodePtr =
typename ArrayT::value_type;
2951 "argument to stealNodes() must be a pointer array");
2952 using NodeType =
typename std::remove_pointer<NodePtr>::type;
2953 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
2954 static_assert(NodeChainType::template Contains<NonConstNodeType>,
2955 "can't extract non-const nodes from a const tree");
2956 using ArrayChildT =
typename std::conditional<
2959 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
2960 if (ChildT*
child = iter->second.child) {
2963 array.push_back(
reinterpret_cast<NodePtr
>(&stealChild(iter, Tile(
value, state))));
2976template<
typename ChildT>
2977template<MergePolicy Policy>
2987 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
2988 MapIter j = mTable.find(i->first);
2989 if (other.isChild(i)) {
2990 if (j == mTable.end()) {
2992 child.resetBackground(other.mBackground, mBackground);
2993 mTable[i->first] = NodeStruct(
child);
2994 }
else if (isTile(j)) {
2997 child.resetBackground(other.mBackground, mBackground);
3001 getChild(j).template merge<MERGE_ACTIVE_STATES>(getChild(i),
3002 other.mBackground, mBackground);
3004 }
else if (other.isTileOn(i)) {
3005 if (j == mTable.end()) {
3006 mTable[i->first] = i->second;
3007 }
else if (!isTileOn(j)) {
3009 setTile(j, Tile(other.getTile(i).value,
true));
3016 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3017 MapIter j = mTable.find(i->first);
3018 if (other.isChild(i)) {
3019 if (j == mTable.end()) {
3021 child.resetBackground(other.mBackground, mBackground);
3022 mTable[i->first] = NodeStruct(
child);
3023 }
else if (isTile(j)) {
3025 child.resetBackground(other.mBackground, mBackground);
3028 getChild(j).template merge<MERGE_NODES>(
3029 getChild(i), other.mBackground, mBackground);
3036 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3037 MapIter j = mTable.find(i->first);
3038 if (other.isChild(i)) {
3039 if (j == mTable.end()) {
3042 child.resetBackground(other.mBackground, mBackground);
3043 mTable[i->first] = NodeStruct(
child);
3044 }
else if (isTile(j)) {
3047 child.resetBackground(other.mBackground, mBackground);
3048 const Tile tile = getTile(j);
3052 child.template merge<MERGE_ACTIVE_STATES_AND_NODES>(
3053 tile.value, tile.active);
3057 getChild(j).template merge<MERGE_ACTIVE_STATES_AND_NODES>(getChild(i),
3058 other.mBackground, mBackground);
3060 }
else if (other.isTileOn(i)) {
3061 if (j == mTable.end()) {
3063 mTable[i->first] = i->second;
3064 }
else if (isTileOff(j)) {
3066 setTile(j, Tile(other.getTile(i).value,
true));
3067 }
else if (isChild(j)) {
3069 const Tile& tile = getTile(i);
3070 getChild(j).template merge<MERGE_ACTIVE_STATES_AND_NODES>(
3071 tile.value, tile.active);
3088template<
typename ChildT>
3089template<
typename OtherChildType>
3094 using OtherCIterT =
typename OtherRootT::MapCIter;
3096 enforceSameConfiguration(other);
3098 for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3099 MapIter j = mTable.find(i->first);
3100 if (other.isChild(i)) {
3101 if (j == mTable.end()) {
3102 mTable[i->first] = NodeStruct(
3103 *(
new ChildT(other.getChild(i), mBackground,
TopologyCopy())));
3104 }
else if (this->isChild(j)) {
3105 this->getChild(j).topologyUnion(other.getChild(i), preserveTiles);
3107 if (!preserveTiles || this->isTileOff(j)) {
3108 ChildT*
child =
new ChildT(
3109 other.getChild(i), this->getTile(j).value,
TopologyCopy());
3110 if (this->isTileOn(j))
child->setValuesOn();
3111 this->setChild(j, *
child);
3114 }
else if (other.isTileOn(i)) {
3115 if (j == mTable.end()) {
3116 mTable[i->first] = NodeStruct(Tile(mBackground,
true));
3117 }
else if (this->isChild(j)) {
3118 this->getChild(j).setValuesOn();
3119 }
else if (this->isTileOff(j)) {
3120 this->setTile(j, Tile(this->getTile(j).
value,
true));
3126template<
typename ChildT>
3127template<
typename OtherChildType>
3132 using OtherCIterT =
typename OtherRootT::MapCIter;
3134 enforceSameConfiguration(other);
3136 std::set<Coord> tmp;
3137 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
3138 OtherCIterT j = other.mTable.find(i->first);
3139 if (this->isChild(i)) {
3140 if (j == other.mTable.end() || other.isTileOff(j)) {
3141 tmp.insert(i->first);
3142 }
else if (other.isChild(j)) {
3143 this->getChild(i).topologyIntersection(other.getChild(j), mBackground);
3145 }
else if (this->isTileOn(i)) {
3146 if (j == other.mTable.end() || other.isTileOff(j)) {
3147 this->setTile(i, Tile(this->getTile(i).
value,
false));
3148 }
else if (other.isChild(j)) {
3150 new ChildT(other.getChild(j), this->getTile(i).value,
TopologyCopy());
3151 this->setChild(i, *
child);
3155 for (std::set<Coord>::iterator i = tmp.begin(), e = tmp.end(); i != e; ++i) {
3156 MapIter it = this->findCoord(*i);
3157 setTile(it, Tile());
3162template<
typename ChildT>
3163template<
typename OtherChildType>
3168 using OtherCIterT =
typename OtherRootT::MapCIter;
3170 enforceSameConfiguration(other);
3172 for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3173 MapIter j = mTable.find(i->first);
3174 if (other.isChild(i)) {
3175 if (j == mTable.end() || this->isTileOff(j)) {
3177 }
else if (this->isChild(j)) {
3178 this->getChild(j).topologyDifference(other.getChild(i), mBackground);
3179 }
else if (this->isTileOn(j)) {
3181 ChildT*
child =
new ChildT(j->first, this->getTile(j).value,
true);
3182 child->topologyDifference(other.getChild(i), mBackground);
3183 this->setChild(j, *
child);
3185 }
else if (other.isTileOn(i)) {
3186 if (j == mTable.end() || this->isTileOff(j)) {
3188 }
else if (this->isChild(j)) {
3191 }
else if (this->isTileOn(j)) {
3192 this->setTile(j, Tile(this->getTile(j).
value,
false));
3201template<
typename ChildT>
3202template<
typename CombineOp>
3209 this->insertKeys(keys);
3210 other.insertKeys(keys);
3212 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3213 MapIter iter = findOrAddCoord(*i), otherIter = other.findOrAddCoord(*i);
3214 if (isTile(iter) && isTile(otherIter)) {
3218 .setAIsActive(isTileOn(iter))
3219 .setBRef(getTile(otherIter).
value)
3220 .setBIsActive(isTileOn(otherIter)));
3223 }
else if (isChild(iter) && isTile(otherIter)) {
3225 ChildT&
child = getChild(iter);
3226 child.combine(getTile(otherIter).
value, isTileOn(otherIter), op);
3228 }
else if (isTile(iter) && isChild(otherIter)) {
3233 ChildT&
child = getChild(otherIter);
3234 child.combine(getTile(iter).
value, isTileOn(iter), swappedOp);
3237 setChild(iter, stealChild(otherIter, Tile()));
3241 ChildT &
child = getChild(iter), &otherChild = getChild(otherIter);
3242 child.combine(otherChild, op);
3244 if (
prune && isChild(iter)) getChild(iter).prune();
3249 mBackground = args.
result();
3261template<
typename CombineOp,
typename RootT,
typename OtherRootT,
bool Compatible = false>
3264 static inline void combine2(RootT&
self,
const RootT&,
const OtherRootT& other1,
3269 self.enforceSameConfiguration(other1);
3270 self.enforceCompatibleValueTypes(other1);
3272 std::ostringstream ostr;
3273 ostr <<
"cannot combine a " <<
typeid(OtherRootT).name()
3274 <<
" into a " <<
typeid(RootT).name();
3280template<
typename CombineOp,
typename RootT,
typename OtherRootT>
3283 static inline void combine2(RootT&
self,
const RootT& other0,
const OtherRootT& other1,
3284 CombineOp& op,
bool prune)
3286 self.doCombine2(other0, other1, op,
prune);
3291template<
typename ChildT>
3292template<
typename CombineOp,
typename OtherRootNode>
3295 CombineOp& op,
bool prune)
3297 using OtherValueType =
typename OtherRootNode::ValueType;
3301 *
this, other0, other1, op,
prune);
3305template<
typename ChildT>
3306template<
typename CombineOp,
typename OtherRootNode>
3309 CombineOp& op,
bool prune)
3311 enforceSameConfiguration(other1);
3313 using OtherValueT =
typename OtherRootNode::ValueType;
3314 using OtherTileT =
typename OtherRootNode::Tile;
3315 using OtherNodeStructT =
typename OtherRootNode::NodeStruct;
3316 using OtherMapCIterT =
typename OtherRootNode::MapCIter;
3321 other0.insertKeys(keys);
3322 other1.insertKeys(keys);
3324 const NodeStruct bg0(Tile(other0.mBackground,
false));
3325 const OtherNodeStructT bg1(OtherTileT(other1.mBackground,
false));
3327 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3328 MapIter thisIter = this->findOrAddCoord(*i);
3329 MapCIter iter0 = other0.findKey(*i);
3330 OtherMapCIterT iter1 = other1.findKey(*i);
3331 const NodeStruct& ns0 = (iter0 != other0.mTable.end()) ? iter0->second : bg0;
3332 const OtherNodeStructT& ns1 = (iter1 != other1.mTable.end()) ? iter1->second : bg1;
3333 if (ns0.isTile() && ns1.isTile()) {
3336 op(args.
setARef(ns0.tile.value)
3342 if (!isChild(thisIter)) {
3344 const Coord& childOrigin =
3345 ns0.isChild() ? ns0.child->origin() : ns1.child->origin();
3346 setChild(thisIter, *(
new ChildT(childOrigin, getTile(thisIter).
value)));
3348 ChildT&
child = getChild(thisIter);
3353 child.combine2(ns0.tile.value, *ns1.child, ns0.isTileOn(), op);
3354 }
else if (ns1.isTile()) {
3357 child.combine2(*ns0.child, ns1.tile.value, ns1.isTileOn(), op);
3361 child.combine2(*ns0.child, *ns1.child, op);
3364 if (
prune && isChild(thisIter)) getChild(thisIter).prune();
3368 op(args.
setARef(other0.mBackground).
setBRef(other1.mBackground));
3369 mBackground = args.
result();
3376template<
typename ChildT>
3377template<
typename BBoxOp>
3381 const bool descent = op.template descent<LEVEL>();
3382 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
3383 if (this->isTileOff(i))
continue;
3384 if (this->isChild(i) && descent) {
3385 this->getChild(i).visitActiveBBox(op);
3393template<
typename ChildT>
3394template<
typename VisitorOp>
3398 doVisit<RootNode, VisitorOp, ChildAllIter>(*
this, op);
3402template<
typename ChildT>
3403template<
typename VisitorOp>
3407 doVisit<const RootNode, VisitorOp, ChildAllCIter>(*
this, op);
3411template<
typename ChildT>
3412template<
typename RootNodeT,
typename VisitorOp,
typename ChildAllIterT>
3416 typename RootNodeT::ValueType val;
3417 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
3418 if (op(iter))
continue;
3419 if (
typename ChildAllIterT::ChildNodeType*
child = iter.probeChild(val)) {
3429template<
typename ChildT>
3430template<
typename OtherRootNodeType,
typename VisitorOp>
3435 typename OtherRootNodeType::ChildAllIter>(*
this, other, op);
3439template<
typename ChildT>
3440template<
typename OtherRootNodeType,
typename VisitorOp>
3445 typename OtherRootNodeType::ChildAllCIter>(*
this, other, op);
3449template<
typename ChildT>
3452 typename OtherRootNodeT,
3454 typename ChildAllIterT,
3455 typename OtherChildAllIterT>
3459 enforceSameConfiguration(other);
3461 typename RootNodeT::ValueType val;
3462 typename OtherRootNodeT::ValueType otherVal;
3467 RootNodeT copyOfSelf(
self.mBackground);
3468 copyOfSelf.mTable =
self.mTable;
3469 OtherRootNodeT copyOfOther(other.mBackground);
3470 copyOfOther.mTable = other.mTable;
3474 self.insertKeys(keys);
3475 other.insertKeys(keys);
3476 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3477 copyOfSelf.findOrAddCoord(*i);
3478 copyOfOther.findOrAddCoord(*i);
3481 ChildAllIterT iter = copyOfSelf.beginChildAll();
3482 OtherChildAllIterT otherIter = copyOfOther.beginChildAll();
3484 for ( ; iter && otherIter; ++iter, ++otherIter)
3486 const size_t skipBranch =
static_cast<size_t>(op(iter, otherIter));
3488 typename ChildAllIterT::ChildNodeType*
child =
3489 (skipBranch & 1U) ?
nullptr : iter.probeChild(val);
3490 typename OtherChildAllIterT::ChildNodeType* otherChild =
3491 (skipBranch & 2U) ?
nullptr : otherIter.probeChild(otherVal);
3493 if (
child !=
nullptr && otherChild !=
nullptr) {
3494 child->visit2Node(*otherChild, op);
3495 }
else if (
child !=
nullptr) {
3496 child->visit2(otherIter, op);
3497 }
else if (otherChild !=
nullptr) {
3498 otherChild->visit2(iter, op,
true);
3503 copyOfSelf.eraseBackgroundTiles();
3504 copyOfOther.eraseBackgroundTiles();
3508 self.resetTable(copyOfSelf.mTable);
3509 other.resetTable(copyOfOther.mTable);
ValueT value
Definition: GridBuilder.h:1287
ChildT * child
Definition: GridBuilder.h:1286
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Definition: NanoVDB.h:860
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:451
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: Types.h:503
const AValueType & result() const
Get the output value.
Definition: Types.h:495
CombineArgs & setBIsActive(bool b)
Set the active state of the B value.
Definition: Types.h:519
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
Definition: Types.h:505
bool resultIsActive() const
Definition: Types.h:514
CombineArgs & setAIsActive(bool b)
Set the active state of the A value.
Definition: Types.h:517
Tag dispatch class that distinguishes constructors during file input.
Definition: Types.h:570
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:564
Definition: Exceptions.h:64
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:248
void translate(const Coord &t)
Translate this bounding box by (tx, ty, tz).
Definition: Coord.h:457
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:417
bool empty() const
Return true if this bounding box is empty (i.e., encloses no coordinates).
Definition: Coord.h:355
const Coord & min() const
Definition: Coord.h:320
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition: Coord.h:411
const Coord & max() const
Definition: Coord.h:321
static CoordBBox inf()
Return an "infinite" bounding box, as defined by the Coord value range.
Definition: Coord.h:318
bool isInside(const Coord &xyz) const
Return true if point (x, y, z) is inside this bounding box.
Definition: Coord.h:399
void intersect(const CoordBBox &bbox)
Intersect this bounding box with the given bounding box.
Definition: Coord.h:443
static CoordBBox createCube(const Coord &min, ValueType dim)
Definition: Coord.h:312
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:25
Int32 y() const
Definition: Coord.h:131
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:91
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition: Coord.h:175
const Int32 * asPointer() const
Definition: Coord.h:141
Int32 x() const
Definition: Coord.h:130
Coord & setZ(Int32 z)
Definition: Coord.h:81
Coord & setY(Int32 y)
Definition: Coord.h:80
static bool lessThan(const Coord &a, const Coord &b)
Definition: Coord.h:208
Int32 z() const
Definition: Coord.h:132
Coord & setX(Int32 x)
Definition: Coord.h:79
void read(std::istream &is)
Definition: Coord.h:219
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:1884
DenseIter< RootNode, MapIter, ChildType, ValueType > ChildAllIter
Definition: RootNode.h:364
void visit(VisitorOp &)
Definition: RootNode.h:3396
static bool hasSameConfiguration(const RootNode< OtherChildType > &other)
Return false if the other node's dimensions don't match this node's.
Definition: RootNode.h:1409
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:1735
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:464
bool isValueOn(const Coord &xyz) const
Definition: RootNode.h:1679
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:1349
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:2244
RootNode & operator=(const RootNode &other)
Copy a root node of the same type as this node.
Definition: RootNode.h:1173
Coord getMaxIndex() const
Return the largest index of the current tree.
Definition: RootNode.h:1341
ValueOffCIter cbeginValueOff() const
Definition: RootNode.h:386
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() but, if necessary, update the given accessor with pointers to the nodes along the...
Index32 transientData() const
Return the transient data value.
Definition: RootNode.h:410
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:2589
static Index getChildDim()
Definition: RootNode.h:457
RootNode & operator=(const RootNode< OtherChildType > &other)
Copy a root node of the same tree configuration as this node but a different ValueType.
Index32 nonLeafCount() const
Definition: RootNode.h:1564
void combine(RootNode &other, CombineOp &, bool prune=false)
Definition: RootNode.h:3204
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:2623
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition: RootNode.h:2889
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:2535
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition: RootNode.h:2218
LeafNodeType * touchLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as touchLeaf() but, if necessary, update the given accessor with pointers to the nodes along the...
ValueIter< RootNode, MapIter, ValueOffPred, ValueType > ValueOffIter
Definition: RootNode.h:369
ValueIter< RootNode, MapIter, ValueAllPred, ValueType > ValueAllIter
Definition: RootNode.h:371
void topologyUnion(const RootNode< OtherChildType > &other, const bool preserveTiles=false)
Union this tree's set of active values with the active values of the other tree, whose ValueType may ...
Definition: RootNode.h:3091
Index64 onLeafVoxelCount() const
Definition: RootNode.h:1622
const LeafNodeType * probeConstLeafAndCache(const Coord &xyz, AccessorT &acc) const
void clip(const CoordBBox &)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: RootNode.h:2474
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:2805
static bool hasCompatibleValueType(const RootNode< OtherChildType > &other)
Definition: RootNode.h:1441
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:2849
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:2514
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:1238
typename ChildType::LeafNodeType LeafNodeType
Definition: RootNode.h:42
size_t eraseBackgroundTiles()
Remove all background tiles.
Definition: RootNode.h:1272
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:3165
ValueIter< RootNode, MapIter, ValueOnPred, ValueType > ValueOnIter
Definition: RootNode.h:367
ValueOnCIter beginValueOn() const
Definition: RootNode.h:388
void merge(RootNode &other)
Efficiently merge another tree into this tree using one of several schemes.
Definition: RootNode.h:2979
ChildIter< RootNode, MapIter, ChildOnPred, ChildType > ChildOnIter
Definition: RootNode.h:360
Index64 offLeafVoxelCount() const
Definition: RootNode.h:1634
Index getWidth() const
Definition: RootNode.h:462
Index getTableSize() const
Return the number of entries in this node's table.
Definition: RootNode.h:460
void combine2(const RootNode &other0, const OtherRootNode &other1, CombineOp &op, bool prune=false)
Definition: RootNode.h:3294
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: RootNode.h:2016
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: RootNode.h:1925
size_t numBackgroundTiles() const
Return the number of background tiles.
Definition: RootNode.h:1260
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:1906
bool empty() const
Return true if this node's table is either empty or contains only background tiles.
Definition: RootNode.h:448
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Definition: RootNode.h:2813
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:2110
ValueOffCIter beginValueOff() const
Definition: RootNode.h:389
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: RootNode.h:1841
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:2554
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
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:2638
ChildAllIter beginChildAll()
Definition: RootNode.h:383
static Index getLevel()
Definition: RootNode.h:455
bool writeTopology(std::ostream &, bool toHalf=false) const
Definition: RootNode.h:2288
ValueIter< const RootNode, MapCIter, ValueAllPred, const ValueType > ValueAllCIter
Definition: RootNode.h:372
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Definition: RootNode.h:1699
const NodeT * probeConstNodeAndCache(const Coord &xyz, AccessorT &acc) const
Definition: RootNode.h:2868
bool probeValue(const Coord &xyz, ValueType &value) const
Definition: RootNode.h:2074
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:1771
ValueOnIter beginValueOn()
Definition: RootNode.h:391
void modifyValueAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: RootNode.h:1980
void visit2(OtherRootNodeType &other, VisitorOp &)
Definition: RootNode.h:3432
ChildOffCIter cbeginChildOff() const
Definition: RootNode.h:376
ChildOffIter beginChildOff()
Definition: RootNode.h:382
Index64 onVoxelCount() const
Definition: RootNode.h:1590
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:2685
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:1757
void writeBuffers(std::ostream &, bool toHalf=false) const
Definition: RootNode.h:2430
ValueOnCIter cbeginValueOn() const
Definition: RootNode.h:385
Index32 leafCount() const
Definition: RootNode.h:1552
const LeafNodeType * probeLeaf(const Coord &xyz) const
Index32 childCount() const
Definition: RootNode.h:1578
Index64 onTileCount() const
Definition: RootNode.h:1645
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:1948
void visitActiveBBox(BBoxOp &) const
Call the templated functor BBoxOp with bounding box information for all active tiles and leaf nodes i...
Definition: RootNode.h:3379
~RootNode()
Definition: RootNode.h:123
Index64 offVoxelCount() const
Definition: RootNode.h:1606
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:2726
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:1211
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:1362
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:2168
ChildAllCIter beginChildAll() const
Definition: RootNode.h:380
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Definition: RootNode.h:1794
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:3129
void setTransientData(Index32 transientData)
Set the transient data value.
Definition: RootNode.h:412
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:2947
Index getHeight() const
Definition: RootNode.h:463
void clear()
Definition: RootNode.h:1482
const LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc) const
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Definition: RootNode.h:2090
const NodeT * probeConstNode(const Coord &xyz) const
Definition: RootNode.h:2788
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:1493
const ValueType & background() const
Return this node's background value.
Definition: RootNode.h:430
static void getNodeLog2Dims(std::vector< Index > &dims)
Definition: RootNode.h:1325
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:539
Coord getMinIndex() const
Return the smallest index of the current tree.
Definition: RootNode.h:1334
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:1688
int getValueDepthAndCache(const Coord &xyz, AccessorT &) const
Definition: RootNode.h:1745
const ValueType & getValue(const Coord &xyz) const
Definition: RootNode.h:1711
void nodeCount(std::vector< Index32 > &vec) const
Definition: RootNode.h:1660
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
Definition: RootNode.h:1468
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:1865
void stealNodes(ArrayT &array)
Definition: RootNode.h:818
bool expand(const Coord &xyz)
Expand this node's table so that (x, y, z) is included in the index range.
Definition: RootNode.h:1311
void readBuffers(std::istream &, bool fromHalf=false)
Definition: RootNode.h:2440
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: RootNode.h:2043
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:2770
bool readTopology(std::istream &, bool fromHalf=false)
Definition: RootNode.h:2324
ChildIter< const RootNode, MapCIter, ChildOnPred, const ChildType > ChildOnCIter
Definition: RootNode.h:361
ValueAllIter beginValueAll()
Definition: RootNode.h:393
friend class RootNode
Definition: RootNode.h:903
Definition: NodeMasks.h:1067
bool isOn(Index32 i) const
Definition: NodeMasks.h:1331
void load(std::istream &is)
Definition: NodeMasks.h:1372
Vec3< T2 > operator*(T1 scalar, const Vec3< T2 > &vec)
Definition: NanoVDB.h:1163
BBox< Coord > CoordBBox
Definition: NanoVDB.h:1658
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 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 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
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: Types.h:54
uint32_t Index32
Definition: Types.h:52
int32_t Int32
Definition: Types.h:56
uint64_t Index64
Definition: Types.h:53
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:69
@ MERGE_ACTIVE_STATES
Definition: Types.h:389
@ MERGE_NODES
Definition: Types.h:390
@ MERGE_ACTIVE_STATES_AND_NODES
Definition: Types.h:391
@ OPENVDB_FILE_VERSION_ROOTNODE_MAP
Definition: version.h.in:236
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_THROW(exception, message)
Definition: Exceptions.h:74
CanConvertType<FromType, ToType>::value is true if a value of type ToType can be constructed from a v...
Definition: Types.h:285
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:1007
typename NodeChain< typename HeadT::ChildNodeType, HeadLevel-1 >::Type SubtreeT
Definition: RootNode.h:1008
typename SubtreeT::template Append< HeadT > Type
Definition: RootNode.h:1009
static void combine2(RootT &self, const RootT &other0, const OtherRootT &other1, CombineOp &op, bool prune)
Definition: RootNode.h:3283
Definition: RootNode.h:3263
static void combine2(RootT &self, const RootT &, const OtherRootT &other1, CombineOp &, bool)
Definition: RootNode.h:3264
static void copyWithValueConversion(RootT &self, const OtherRootT &other)
Definition: RootNode.h:1132
Definition: RootNode.h:1113
static void copyWithValueConversion(RootT &self, const OtherRootT &other)
Definition: RootNode.h:1114
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:1026
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202