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> 31 template<
typename HeadType,
int HeadLevel>
struct NodeChain;
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>
108 template<
typename OtherChildType>
120 template<
typename OtherChildType>
127 Tile():
value(zeroVal<ValueType>()), active(
false) {}
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 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;
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;
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;
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;
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);
541 this->fill(bbox, value, active);
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>
592 const ValueType& getValueAndCache(
const Coord& xyz, AccessorT&)
const;
597 template<
typename AccessorT>
598 bool isValueOnAndCache(
const Coord& xyz, AccessorT&)
const;
604 template<
typename AccessorT>
605 void setValueAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
611 template<
typename AccessorT>
612 void setValueOnlyAndCache(
const Coord& xyz,
const ValueType& value, 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>
634 void setValueOffAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
640 template<
typename AccessorT>
641 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&);
648 template<
typename AccessorT>
649 bool probeValueAndCache(
const Coord& xyz,
ValueType& value, AccessorT&)
const;
656 template<
typename AccessorT>
657 int getValueDepthAndCache(
const Coord& xyz, AccessorT&)
const;
675 template<
typename AccessorT>
686 template<
typename NodeT>
687 NodeT* stealNode(
const Coord& xyz,
const ValueType& value,
bool state);
694 bool addChild(ChildType*
child);
698 void addTile(
const Coord& xyz,
const ValueType& value,
bool state);
703 void addTile(
Index level,
const Coord& xyz,
const ValueType& value,
bool state);
707 template<
typename AccessorT>
708 void addTileAndCache(
Index level,
const Coord& xyz,
const ValueType&,
bool state, AccessorT&);
719 template<
typename AccessorT>
720 LeafNodeType* touchLeafAndCache(
const Coord& xyz, AccessorT& acc);
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;
744 const LeafNodeType* probeConstLeaf(
const Coord& xyz)
const;
751 template<
typename AccessorT>
752 LeafNodeType* probeLeafAndCache(
const Coord& xyz, AccessorT& acc);
753 template<
typename AccessorT>
754 const LeafNodeType* probeConstLeafAndCache(
const Coord& xyz, AccessorT& acc)
const;
755 template<
typename AccessorT>
756 const LeafNodeType* probeLeafAndCache(
const Coord& xyz, AccessorT& acc)
const;
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);
885 #if OPENVDB_ABI_VERSION_NUMBER >= 10 887 const Coord&
origin()
const {
return mOrigin; }
893 void setOrigin(
const Coord &origin);
908 void resetTable(MapType& table) { mTable.swap(table); table.clear(); }
909 void resetTable(
const MapType&)
const {}
912 Index getChildCount()
const;
913 Index getTileCount()
const;
914 Index getActiveTileCount()
const;
915 Index getInactiveTileCount()
const;
917 #if OPENVDB_ABI_VERSION_NUMBER < 10 919 static Coord coordToKey(
const Coord& xyz) {
return xyz & ~(ChildType::DIM - 1); }
922 Coord coordToKey(
const Coord& xyz)
const {
return (xyz - mOrigin) & ~(ChildType::DIM - 1); }
926 void insertKeys(CoordSet&)
const;
929 bool hasKey(
const Coord& key)
const {
return mTable.find(key) != mTable.end(); }
933 MapIter findKey(
const Coord& key) {
return mTable.find(key); }
934 MapCIter findKey(
const Coord& key)
const {
return mTable.find(key); }
939 MapIter findCoord(
const Coord& xyz) {
return mTable.find(coordToKey(xyz)); }
940 MapCIter findCoord(
const Coord& xyz)
const {
return mTable.find(coordToKey(xyz)); }
945 MapIter findOrAddCoord(
const Coord& xyz);
951 template<
typename OtherChildType>
959 template<
typename OtherChildType>
962 template<
typename CombineOp,
typename OtherRootNode >
963 void doCombine2(
const RootNode&,
const OtherRootNode&, CombineOp&,
bool prune);
967 #if OPENVDB_ABI_VERSION_NUMBER >= 10 970 #if OPENVDB_ABI_VERSION_NUMBER >= 9 1000 template<
typename HeadT,
int HeadLevel>
1003 using Type =
typename SubtreeT::template Append<HeadT>;
1007 template<
typename HeadT>
1019 template<
typename ChildT1,
typename NodeT2>
1021 static const bool value =
false;
1024 template<
typename ChildT1,
typename ChildT2>
1034 template<
typename ChildT>
1038 #if OPENVDB_ABI_VERSION_NUMBER >= 10
1046 template<
typename ChildT>
1049 : mBackground(background)
1050 #if OPENVDB_ABI_VERSION_NUMBER >= 10
1058 template<
typename ChildT>
1059 template<
typename OtherChildType>
1063 : mBackground(backgd)
1064 #if OPENVDB_ABI_VERSION_NUMBER >= 10
1065 , mOrigin(other.mOrigin)
1067 #if OPENVDB_ABI_VERSION_NUMBER >= 9
1068 , mTransientData(other.mTransientData)
1073 #if OPENVDB_ABI_VERSION_NUMBER >= 10 1074 if (mOrigin != Coord(0,0,0)) {
1079 enforceSameConfiguration(other);
1081 const Tile bgTile(backgd,
false), fgTile(foregd,
true);
1084 for (
typename OtherRootT::MapCIter i=other.mTable.begin(), e=other.mTable.end(); i != e; ++i) {
1085 mTable[i->first] = OtherRootT::isTile(i)
1086 ? NodeStruct(OtherRootT::isTileOn(i) ? fgTile : bgTile)
1087 : NodeStruct(*(
new ChildT(OtherRootT::getChild(i), backgd, foregd,
TopologyCopy())));
1092 template<
typename ChildT>
1093 template<
typename OtherChildType>
1097 : mBackground(backgd)
1098 #if OPENVDB_ABI_VERSION_NUMBER >= 10
1099 , mOrigin(other.mOrigin)
1101 #if OPENVDB_ABI_VERSION_NUMBER >= 9
1102 , mTransientData(other.mTransientData)
1107 #if OPENVDB_ABI_VERSION_NUMBER >= 10 1108 if (mOrigin != Coord(0,0,0)) {
1113 enforceSameConfiguration(other);
1115 const Tile bgTile(backgd,
false), fgTile(backgd,
true);
1117 for (
typename OtherRootT::MapCIter i=other.mTable.begin(), e=other.mTable.end(); i != e; ++i) {
1118 mTable[i->first] = OtherRootT::isTile(i)
1119 ? NodeStruct(OtherRootT::isTileOn(i) ? fgTile : bgTile)
1120 : NodeStruct(*(
new ChildT(OtherRootT::getChild(i), backgd,
TopologyCopy())));
1131 template<
typename RootT,
typename OtherRootT,
bool Compatible = false>
1138 self.enforceSameConfiguration(other);
1139 self.enforceCompatibleValueTypes(other);
1141 std::ostringstream ostr;
1142 ostr <<
"cannot convert a " <<
typeid(OtherRootT).name()
1143 <<
" to a " <<
typeid(RootT).name();
1149 template<
typename RootT,
typename OtherRootT>
1154 using ValueT =
typename RootT::ValueType;
1155 using ChildT =
typename RootT::ChildNodeType;
1156 using NodeStruct =
typename RootT::NodeStruct;
1157 using Tile =
typename RootT::Tile;
1158 using OtherValueT =
typename OtherRootT::ValueType;
1159 using OtherMapCIter =
typename OtherRootT::MapCIter;
1160 using OtherTile =
typename OtherRootT::Tile;
1164 static inline ValueT convertValue(
const OtherValueT& val) {
return ValueT(val); }
1167 self.mBackground = Local::convertValue(other.mBackground);
1168 #if OPENVDB_ABI_VERSION_NUMBER >= 10 1169 if (other.mOrigin != Coord(0,0,0)) {
1170 OPENVDB_THROW(
ValueError,
"RootNodeCopyHelper::copyWithValueConversion: non-zero offsets are currently not supported");
1172 self.mOrigin = other.mOrigin;
1174 #if OPENVDB_ABI_VERSION_NUMBER >= 9 1175 self.mTransientData = other.mTransientData;
1181 for (OtherMapCIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
1182 if (other.isTile(i)) {
1184 const OtherTile& otherTile = other.getTile(i);
1185 self.mTable[i->first] = NodeStruct(
1186 Tile(Local::convertValue(otherTile.value), otherTile.active));
1189 self.mTable[i->first] = NodeStruct(*(
new ChildT(other.getChild(i))));
1197 template<
typename ChildT>
1201 if (&other !=
this) {
1202 mBackground = other.mBackground;
1203 #if OPENVDB_ABI_VERSION_NUMBER >= 10 1204 mOrigin = other.mOrigin;
1205 if (mOrigin != Coord(0,0,0)) {
1209 #if OPENVDB_ABI_VERSION_NUMBER >= 9 1210 mTransientData = other.mTransientData;
1216 for (MapCIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
1218 isTile(i) ? NodeStruct(getTile(i)) : NodeStruct(*(
new ChildT(getChild(i))));
1225 template<
typename ChildT>
1226 template<
typename OtherChildType>
1231 using OtherValueT =
typename OtherRootT::ValueType;
1241 template<
typename ChildT>
1247 if (updateChildNodes) {
1250 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1251 ChildT *child = iter->second.child;
1253 child->resetBackground(mBackground, background);
1255 Tile& tile = getTile(iter);
1256 if (tile.active)
continue;
1268 template<
typename ChildT>
1275 template<
typename ChildT>
1282 template<
typename ChildT>
1290 template<
typename ChildT>
1295 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1302 template<
typename ChildT>
1306 std::set<Coord> keysToErase;
1307 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1310 for (std::set<Coord>::iterator i = keysToErase.begin(), e = keysToErase.end(); i != e; ++i) {
1313 return keysToErase.size();
1320 template<
typename ChildT>
1324 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1325 keys.insert(i->first);
1330 template<
typename ChildT>
1331 inline typename RootNode<ChildT>::MapIter
1334 const Coord key = coordToKey(xyz);
1335 std::pair<MapIter, bool> result = mTable.insert(
1336 typename MapType::value_type(key, NodeStruct(Tile(mBackground,
false))));
1337 return result.first;
1341 template<
typename ChildT>
1345 const Coord key = coordToKey(xyz);
1346 std::pair<MapIter, bool> result = mTable.insert(
1347 typename MapType::value_type(key, NodeStruct(Tile(mBackground,
false))));
1348 return result.second;
1355 template<
typename ChildT>
1360 ChildT::getNodeLog2Dims(dims);
1364 template<
typename ChildT>
1368 return mTable.empty() ? Coord(0) : mTable.begin()->first;
1371 template<
typename ChildT>
1375 return mTable.empty() ? Coord(0) : mTable.rbegin()->first + Coord(ChildT::DIM - 1);
1379 template<
typename ChildT>
1391 template<
typename ChildT>
1392 template<
typename OtherChildType>
1397 using OtherMapT =
typename OtherRootT::MapType;
1398 using OtherIterT =
typename OtherRootT::MapIter;
1399 using OtherCIterT =
typename OtherRootT::MapCIter;
1404 OtherMapT copyOfOtherTable = other.mTable;
1407 for (MapCIter thisIter = mTable.begin(); thisIter != mTable.end(); ++thisIter) {
1411 OtherCIterT otherIter = other.findKey(thisIter->first);
1412 if (otherIter == other.mTable.end())
return false;
1415 if (isChild(thisIter)) {
1416 if (OtherRootT::isTile(otherIter))
return false;
1418 if (!getChild(thisIter).hasSameTopology(&OtherRootT::getChild(otherIter)))
return false;
1420 if (OtherRootT::isChild(otherIter))
return false;
1421 if (getTile(thisIter).active != OtherRootT::getTile(otherIter).active)
return false;
1428 copyOfOtherTable.erase(otherIter->first);
1431 for (OtherIterT i = copyOfOtherTable.begin(), e = copyOfOtherTable.end(); i != e; ++i) {
1438 template<
typename ChildT>
1439 template<
typename OtherChildType>
1443 std::vector<Index> thisDims, otherDims;
1446 return (thisDims == otherDims);
1450 template<
typename ChildT>
1451 template<
typename OtherChildType>
1455 std::vector<Index> thisDims, otherDims;
1458 if (thisDims != otherDims) {
1459 std::ostringstream ostr;
1460 ostr <<
"grids have incompatible configurations (" << thisDims[0];
1461 for (
size_t i = 1, N = thisDims.size(); i < N; ++i) ostr <<
" x " << thisDims[i];
1462 ostr <<
" vs. " << otherDims[0];
1463 for (
size_t i = 1, N = otherDims.size(); i < N; ++i) ostr <<
" x " << otherDims[i];
1470 template<
typename ChildT>
1471 template<
typename OtherChildType>
1475 using OtherValueType =
typename OtherChildType::ValueType;
1480 template<
typename ChildT>
1481 template<
typename OtherChildType>
1485 using OtherValueType =
typename OtherChildType::ValueType;
1487 std::ostringstream ostr;
1488 ostr <<
"values of type " << typeNameAsString<OtherValueType>()
1489 <<
" cannot be converted to type " << typeNameAsString<ValueType>();
1498 template<
typename ChildT>
1503 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1504 if (
const ChildT *child = iter->second.child) {
1505 sum += child->memUsage();
1512 template<
typename ChildT>
1516 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1517 delete i->second.child;
1523 template<
typename ChildT>
1527 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1528 if (
const ChildT *child = iter->second.child) {
1529 child->evalActiveBoundingBox(bbox, visitVoxels);
1530 }
else if (isTileOn(iter)) {
1531 bbox.expand(iter->first, ChildT::DIM);
1537 template<
typename ChildT>
1544 template<
typename ChildT>
1549 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1550 if (isTile(i)) ++sum;
1556 template<
typename ChildT>
1561 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1562 if (isTileOn(i)) ++sum;
1568 template<
typename ChildT>
1573 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1574 if (isTileOff(i)) ++sum;
1580 template<
typename ChildT>
1585 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1586 if (isChild(i)) sum += getChild(i).leafCount();
1592 template<
typename ChildT>
1597 if (ChildT::LEVEL != 0) {
1598 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1599 if (isChild(i)) sum += getChild(i).nonLeafCount();
1606 template<
typename ChildT>
1611 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1612 if (isChild(i)) ++sum;
1618 template<
typename ChildT>
1623 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1625 sum += getChild(i).onVoxelCount();
1626 }
else if (isTileOn(i)) {
1627 sum += ChildT::NUM_VOXELS;
1634 template<
typename ChildT>
1639 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1641 sum += getChild(i).offVoxelCount();
1643 sum += ChildT::NUM_VOXELS;
1650 template<
typename ChildT>
1655 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1656 if (isChild(i)) sum += getChild(i).onLeafVoxelCount();
1662 template<
typename ChildT>
1667 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1668 if (isChild(i)) sum += getChild(i).offLeafVoxelCount();
1673 template<
typename ChildT>
1678 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1680 sum += getChild(i).onTileCount();
1681 }
else if (isTileOn(i)) {
1688 template<
typename ChildT>
1692 assert(vec.size() >
LEVEL);
1694 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1697 getChild(i).nodeCount(vec);
1701 vec[ChildNodeType::LEVEL] = sum;
1707 template<
typename ChildT>
1711 MapCIter iter = this->findCoord(xyz);
1712 if (iter == mTable.end() || isTileOff(iter))
return false;
1713 return isTileOn(iter) ?
true : getChild(iter).isValueOn(xyz);
1716 template<
typename ChildT>
1720 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1721 if (isChild(i) ? getChild(i).hasActiveTiles() : getTile(i).active)
return true;
1726 template<
typename ChildT>
1727 template<
typename AccessorT>
1731 MapCIter iter = this->findCoord(xyz);
1732 if (iter == mTable.end() || isTileOff(iter))
return false;
1733 if (isTileOn(iter))
return true;
1734 acc.insert(xyz, &getChild(iter));
1735 return getChild(iter).isValueOnAndCache(xyz, acc);
1739 template<
typename ChildT>
1740 inline const typename ChildT::ValueType&
1743 MapCIter iter = this->findCoord(xyz);
1744 return iter == mTable.end() ? mBackground
1745 : (isTile(iter) ? getTile(iter).value : getChild(iter).getValue(xyz));
1748 template<
typename ChildT>
1749 template<
typename AccessorT>
1750 inline const typename ChildT::ValueType&
1753 MapCIter iter = this->findCoord(xyz);
1754 if (iter == mTable.end())
return mBackground;
1755 if (isChild(iter)) {
1756 acc.insert(xyz, &getChild(iter));
1757 return getChild(iter).getValueAndCache(xyz, acc);
1759 return getTile(iter).value;
1763 template<
typename ChildT>
1767 MapCIter iter = this->findCoord(xyz);
1768 return iter == mTable.end() ? -1
1769 : (isTile(iter) ? 0 : int(LEVEL) - int(getChild(iter).getValueLevel(xyz)));
1772 template<
typename ChildT>
1773 template<
typename AccessorT>
1777 MapCIter iter = this->findCoord(xyz);
1778 if (iter == mTable.end())
return -1;
1779 if (isTile(iter))
return 0;
1780 acc.insert(xyz, &getChild(iter));
1781 return int(LEVEL) - int(getChild(iter).getValueLevelAndCache(xyz, acc));
1785 template<
typename ChildT>
1789 MapIter iter = this->findCoord(xyz);
1790 if (iter != mTable.end() && !isTileOff(iter)) {
1791 if (isTileOn(iter)) {
1792 setChild(iter, *
new ChildT(xyz, getTile(iter).value,
true));
1794 getChild(iter).setValueOff(xyz);
1799 template<
typename ChildT>
1803 ChildT* child =
nullptr;
1804 MapIter iter = this->findCoord(xyz);
1805 if (iter == mTable.end()) {
1807 child =
new ChildT(xyz, mBackground);
1808 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1812 }
else if (isChild(iter)) {
1813 child = &getChild(iter);
1814 }
else if (on != getTile(iter).active) {
1815 child =
new ChildT(xyz, getTile(iter).value, !on);
1816 setChild(iter, *child);
1818 if (child) child->setActiveState(xyz, on);
1821 template<
typename ChildT>
1822 template<
typename AccessorT>
1826 ChildT* child =
nullptr;
1827 MapIter iter = this->findCoord(xyz);
1828 if (iter == mTable.end()) {
1830 child =
new ChildT(xyz, mBackground);
1831 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1835 }
else if (isChild(iter)) {
1836 child = &getChild(iter);
1837 }
else if (on != getTile(iter).active) {
1838 child =
new ChildT(xyz, getTile(iter).value, !on);
1839 setChild(iter, *child);
1842 acc.insert(xyz, child);
1843 child->setActiveStateAndCache(xyz, on, acc);
1848 template<
typename ChildT>
1852 ChildT* child =
nullptr;
1853 MapIter iter = this->findCoord(xyz);
1854 if (iter == mTable.end()) {
1856 child =
new ChildT(xyz, mBackground);
1857 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1859 }
else if (isChild(iter)) {
1860 child = &getChild(iter);
1862 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1863 setChild(iter, *child);
1865 if (child) child->setValueOff(xyz, value);
1868 template<
typename ChildT>
1869 template<
typename AccessorT>
1873 ChildT* child =
nullptr;
1874 MapIter iter = this->findCoord(xyz);
1875 if (iter == mTable.end()) {
1877 child =
new ChildT(xyz, mBackground);
1878 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1880 }
else if (isChild(iter)) {
1881 child = &getChild(iter);
1883 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1884 setChild(iter, *child);
1887 acc.insert(xyz, child);
1888 child->setValueOffAndCache(xyz, value, acc);
1893 template<
typename ChildT>
1897 ChildT* child =
nullptr;
1898 MapIter iter = this->findCoord(xyz);
1899 if (iter == mTable.end()) {
1900 child =
new ChildT(xyz, mBackground);
1901 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1902 }
else if (isChild(iter)) {
1903 child = &getChild(iter);
1905 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1906 setChild(iter, *child);
1908 if (child) child->setValueOn(xyz, value);
1911 template<
typename ChildT>
1912 template<
typename AccessorT>
1916 ChildT* child =
nullptr;
1917 MapIter iter = this->findCoord(xyz);
1918 if (iter == mTable.end()) {
1919 child =
new ChildT(xyz, mBackground);
1920 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1921 }
else if (isChild(iter)) {
1922 child = &getChild(iter);
1924 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1925 setChild(iter, *child);
1928 acc.insert(xyz, child);
1929 child->setValueAndCache(xyz, value, acc);
1934 template<
typename ChildT>
1938 ChildT* child =
nullptr;
1939 MapIter iter = this->findCoord(xyz);
1940 if (iter == mTable.end()) {
1941 child =
new ChildT(xyz, mBackground);
1942 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1943 }
else if (isChild(iter)) {
1944 child = &getChild(iter);
1946 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1947 setChild(iter, *child);
1949 if (child) child->setValueOnly(xyz, value);
1952 template<
typename ChildT>
1953 template<
typename AccessorT>
1957 ChildT* child =
nullptr;
1958 MapIter iter = this->findCoord(xyz);
1959 if (iter == mTable.end()) {
1960 child =
new ChildT(xyz, mBackground);
1961 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1962 }
else if (isChild(iter)) {
1963 child = &getChild(iter);
1965 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1966 setChild(iter, *child);
1969 acc.insert(xyz, child);
1970 child->setValueOnlyAndCache(xyz, value, acc);
1975 template<
typename ChildT>
1976 template<
typename ModifyOp>
1980 ChildT* child =
nullptr;
1981 MapIter iter = this->findCoord(xyz);
1982 if (iter == mTable.end()) {
1983 child =
new ChildT(xyz, mBackground);
1984 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
1985 }
else if (isChild(iter)) {
1986 child = &getChild(iter);
1990 bool createChild = isTileOff(iter);
1994 const ValueType& tileVal = getTile(iter).value;
2000 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2001 setChild(iter, *child);
2004 if (child) child->modifyValue(xyz, op);
2007 template<
typename ChildT>
2008 template<
typename ModifyOp,
typename AccessorT>
2012 ChildT* child =
nullptr;
2013 MapIter iter = this->findCoord(xyz);
2014 if (iter == mTable.end()) {
2015 child =
new ChildT(xyz, mBackground);
2016 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2017 }
else if (isChild(iter)) {
2018 child = &getChild(iter);
2022 bool createChild = isTileOff(iter);
2026 const ValueType& tileVal = getTile(iter).value;
2032 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2033 setChild(iter, *child);
2037 acc.insert(xyz, child);
2038 child->modifyValueAndCache(xyz, op, acc);
2043 template<
typename ChildT>
2044 template<
typename ModifyOp>
2048 ChildT* child =
nullptr;
2049 MapIter iter = this->findCoord(xyz);
2050 if (iter == mTable.end()) {
2051 child =
new ChildT(xyz, mBackground);
2052 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2053 }
else if (isChild(iter)) {
2054 child = &getChild(iter);
2056 const Tile& tile = getTile(iter);
2057 bool modifiedState = tile.active;
2059 op(modifiedVal, modifiedState);
2063 child =
new ChildT(xyz, tile.value, tile.active);
2064 setChild(iter, *child);
2067 if (child) child->modifyValueAndActiveState(xyz, op);
2070 template<
typename ChildT>
2071 template<
typename ModifyOp,
typename AccessorT>
2074 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
2076 ChildT* child =
nullptr;
2077 MapIter iter = this->findCoord(xyz);
2078 if (iter == mTable.end()) {
2079 child =
new ChildT(xyz, mBackground);
2080 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2081 }
else if (isChild(iter)) {
2082 child = &getChild(iter);
2084 const Tile& tile = getTile(iter);
2085 bool modifiedState = tile.active;
2087 op(modifiedVal, modifiedState);
2091 child =
new ChildT(xyz, tile.value, tile.active);
2092 setChild(iter, *child);
2096 acc.insert(xyz, child);
2097 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
2102 template<
typename ChildT>
2106 MapCIter iter = this->findCoord(xyz);
2107 if (iter == mTable.end()) {
2108 value = mBackground;
2110 }
else if (isChild(iter)) {
2111 return getChild(iter).probeValue(xyz, value);
2113 value = getTile(iter).value;
2114 return isTileOn(iter);
2117 template<
typename ChildT>
2118 template<
typename AccessorT>
2122 MapCIter iter = this->findCoord(xyz);
2123 if (iter == mTable.end()) {
2124 value = mBackground;
2126 }
else if (isChild(iter)) {
2127 acc.insert(xyz, &getChild(iter));
2128 return getChild(iter).probeValueAndCache(xyz, value, acc);
2130 value = getTile(iter).value;
2131 return isTileOn(iter);
2138 template<
typename ChildT>
2142 if (bbox.empty())
return;
2147 for (
int x = bbox.min().x(); x <= bbox.max().x(); x = tileMax.x() + 1) {
2149 for (
int y = bbox.min().y(); y <= bbox.max().y(); y = tileMax.y() + 1) {
2151 for (
int z = bbox.min().z(); z <= bbox.max().z(); z = tileMax.z() + 1) {
2155 Coord tileMin = coordToKey(xyz);
2156 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2158 if (xyz != tileMin || Coord::lessThan(bbox.max(), tileMax)) {
2162 ChildT* child =
nullptr;
2163 MapIter iter = this->findKey(tileMin);
2164 if (iter == mTable.end()) {
2167 child =
new ChildT(xyz, mBackground);
2168 mTable[tileMin] = NodeStruct(*child);
2169 }
else if (isTile(iter)) {
2172 const Tile& tile = getTile(iter);
2173 child =
new ChildT(xyz, tile.value, tile.active);
2174 mTable[tileMin] = NodeStruct(*child);
2175 }
else if (isChild(iter)) {
2176 child = &getChild(iter);
2181 child->fill(
CoordBBox(xyz, tmp), value, active);
2187 MapIter iter = this->findOrAddCoord(tileMin);
2188 setTile(iter, Tile(value, active));
2196 template<
typename ChildT>
2200 if (bbox.empty())
return;
2202 if (active && mTable.empty()) {
2212 Coord xyz, tileMin, tileMax;
2213 for (
int x = bbox.min().x(); x <= bbox.max().x(); x = tileMax.x() + 1) {
2215 for (
int y = bbox.min().y(); y <= bbox.max().y(); y = tileMax.y() + 1) {
2217 for (
int z = bbox.min().z(); z <= bbox.max().z(); z = tileMax.z() + 1) {
2221 tileMin = coordToKey(xyz);
2222 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2226 const auto iter = findOrAddCoord(tileMin);
2231 const auto& tile = getTile(iter);
2232 auto* child =
new ChildT{tileMin, tile.value, tile.active};
2233 setChild(iter, *child);
2236 getChild(iter).denseFill(bbox, value, active);
2246 template<
typename ChildT>
2254 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2255 if (this->isTileOff(i))
continue;
2256 ChildT* child = i->second.child;
2257 if (child ==
nullptr) {
2260 child =
new ChildT{i->first, this->getTile(i).value,
true};
2261 i->second.child =
child;
2263 child->voxelizeActiveTiles(threaded);
2271 template<
typename ChildT>
2272 template<
typename DenseT>
2276 using DenseValueType =
typename DenseT::ValueType;
2278 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2279 const Coord&
min = dense.bbox().min();
2281 for (Coord xyz = bbox.min(); xyz[0] <= bbox.max()[0]; xyz[0] = nodeBBox.max()[0] + 1) {
2282 for (xyz[1] = bbox.min()[1]; xyz[1] <= bbox.max()[1]; xyz[1] = nodeBBox.max()[1] + 1) {
2283 for (xyz[2] = bbox.min()[2]; xyz[2] <= bbox.max()[2]; xyz[2] = nodeBBox.max()[2] + 1) {
2286 nodeBBox = CoordBBox::createCube(coordToKey(xyz), ChildT::DIM);
2291 MapCIter iter = this->findKey(nodeBBox.min());
2292 if (iter != mTable.end() && isChild(iter)) {
2293 getChild(iter).copyToDense(sub, dense);
2295 const ValueType value = iter==mTable.end() ? mBackground : getTile(iter).value;
2296 sub.translate(-min);
2297 DenseValueType* a0 = dense.data() + zStride*sub.min()[2];
2298 for (
Int32 x=sub.min()[0], ex=sub.max()[0]+1; x<ex; ++x) {
2299 DenseValueType* a1 = a0 + x*xStride;
2300 for (
Int32 y=sub.min()[1], ey=sub.max()[1]+1; y<ey; ++y) {
2301 DenseValueType* a2 = a1 + y*yStride;
2302 for (
Int32 z=sub.min()[2], ez=sub.max()[2]+1; z<ez; ++z, a2 += zStride) {
2303 *a2 = DenseValueType(value);
2316 template<
typename ChildT>
2321 os.write(reinterpret_cast<const char*>(&mBackground),
sizeof(
ValueType));
2324 os.write(reinterpret_cast<const char*>(&truncatedVal),
sizeof(
ValueType));
2328 const Index numTiles = this->getTileCount(), numChildren = this->
childCount();
2329 os.write(reinterpret_cast<const char*>(&numTiles),
sizeof(
Index));
2330 os.write(reinterpret_cast<const char*>(&numChildren),
sizeof(
Index));
2332 if (numTiles == 0 && numChildren == 0)
return false;
2335 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2336 if (isChild(i))
continue;
2337 os.write(reinterpret_cast<const char*>(i->first.asPointer()), 3 *
sizeof(
Int32));
2338 os.write(reinterpret_cast<const char*>(&getTile(i).value),
sizeof(
ValueType));
2339 os.write(reinterpret_cast<const char*>(&getTile(i).active),
sizeof(
bool));
2342 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2343 if (isTile(i))
continue;
2344 os.write(reinterpret_cast<const char*>(i->first.asPointer()), 3 *
sizeof(
Int32));
2345 getChild(i).writeTopology(os, toHalf);
2352 template<
typename ChildT>
2364 is.read(reinterpret_cast<char*>(&mBackground),
sizeof(
ValueType));
2366 is.read(reinterpret_cast<char*>(&inside),
sizeof(
ValueType));
2371 Coord rangeMin, rangeMax;
2372 is.read(reinterpret_cast<char*>(rangeMin.asPointer()), 3 *
sizeof(
Int32));
2373 is.read(reinterpret_cast<char*>(rangeMax.asPointer()), 3 *
sizeof(
Int32));
2376 Index tableSize = 0, log2Dim[4] = { 0, 0, 0, 0 };
2378 for (
int i = 0; i < 3; ++i) {
2379 offset[i] = rangeMin[i] >> ChildT::TOTAL;
2380 rangeMin[i] = offset[i] << ChildT::TOTAL;
2382 tableSize += log2Dim[i];
2383 rangeMax[i] = (((1 << log2Dim[i]) + offset[i]) << ChildT::TOTAL) - 1;
2385 log2Dim[3] = log2Dim[1] + log2Dim[2];
2386 tableSize = 1U << tableSize;
2394 for (
Index i = 0; i < tableSize; ++i) {
2398 origin[0] = (n >> log2Dim[3]) + offset[0];
2399 n &= (1U << log2Dim[3]) - 1;
2400 origin[1] = (n >> log2Dim[2]) + offset[1];
2401 origin[2] = (n & ((1U << log2Dim[2]) - 1)) + offset[1];
2402 origin <<= ChildT::TOTAL;
2404 if (childMask.isOn(i)) {
2406 ChildT* child =
new ChildT(
PartialCreate(), origin, mBackground);
2407 child->readTopology(is);
2408 mTable[
origin] = NodeStruct(*child);
2413 is.read(reinterpret_cast<char*>(&value),
sizeof(
ValueType));
2415 mTable[
origin] = NodeStruct(Tile(value, valueMask.
isOn(i)));
2424 is.read(reinterpret_cast<char*>(&mBackground),
sizeof(
ValueType));
2427 Index numTiles = 0, numChildren = 0;
2428 is.read(reinterpret_cast<char*>(&numTiles),
sizeof(
Index));
2429 is.read(reinterpret_cast<char*>(&numChildren),
sizeof(
Index));
2431 if (numTiles == 0 && numChildren == 0)
return false;
2438 for (
Index n = 0; n < numTiles; ++n) {
2439 is.read(reinterpret_cast<char*>(vec), 3 *
sizeof(
Int32));
2440 is.read(reinterpret_cast<char*>(&value),
sizeof(
ValueType));
2441 is.read(reinterpret_cast<char*>(&active),
sizeof(
bool));
2442 mTable[Coord(vec)] = NodeStruct(Tile(value, active));
2446 for (
Index n = 0; n < numChildren; ++n) {
2447 is.read(reinterpret_cast<char*>(vec), 3 *
sizeof(
Int32));
2449 ChildT* child =
new ChildT(
PartialCreate(), origin, mBackground);
2450 child->readTopology(is, fromHalf);
2451 mTable[Coord(vec)] = NodeStruct(*child);
2458 template<
typename ChildT>
2462 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2463 if (isChild(i)) getChild(i).writeBuffers(os, toHalf);
2468 template<
typename ChildT>
2472 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2473 if (isChild(i)) getChild(i).readBuffers(is, fromHalf);
2478 template<
typename ChildT>
2482 const Tile bgTile(mBackground,
false);
2484 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2490 ChildT& child = getChild(i);
2491 child.readBuffers(is, clipBBox, fromHalf);
2495 this->
clip(clipBBox);
2502 template<
typename ChildT>
2506 const Tile bgTile(mBackground,
false);
2510 MapType copyOfTable(mTable);
2511 for (MapIter i = copyOfTable.begin(), e = copyOfTable.end(); i != e; ++i) {
2512 const Coord& xyz = i->first;
2513 CoordBBox tileBBox(xyz, xyz.offsetBy(ChildT::DIM - 1));
2514 if (!clipBBox.hasOverlap(tileBBox)) {
2516 setTile(this->findCoord(xyz), bgTile);
2518 }
else if (!clipBBox.isInside(tileBBox)) {
2522 getChild(i).clip(clipBBox, mBackground);
2526 tileBBox.intersect(clipBBox);
2527 const Tile& origTile = getTile(i);
2528 setTile(this->findCoord(xyz), bgTile);
2529 this->
sparseFill(tileBBox, origTile.value, origTile.active);
2542 template<
typename ChildT>
2548 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2549 if (this->isTile(i))
continue;
2550 this->getChild(i).prune(tolerance);
2551 if (this->getChild(i).isConstant(value, state, tolerance)) {
2552 this->setTile(i, Tile(value, state));
2562 template<
typename ChildT>
2563 template<
typename NodeT>
2568 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2570 MapIter iter = this->findCoord(xyz);
2571 if (iter == mTable.end() || isTile(iter))
return nullptr;
2573 ?
reinterpret_cast<NodeT*
>(&stealChild(iter, Tile(value, state)))
2574 : getChild(iter).template stealNode<NodeT>(xyz,
value, state);
2582 template<
typename ChildT>
2586 if (leaf ==
nullptr)
return;
2587 ChildT* child =
nullptr;
2588 const Coord& xyz = leaf->origin();
2589 MapIter iter = this->findCoord(xyz);
2590 if (iter == mTable.end()) {
2591 if (ChildT::LEVEL>0) {
2592 child =
new ChildT(xyz, mBackground,
false);
2594 child =
reinterpret_cast<ChildT*
>(leaf);
2596 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2597 }
else if (isChild(iter)) {
2598 if (ChildT::LEVEL>0) {
2599 child = &getChild(iter);
2601 child =
reinterpret_cast<ChildT*
>(leaf);
2602 setChild(iter, *child);
2605 if (ChildT::LEVEL>0) {
2606 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2608 child =
reinterpret_cast<ChildT*
>(leaf);
2610 setChild(iter, *child);
2612 child->addLeaf(leaf);
2616 template<
typename ChildT>
2617 template<
typename AccessorT>
2621 if (leaf ==
nullptr)
return;
2622 ChildT* child =
nullptr;
2623 const Coord& xyz = leaf->origin();
2624 MapIter iter = this->findCoord(xyz);
2625 if (iter == mTable.end()) {
2626 if (ChildT::LEVEL>0) {
2627 child =
new ChildT(xyz, mBackground,
false);
2629 child =
reinterpret_cast<ChildT*
>(leaf);
2631 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2632 }
else if (isChild(iter)) {
2633 if (ChildT::LEVEL>0) {
2634 child = &getChild(iter);
2636 child =
reinterpret_cast<ChildT*
>(leaf);
2637 setChild(iter, *child);
2640 if (ChildT::LEVEL>0) {
2641 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2643 child =
reinterpret_cast<ChildT*
>(leaf);
2645 setChild(iter, *child);
2647 acc.insert(xyz, child);
2648 child->addLeafAndCache(leaf, acc);
2651 template<
typename ChildT>
2655 if (!child)
return false;
2656 const Coord& xyz = child->origin();
2657 MapIter iter = this->findCoord(xyz);
2658 if (iter == mTable.end()) {
2659 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2661 setChild(iter, *child);
2666 #if OPENVDB_ABI_VERSION_NUMBER >= 10 2667 template<
typename ChildT>
2672 if (mOrigin != Coord(0,0,0)) {
2678 template<
typename ChildT>
2682 MapIter iter = this->findCoord(xyz);
2683 if (iter == mTable.end()) {
2684 mTable[this->coordToKey(xyz)] = NodeStruct(Tile(value, state));
2686 setTile(iter, Tile(value, state));
2690 template<
typename ChildT>
2695 if (LEVEL >= level) {
2696 MapIter iter = this->findCoord(xyz);
2697 if (iter == mTable.end()) {
2698 if (LEVEL > level) {
2699 ChildT* child =
new ChildT(xyz, mBackground,
false);
2700 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2701 child->addTile(level, xyz, value, state);
2703 mTable[this->coordToKey(xyz)] = NodeStruct(Tile(value, state));
2705 }
else if (isChild(iter)) {
2706 if (LEVEL > level) {
2707 getChild(iter).addTile(level, xyz, value, state);
2709 setTile(iter, Tile(value, state));
2712 if (LEVEL > level) {
2713 ChildT* child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2714 setChild(iter, *child);
2715 child->addTile(level, xyz, value, state);
2717 setTile(iter, Tile(value, state));
2724 template<
typename ChildT>
2725 template<
typename AccessorT>
2728 bool state, AccessorT& acc)
2730 if (LEVEL >= level) {
2731 MapIter iter = this->findCoord(xyz);
2732 if (iter == mTable.end()) {
2733 if (LEVEL > level) {
2734 ChildT* child =
new ChildT(xyz, mBackground,
false);
2735 acc.insert(xyz, child);
2736 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2737 child->addTileAndCache(level, xyz, value, state, acc);
2739 mTable[this->coordToKey(xyz)] = NodeStruct(Tile(value, state));
2741 }
else if (isChild(iter)) {
2742 if (LEVEL > level) {
2743 ChildT* child = &getChild(iter);
2744 acc.insert(xyz, child);
2745 child->addTileAndCache(level, xyz, value, state, acc);
2747 setTile(iter, Tile(value, state));
2750 if (LEVEL > level) {
2751 ChildT* child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2752 acc.insert(xyz, child);
2753 setChild(iter, *child);
2754 child->addTileAndCache(level, xyz, value, state, acc);
2756 setTile(iter, Tile(value, state));
2766 template<
typename ChildT>
2767 inline typename ChildT::LeafNodeType*
2770 ChildT* child =
nullptr;
2771 MapIter iter = this->findCoord(xyz);
2772 if (iter == mTable.end()) {
2773 child =
new ChildT(xyz, mBackground,
false);
2774 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2775 }
else if (isChild(iter)) {
2776 child = &getChild(iter);
2778 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2779 setChild(iter, *child);
2781 return child->touchLeaf(xyz);
2785 template<
typename ChildT>
2786 template<
typename AccessorT>
2787 inline typename ChildT::LeafNodeType*
2790 ChildT* child =
nullptr;
2791 MapIter iter = this->findCoord(xyz);
2792 if (iter == mTable.end()) {
2793 child =
new ChildT(xyz, mBackground,
false);
2794 mTable[this->coordToKey(xyz)] = NodeStruct(*child);
2795 }
else if (isChild(iter)) {
2796 child = &getChild(iter);
2798 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2799 setChild(iter, *child);
2801 acc.insert(xyz, child);
2802 return child->touchLeafAndCache(xyz, acc);
2809 template<
typename ChildT>
2810 template<
typename NodeT>
2815 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2817 MapIter iter = this->findCoord(xyz);
2818 if (iter == mTable.end() || isTile(iter))
return nullptr;
2819 ChildT* child = &getChild(iter);
2821 ?
reinterpret_cast<NodeT*
>(
child)
2822 : child->template probeNode<NodeT>(xyz);
2827 template<
typename ChildT>
2828 template<
typename NodeT>
2833 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2835 MapCIter iter = this->findCoord(xyz);
2836 if (iter == mTable.end() || isTile(iter))
return nullptr;
2837 const ChildT* child = &getChild(iter);
2839 ?
reinterpret_cast<const NodeT*
>(
child)
2840 : child->template probeConstNode<NodeT>(xyz);
2845 template<
typename ChildT>
2846 inline typename ChildT::LeafNodeType*
2849 return this->
template probeNode<LeafNodeType>(xyz);
2853 template<
typename ChildT>
2854 inline const typename ChildT::LeafNodeType*
2857 return this->
template probeConstNode<LeafNodeType>(xyz);
2861 template<
typename ChildT>
2862 template<
typename AccessorT>
2863 inline typename ChildT::LeafNodeType*
2866 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
2870 template<
typename ChildT>
2871 template<
typename AccessorT>
2872 inline const typename ChildT::LeafNodeType*
2875 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
2879 template<
typename ChildT>
2880 template<
typename AccessorT>
2881 inline const typename ChildT::LeafNodeType*
2888 template<
typename ChildT>
2889 template<
typename NodeT,
typename AccessorT>
2894 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2896 MapIter iter = this->findCoord(xyz);
2897 if (iter == mTable.end() || isTile(iter))
return nullptr;
2898 ChildT* child = &getChild(iter);
2899 acc.insert(xyz, child);
2901 ?
reinterpret_cast<NodeT*
>(
child)
2902 : child->template probeNodeAndCache<NodeT>(xyz, acc);
2907 template<
typename ChildT>
2908 template<
typename NodeT,
typename AccessorT>
2913 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2915 MapCIter iter = this->findCoord(xyz);
2916 if (iter == mTable.end() || isTile(iter))
return nullptr;
2917 const ChildT* child = &getChild(iter);
2918 acc.insert(xyz, child);
2920 ?
reinterpret_cast<const NodeT*
>(
child)
2921 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
2928 template<
typename ChildT>
2929 template<
typename ArrayT>
2933 using NodePtr =
typename ArrayT::value_type;
2935 "argument to getNodes() must be a pointer array");
2936 using NodeType =
typename std::remove_pointer<NodePtr>::type;
2937 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
2938 static_assert(NodeChainType::template Contains<NonConstNodeType>,
2939 "can't extract non-const nodes from a const tree");
2940 using ArrayChildT =
typename std::conditional<
2943 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
2944 if (ChildT* child = iter->second.child) {
2947 array.push_back(reinterpret_cast<NodePtr>(iter->second.child));
2949 child->getNodes(array);
2956 template<
typename ChildT>
2957 template<
typename ArrayT>
2961 using NodePtr =
typename ArrayT::value_type;
2963 "argument to getNodes() must be a pointer array");
2964 using NodeType =
typename std::remove_pointer<NodePtr>::type;
2966 "argument to getNodes() must be an array of const node pointers");
2967 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
2968 static_assert(NodeChainType::template Contains<NonConstNodeType>,
2969 "can't extract non-const nodes from a const tree");
2971 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
2975 array.push_back(reinterpret_cast<NodePtr>(iter->second.child));
2977 child->getNodes(array);
2986 template<
typename ChildT>
2987 template<
typename ArrayT>
2991 using NodePtr =
typename ArrayT::value_type;
2993 "argument to stealNodes() must be a pointer array");
2994 using NodeType =
typename std::remove_pointer<NodePtr>::type;
2995 using NonConstNodeType =
typename std::remove_const<NodeType>::type;
2996 static_assert(NodeChainType::template Contains<NonConstNodeType>,
2997 "can't extract non-const nodes from a const tree");
2998 using ArrayChildT =
typename std::conditional<
3001 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
3002 if (ChildT* child = iter->second.child) {
3005 array.push_back(reinterpret_cast<NodePtr>(&stealChild(iter, Tile(value, state))));
3007 child->stealNodes(array, value, state);
3018 template<
typename ChildT>
3019 template<MergePolicy Policy>
3029 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3030 MapIter j = mTable.find(i->first);
3031 if (other.isChild(i)) {
3032 if (j == mTable.end()) {
3033 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3034 child.resetBackground(other.mBackground, mBackground);
3035 mTable[i->first] = NodeStruct(child);
3036 }
else if (isTile(j)) {
3038 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3039 child.resetBackground(other.mBackground, mBackground);
3043 getChild(j).template merge<MERGE_ACTIVE_STATES>(getChild(i),
3044 other.mBackground, mBackground);
3046 }
else if (other.isTileOn(i)) {
3047 if (j == mTable.end()) {
3048 mTable[i->first] = i->second;
3049 }
else if (!isTileOn(j)) {
3051 setTile(j, Tile(other.getTile(i).value,
true));
3058 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3059 MapIter j = mTable.find(i->first);
3060 if (other.isChild(i)) {
3061 if (j == mTable.end()) {
3062 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3063 child.resetBackground(other.mBackground, mBackground);
3064 mTable[i->first] = NodeStruct(child);
3065 }
else if (isTile(j)) {
3066 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3067 child.resetBackground(other.mBackground, mBackground);
3070 getChild(j).template merge<MERGE_NODES>(
3071 getChild(i), other.mBackground, mBackground);
3078 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3079 MapIter j = mTable.find(i->first);
3080 if (other.isChild(i)) {
3081 if (j == mTable.end()) {
3083 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3084 child.resetBackground(other.mBackground, mBackground);
3085 mTable[i->first] = NodeStruct(child);
3086 }
else if (isTile(j)) {
3088 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3089 child.resetBackground(other.mBackground, mBackground);
3090 const Tile tile = getTile(j);
3094 child.template merge<MERGE_ACTIVE_STATES_AND_NODES>(
3095 tile.value, tile.active);
3099 getChild(j).template merge<MERGE_ACTIVE_STATES_AND_NODES>(getChild(i),
3100 other.mBackground, mBackground);
3102 }
else if (other.isTileOn(i)) {
3103 if (j == mTable.end()) {
3105 mTable[i->first] = i->second;
3106 }
else if (isTileOff(j)) {
3108 setTile(j, Tile(other.getTile(i).value,
true));
3109 }
else if (isChild(j)) {
3111 const Tile& tile = getTile(i);
3112 getChild(j).template merge<MERGE_ACTIVE_STATES_AND_NODES>(
3113 tile.value, tile.active);
3130 template<
typename ChildT>
3131 template<
typename OtherChildType>
3136 using OtherCIterT =
typename OtherRootT::MapCIter;
3138 enforceSameConfiguration(other);
3140 for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3141 MapIter j = mTable.find(i->first);
3142 if (other.isChild(i)) {
3143 if (j == mTable.end()) {
3144 mTable[i->first] = NodeStruct(
3145 *(
new ChildT(other.getChild(i), mBackground,
TopologyCopy())));
3146 }
else if (this->isChild(j)) {
3147 this->getChild(j).topologyUnion(other.getChild(i), preserveTiles);
3149 if (!preserveTiles || this->isTileOff(j)) {
3150 ChildT* child =
new ChildT(
3151 other.getChild(i), this->getTile(j).value,
TopologyCopy());
3152 if (this->isTileOn(j)) child->setValuesOn();
3153 this->setChild(j, *child);
3156 }
else if (other.isTileOn(i)) {
3157 if (j == mTable.end()) {
3158 mTable[i->first] = NodeStruct(Tile(mBackground,
true));
3159 }
else if (this->isChild(j)) {
3160 this->getChild(j).setValuesOn();
3161 }
else if (this->isTileOff(j)) {
3162 this->setTile(j, Tile(this->getTile(j).value,
true));
3168 template<
typename ChildT>
3169 template<
typename OtherChildType>
3174 using OtherCIterT =
typename OtherRootT::MapCIter;
3176 enforceSameConfiguration(other);
3178 std::set<Coord> tmp;
3179 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
3180 OtherCIterT j = other.mTable.find(i->first);
3181 if (this->isChild(i)) {
3182 if (j == other.mTable.end() || other.isTileOff(j)) {
3183 tmp.insert(i->first);
3184 }
else if (other.isChild(j)) {
3185 this->getChild(i).topologyIntersection(other.getChild(j), mBackground);
3187 }
else if (this->isTileOn(i)) {
3188 if (j == other.mTable.end() || other.isTileOff(j)) {
3189 this->setTile(i, Tile(this->getTile(i).value,
false));
3190 }
else if (other.isChild(j)) {
3192 new ChildT(other.getChild(j), this->getTile(i).value,
TopologyCopy());
3193 this->setChild(i, *child);
3197 for (std::set<Coord>::iterator i = tmp.begin(), e = tmp.end(); i != e; ++i) {
3198 MapIter it = this->findCoord(*i);
3199 setTile(it, Tile());
3204 template<
typename ChildT>
3205 template<
typename OtherChildType>
3210 using OtherCIterT =
typename OtherRootT::MapCIter;
3212 enforceSameConfiguration(other);
3214 for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3215 MapIter j = mTable.find(i->first);
3216 if (other.isChild(i)) {
3217 if (j == mTable.end() || this->isTileOff(j)) {
3219 }
else if (this->isChild(j)) {
3220 this->getChild(j).topologyDifference(other.getChild(i), mBackground);
3221 }
else if (this->isTileOn(j)) {
3223 ChildT* child =
new ChildT(j->first, this->getTile(j).value,
true);
3224 child->topologyDifference(other.getChild(i), mBackground);
3225 this->setChild(j, *child);
3227 }
else if (other.isTileOn(i)) {
3228 if (j == mTable.end() || this->isTileOff(j)) {
3230 }
else if (this->isChild(j)) {
3233 }
else if (this->isTileOn(j)) {
3234 this->setTile(j, Tile(this->getTile(j).value,
false));
3243 template<
typename ChildT>
3244 template<
typename CombineOp>
3251 this->insertKeys(keys);
3252 other.insertKeys(keys);
3254 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3255 MapIter iter = findOrAddCoord(*i), otherIter = other.findOrAddCoord(*i);
3256 if (isTile(iter) && isTile(otherIter)) {
3259 op(args.
setARef(getTile(iter).value)
3260 .setAIsActive(isTileOn(iter))
3261 .setBRef(getTile(otherIter).value)
3262 .setBIsActive(isTileOn(otherIter)));
3265 }
else if (isChild(iter) && isTile(otherIter)) {
3267 ChildT& child = getChild(iter);
3268 child.combine(getTile(otherIter).value, isTileOn(otherIter), op);
3270 }
else if (isTile(iter) && isChild(otherIter)) {
3275 ChildT& child = getChild(otherIter);
3276 child.combine(getTile(iter).value, isTileOn(iter), swappedOp);
3279 setChild(iter, stealChild(otherIter, Tile()));
3283 ChildT &child = getChild(iter), &otherChild = getChild(otherIter);
3284 child.combine(otherChild, op);
3286 if (prune && isChild(iter)) getChild(iter).prune();
3290 op(args.
setARef(mBackground).setBRef(other.mBackground));
3291 mBackground = args.
result();
3303 template<
typename CombineOp,
typename RootT,
typename OtherRootT,
bool Compatible = false>
3306 static inline void combine2(RootT&
self,
const RootT&,
const OtherRootT& other1,
3311 self.enforceSameConfiguration(other1);
3312 self.enforceCompatibleValueTypes(other1);
3314 std::ostringstream ostr;
3315 ostr <<
"cannot combine a " <<
typeid(OtherRootT).name()
3316 <<
" into a " <<
typeid(RootT).name();
3322 template<
typename CombineOp,
typename RootT,
typename OtherRootT>
3325 static inline void combine2(RootT&
self,
const RootT& other0,
const OtherRootT& other1,
3326 CombineOp& op,
bool prune)
3328 self.doCombine2(other0, other1, op, prune);
3333 template<
typename ChildT>
3334 template<
typename CombineOp,
typename OtherRootNode>
3337 CombineOp& op,
bool prune)
3339 using OtherValueType =
typename OtherRootNode::ValueType;
3343 *
this, other0, other1, op, prune);
3347 template<
typename ChildT>
3348 template<
typename CombineOp,
typename OtherRootNode>
3351 CombineOp& op,
bool prune)
3353 enforceSameConfiguration(other1);
3355 using OtherValueT =
typename OtherRootNode::ValueType;
3356 using OtherTileT =
typename OtherRootNode::Tile;
3357 using OtherNodeStructT =
typename OtherRootNode::NodeStruct;
3358 using OtherMapCIterT =
typename OtherRootNode::MapCIter;
3363 other0.insertKeys(keys);
3364 other1.insertKeys(keys);
3366 const NodeStruct bg0(Tile(other0.mBackground,
false));
3367 const OtherNodeStructT bg1(OtherTileT(other1.mBackground,
false));
3369 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3370 MapIter thisIter = this->findOrAddCoord(*i);
3371 MapCIter iter0 = other0.findKey(*i);
3372 OtherMapCIterT iter1 = other1.findKey(*i);
3373 const NodeStruct& ns0 = (iter0 != other0.mTable.end()) ? iter0->second : bg0;
3374 const OtherNodeStructT& ns1 = (iter1 != other1.mTable.end()) ? iter1->second : bg1;
3375 if (ns0.isTile() && ns1.isTile()) {
3378 op(args.
setARef(ns0.tile.value)
3379 .setAIsActive(ns0.isTileOn())
3380 .setBRef(ns1.tile.value)
3381 .setBIsActive(ns1.isTileOn()));
3384 if (!isChild(thisIter)) {
3386 const Coord& childOrigin =
3387 ns0.isChild() ? ns0.child->origin() : ns1.child->origin();
3388 setChild(thisIter, *(
new ChildT(childOrigin, getTile(thisIter).value)));
3390 ChildT& child = getChild(thisIter);
3395 child.combine2(ns0.tile.value, *ns1.child, ns0.isTileOn(), op);
3396 }
else if (ns1.isTile()) {
3399 child.combine2(*ns0.child, ns1.tile.value, ns1.isTileOn(), op);
3403 child.combine2(*ns0.child, *ns1.child, op);
3406 if (prune && isChild(thisIter)) getChild(thisIter).prune();
3410 op(args.
setARef(other0.mBackground).setBRef(other1.mBackground));
3411 mBackground = args.
result();
3419 #endif // OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED const NodeT * probeConstNodeAndCache(const Coord &xyz, AccessorT &acc) const
Same as probeNode() but, if necessary, update the given accessor with pointers to the nodes along the...
Definition: RootNode.h:2910
static const Index LEVEL
Definition: RootNode.h:46
Index32 Index
Definition: Types.h:54
ChildT * child
Definition: GridBuilder.h:1289
ValueIter< RootNode, MapIter, ValueOffPred, ValueType > ValueOffIter
Definition: RootNode.h:369
ValueOnCIter cbeginValueOn() const
Definition: RootNode.h:385
ValueAllCIter beginValueAll() const
Definition: RootNode.h:390
uint64_t Index64
Definition: Types.h:53
ValueIter< const RootNode, MapCIter, ValueOnPred, const ValueType > ValueOnCIter
Definition: RootNode.h:368
bool isValueOn(const Coord &xyz) const
Definition: RootNode.h:1709
static void copyWithValueConversion(RootT &self, const OtherRootT &other)
Definition: RootNode.h:1152
const ValueType & getValue(const Coord &xyz) const
Definition: RootNode.h:1741
ChildAllIter beginChildAll()
Definition: RootNode.h:383
CanConvertType<FromType, ToType>::value is true if a value of type ToType can be constructed from a v...
Definition: Types.h:364
ValueIter< const RootNode, MapCIter, ChildOffPred, ValueType > ChildOffCIter
Definition: RootNode.h:363
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:1801
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
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:3133
ValueOnCIter beginValueOn() const
Definition: RootNode.h:388
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
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:597
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Index32 childCount() const
Definition: RootNode.h:1608
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition: RootNode.h:2248
void modifyValueAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: RootNode.h:2010
ChildOffCIter cbeginChildOff() const
Definition: RootNode.h:376
bool writeTopology(std::ostream &, bool toHalf=false) const
Definition: RootNode.h:2318
ValueOffIter beginValueOff()
Definition: RootNode.h:392
ChildAllCIter beginChildAll() const
Definition: RootNode.h:380
typename ChildType::LeafNodeType LeafNodeType
Definition: RootNode.h:42
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: RootNode.h:887
Index getTableSize() const
Return the number of entries in this node's table.
Definition: RootNode.h:460
Index32 nonLeafCount() const
Definition: RootNode.h:1594
NodeChain<RootNodeType, RootNodeType::LEVEL>::Type is a openvdb::TypeList that lists the types of the...
Definition: RootNode.h:31
Index64 onLeafVoxelCount() const
Definition: RootNode.h:1652
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
void nodeCount(std::vector< Index32 > &vec) const
Definition: RootNode.h:1690
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:2198
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:1936
ValueIter< RootNode, MapIter, ValueOnPred, ValueType > ValueOnIter
Definition: RootNode.h:367
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:2989
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:1525
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return nullptr.
Definition: RootNode.h:2847
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:1243
ValueAllCIter cbeginValueAll() const
Definition: RootNode.h:387
ChildOnCIter beginChildOn() const
Definition: RootNode.h:378
Definition: version.h.in:246
ValueConverter<T>::Type is the type of a RootNode having the same child hierarchy as this node but a ...
Definition: RootNode.h:56
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:2274
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:128
ChildOffIter beginChildOff()
Definition: RootNode.h:382
Definition: Exceptions.h:65
void readBuffers(std::istream &, bool fromHalf=false)
Definition: RootNode.h:2470
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:443
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:2891
ChildOnCIter cbeginChildOn() const
Definition: RootNode.h:375
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:406
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:2619
void sparseFill(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:539
ChildIter< const RootNode, MapCIter, ChildOnPred, const ChildType > ChildOnCIter
Definition: RootNode.h:361
static bool hasSameConfiguration(const RootNode< OtherChildType > &other)
Return false if the other node's dimensions don't match this node's.
Definition: RootNode.h:1441
const NodeT * probeConstNode(const Coord &xyz) const
Return a pointer to the node that contains voxel (x, y, z). If no such node exists, return nullptr.
Definition: RootNode.h:2830
A list of types (not necessarily unique)
Definition: TypeList.h:483
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:1978
DenseIter< const RootNode, MapCIter, const ChildType, const ValueType > ChildAllCIter
Definition: RootNode.h:365
T truncateRealToHalf(const T &val)
Return the given value truncated to 16-bit float precision.
Definition: Compression.h:216
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: Types.h:582
typename ChildType::ValueType ValueType
Definition: RootNode.h:43
LeafNodeType * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one that preserves the values and active states of all voxels.
Definition: RootNode.h:2768
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...
void writeBuffers(std::ostream &, bool toHalf=false) const
Definition: RootNode.h:2460
Index getHeight() const
Definition: RootNode.h:463
BBox< Coord > CoordBBox
Definition: NanoVDB.h:1809
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: RootNode.h:2046
Index64 onVoxelCount() const
Definition: RootNode.h:1620
int32_t Int32
Definition: Types.h:56
void merge(RootNode &other)
Efficiently merge another tree into this tree using one of several schemes.
Definition: RootNode.h:3021
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() but, if necessary, update the given accessor with pointers to the nodes along the...
Definition: RootNode.h:33
ChildOnIter beginChildOn()
Definition: RootNode.h:381
void combine2(const RootNode &other0, const OtherRootNode &other1, CombineOp &op, bool prune=false)
Definition: RootNode.h:3336
void setTransientData(Index32 transientData)
Set the transient data value.
Definition: RootNode.h:412
NodeT * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists, return nullptr.
Definition: RootNode.h:2812
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: RootNode.h:2073
size_t numBackgroundTiles() const
Return the number of background tiles.
Definition: RootNode.h:1292
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:1895
void stealNodes(ArrayT &array)
Steals all nodes of a certain type from the tree and adds them to a container with the following API:...
Definition: RootNode.h:818
bool readTopology(std::istream &, bool fromHalf=false)
Definition: RootNode.h:2354
ChildOffCIter beginChildOff() const
Definition: RootNode.h:379
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
ValueIter< const RootNode, MapCIter, ValueAllPred, const ValueType > ValueAllCIter
Definition: RootNode.h:372
bool isBackgroundTile(const Tile &) const
Return true if the given tile is inactive and has the background value.
Definition: RootNode.h:1270
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:2544
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:1765
static void combine2(RootT &self, const RootT &, const OtherRootT &other1, CombineOp &, bool)
Definition: RootNode.h:3306
bool probeValue(const Coord &xyz, ValueType &value) const
Definition: RootNode.h:2104
static Index getChildDim()
Definition: RootNode.h:457
bool operator!=(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Inequality operator, does exact floating point comparisons.
Definition: Vec3.h:481
Index32 transientData() const
Return the transient data value.
Definition: RootNode.h:410
RootNode()
Construct a new tree with a background value of 0.
Definition: RootNode.h:1036
static Index getLevel()
Definition: RootNode.h:455
Definition: Exceptions.h:13
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:2653
Index64 onTileCount() const
Definition: RootNode.h:1675
Definition: RootNode.h:34
void topologyIntersection(const RootNode< OtherChildType > &other)
Intersects this tree's set of active values with the active values of the other tree, whose ValueType may be different.
Definition: RootNode.h:3171
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: RootNode.h:1914
ValueT value
Definition: GridBuilder.h:1290
ValueIter< RootNode, MapIter, ValueAllPred, ValueType > ValueAllIter
Definition: RootNode.h:371
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: RootNode.h:1955
int getValueDepthAndCache(const Coord &xyz, AccessorT &) const
Definition: RootNode.h:1775
Definition: Exceptions.h:64
Index64 offVoxelCount() const
Definition: RootNode.h:1636
uint32_t Index32
Definition: Types.h:52
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:2140
bool isOn(Index32 i) const
Definition: NodeMasks.h:1331
Index64 offLeafVoxelCount() const
Definition: RootNode.h:1664
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return nullptr.
Definition: RootNode.h:2855
const ValueType & background() const
Return this node's background value.
Definition: RootNode.h:430
const LeafNodeType * probeConstLeafAndCache(const Coord &xyz, AccessorT &acc) const
Same as probeLeaf() but, if necessary, update the given accessor with pointers to the nodes along the...
RootNode & operator=(const RootNode &other)
Copy a root node of the same type as this node.
Definition: RootNode.h:1199
Index getDepth() const
Definition: RootNode.h:464
RootNode(const RootNode &other)
Definition: RootNode.h:75
Definition: RootNode.h:32
ValueOffCIter beginValueOff() const
Definition: RootNode.h:389
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:473
ValueOffCIter cbeginValueOff() const
Definition: RootNode.h:386
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: RootNode.h:1871
Vec2< T > minComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise minimum of the two vectors.
Definition: Vec2.h:504
void setOrigin(const Coord &origin)
change the origin on this root node
Definition: RootNode.h:2669
bool resultIsActive() const
Definition: Types.h:593
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:2584
Index32 FindHighestOn(Index32 v)
Return the most significant on bit of the given 32-bit value.
Definition: NodeMasks.h:159
bool expand(const Coord &xyz)
Expand this node's table so that (x, y, z) is included in the index range.
Definition: RootNode.h:1343
DenseIter< RootNode, MapIter, ChildType, ValueType > ChildAllIter
Definition: RootNode.h:364
ChildAllCIter cbeginChildAll() const
Definition: RootNode.h:377
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< const RootNode, MapCIter, ValueOffPred, const ValueType > ValueOffCIter
Definition: RootNode.h:370
static bool hasCompatibleValueType(const RootNode< OtherChildType > &other)
Definition: RootNode.h:1473
Index32 leafCount() const
Definition: RootNode.h:1582
typename NodeChain< typename HeadT::ChildNodeType, HeadLevel-1 >::Type SubtreeT
Definition: RootNode.h:1002
Definition: NodeMasks.h:1066
Index getWidth() const
Definition: RootNode.h:462
ValueIter< RootNode, MapIter, ChildOffPred, const ValueType > ChildOffIter
Definition: RootNode.h:362
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:2680
static void copyWithValueConversion(RootT &self, const OtherRootT &other)
Definition: RootNode.h:1134
typename ChildType::BuildType BuildType
Definition: RootNode.h:44
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:644
ChildType ChildNodeType
Definition: RootNode.h:41
Coord getMaxIndex() const
Return the largest index of the current tree.
Definition: RootNode.h:1373
void clear()
Definition: RootNode.h:1514
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:2565
void getIndexRange(CoordBBox &bbox) const
Return the current index range. Both min and max are inclusive.
Definition: RootNode.h:1381
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of a RootNod...
Definition: RootNode.h:64
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:2727
void clip(const CoordBBox &)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: RootNode.h:2504
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
Definition: RootNode.h:1500
void topologyDifference(const RootNode< OtherChildType > &other)
Difference this tree's set of active values with the active values of the other tree, whose ValueType may be different. So a resulting voxel will be active only if the original voxel is active in this tree and inactive in the other tree.
Definition: RootNode.h:3207
bool hasActiveTiles() const
Return true if this root node, or any of its child nodes, have active tiles.
Definition: RootNode.h:1718
static void getNodeLog2Dims(std::vector< Index > &dims)
Definition: RootNode.h:1357
void combine(RootNode &other, CombineOp &, bool prune=false)
Definition: RootNode.h:3246
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Definition: RootNode.h:1824
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:1394
bool empty() const
Return true if this node's table is either empty or contains only background tiles.
Definition: RootNode.h:448
~RootNode()
Definition: RootNode.h:123
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Definition: RootNode.h:1729
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
void load(std::istream &is)
Definition: NodeMasks.h:1372
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:529
size_t eraseBackgroundTiles()
Remove all background tiles.
Definition: RootNode.h:1304
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:70
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition: RootNode.h:1787
ValueAllIter beginValueAll()
Definition: RootNode.h:393
ChildIter< RootNode, MapIter, ChildOnPred, ChildType > ChildOnIter
Definition: RootNode.h:360
ValueType combine(const ValueType &v0, const ValueType &v1, const ValueType &v2, const openvdb::Vec3d &w)
Combine different value types.
Definition: AttributeTransferUtil.h:141
typename SubtreeT::template Append< HeadT > Type
Definition: RootNode.h:1003
ValueOnIter beginValueOn()
Definition: RootNode.h:391
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Definition: RootNode.h:2120
Coord getMinIndex() const
Return the smallest index of the current tree.
Definition: RootNode.h:1366
Definition: RootNode.h:38
typename NodeChain< RootNode, LEVEL >::Type NodeChainType
NodeChainType is a list of this tree's node types, from LeafNodeType to RootNode. ...
Definition: RootNode.h:49
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition: RootNode.h:2931
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:212
Tag dispatch class that distinguishes constructors during file input.
Definition: Types.h:650
static CoordBBox getNodeBoundingBox()
Return the bounding box of this RootNode, i.e., an infinite bounding box.
Definition: RootNode.h:406
const AValueType & result() const
Get the output value.
Definition: Types.h:574
static void combine2(RootT &self, const RootT &other0, const OtherRootT &other1, CombineOp &op, bool prune)
Definition: RootNode.h:3325