8 #ifndef OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED
9 #define OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED
18 #include <tbb/parallel_for.h>
31 template<
typename HeadType,
int HeadLevel>
struct NodeChain;
37 template<
typename ChildType>
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>
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) {} }
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) {}
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;
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); }
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;
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; }
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>
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;
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>;
408 #if OPENVDB_ABI_VERSION_NUMBER >= 9
410 Index32 transientData()
const {
return mTransientData; }
412 void setTransientData(
Index32 transientData) { mTransientData = transientData; }
453 bool expand(
const Coord& xyz);
475 template<
typename OtherChildType>
479 template<
typename OtherChildType>
484 template<
typename OtherChildType>
495 void nodeCount(std::vector<Index32> &vec)
const;
523 template<
typename ModifyOp>
524 void modifyValue(
const Coord& xyz,
const ModifyOp& op);
526 template<
typename ModifyOp>
538 void fill(
const CoordBBox& bbox,
const ValueType& value,
bool active =
true);
541 this->
fill(bbox, value, active);
569 template<
typename DenseT>
570 void copyToDense(
const CoordBBox& bbox, DenseT& dense)
const;
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>
604 template<
typename AccessorT>
611 template<
typename AccessorT>
619 template<
typename ModifyOp,
typename AccessorT>
626 template<
typename ModifyOp,
typename AccessorT>
633 template<
typename AccessorT>
640 template<
typename AccessorT>
648 template<
typename AccessorT>
656 template<
typename AccessorT>
660 void clip(
const CoordBBox&);
675 template<
typename AccessorT>
686 template<
typename NodeT>
707 template<
typename AccessorT>
719 template<
typename AccessorT>
725 template <
typename NodeT>
727 template <
typename NodeT>
734 template<
typename NodeT,
typename AccessorT>
736 template<
typename NodeT,
typename AccessorT>
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>
817 template<
typename ArrayT>
846 template<
typename OtherChildType>
862 template<
typename OtherChildType>
875 template<
typename OtherChildType>
878 template<
typename CombineOp>
881 template<
typename CombineOp,
typename OtherRootNode >
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>
952 static void enforceSameConfiguration(
const RootNode<OtherChildType>& other);
959 template<
typename OtherChildType>
960 static void enforceCompatibleValueTypes(
const RootNode<OtherChildType>& other);
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>
1046 template<
typename ChildT>
1049 : mBackground(background)
1058 template<
typename ChildT>
1059 template<
typename OtherChildType>
1063 : mBackground(backgd)
1065 , mOrigin(other.mOrigin)
1068 , mTransientData(other.mTransientData)
1073 #if OPENVDB_ABI_VERSION_NUMBER >= 10
1074 if (mOrigin != Coord(0,0,0)) {
1075 OPENVDB_THROW(ValueError,
"RootNode::RootNode: non-zero offsets are currently not supported");
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)
1099 , mOrigin(other.mOrigin)
1102 , mTransientData(other.mTransientData)
1107 #if OPENVDB_ABI_VERSION_NUMBER >= 10
1108 if (mOrigin != Coord(0,0,0)) {
1109 OPENVDB_THROW(ValueError,
"RootNode::RootNode: non-zero offsets are currently not supported");
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>
1198 inline RootNode<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)) {
1206 OPENVDB_THROW(ValueError,
"RootNode::operator=: non-zero offsets are currently not supported");
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;
1258 tile.value = background;
1265 mBackground = background;
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) {
1296 if (this->isBackgroundTile(i)) ++count;
1302 template<
typename ChildT>
1306 std::set<Coord> keysToErase;
1307 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1308 if (this->isBackgroundTile(i)) keysToErase.insert(i->first);
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
1332 RootNode<ChildT>::findOrAddCoord(
const Coord& xyz)
1334 const Coord key = coordToKey(xyz);
1335 std::pair<MapIter, bool>
result = mTable.insert(
1337 return result.first;
1341 template<
typename ChildT>
1345 const Coord key = coordToKey(xyz);
1346 std::pair<MapIter, bool> result = mTable.insert(
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>
1383 bbox.min() = this->getMinIndex();
1384 bbox.max() = this->getMaxIndex();
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;
1401 if (!hasSameConfiguration(other))
return false;
1404 OtherMapT copyOfOtherTable = other.mTable;
1407 for (MapCIter thisIter = mTable.begin(); thisIter != mTable.end(); ++thisIter) {
1408 if (this->isBackgroundTile(thisIter))
continue;
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>
1540 return this->childCount();
1544 template<
typename ChildT>
1546 RootNode<ChildT>::getTileCount()
const
1549 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1550 if (isTile(i)) ++sum;
1556 template<
typename ChildT>
1558 RootNode<ChildT>::getActiveTileCount()
const
1561 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1562 if (isTileOn(i)) ++sum;
1568 template<
typename ChildT>
1570 RootNode<ChildT>::getInactiveTileCount()
const
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();
1642 }
else if (isTileOff(i) && !this->isBackgroundTile(i)) {
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()) {
2205 sparseFill(bbox, value, active);
2206 voxelizeActiveTiles(
true);
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));
2555 this->eraseBackgroundTiles();
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)) {
2673 OPENVDB_THROW(ValueError,
"RootNode::setOrigin: non-zero offsets are currently not supported");
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*
2884 return this->probeConstLeafAndCache(xyz, acc);
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>
2935 "argument to getNodes() must be a pointer array");
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>
2963 "argument to getNodes() must be a pointer array");
2966 "argument to getNodes() must be an array of const node pointers");
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>
2993 "argument to stealNodes() must be a pointer array");
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 AValueType & result() const
Get the output value.
Vec2< T > minComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise minimum of the two vectors.
ChildAllCIter beginChildAll() const
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
static void combine2(RootT &self, const RootT &other0, const OtherRootT &other1, CombineOp &op, bool prune)
ValueOnIter beginValueOn()
ChildOffCIter cbeginChildOff() const
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
static void copyWithValueConversion(RootT &self, const OtherRootT &other)
cvex test(vector P=0;int unbound=3;export float s=0;export vector Cf=0;)
ValueOffCIter beginValueOff() const
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
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.
Coord getMaxIndex() const
Return the largest index of the current tree.
bool empty() const
Return true if this node's table is either empty or contains only background tiles.
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() but, if necessary, update the given accessor with pointers to the nodes along the...
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.
ValueAllCIter cbeginValueAll() const
ValueIter< const RootNode, MapCIter, ChildOffPred, ValueType > ChildOffCIter
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
void setBackground(const ValueType &value, bool updateChildNodes)
Change inactive tiles or voxels with a value equal to +/- the old background to the specified value (...
int getValueDepthAndCache(const Coord &xyz, AccessorT &) const
bool isOn(Index32 i) const
RootNode & operator=(const RootNode &other)
Copy a root node of the same type as this node.
T negative(const T &val)
Return the unary negation of the given value.
bool probeValue(const Coord &xyz, ValueType &value) const
DenseIter< RootNode, MapIter, ChildType, ValueType > ChildAllIter
void getIndexRange(CoordBBox &bbox) const
Return the current index range. Both min and max are inclusive.
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
GLsizei const GLfloat * value
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 ...
Index32 childCount() const
GLdouble GLdouble GLdouble z
Index32 leafCount() const
const ValueType & background() const
Return this node's background value.
Index64 offLeafVoxelCount() const
ValueConverter<T>::Type is the type of a RootNode having the same child hierarchy as this node but a ...
#define OPENVDB_USE_VERSION_NAMESPACE
void merge(RootNode &other)
Efficiently merge another tree into this tree using one of several schemes.
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
bool isBackgroundTile(const Tile &) const
Return true if the given tile is inactive and has the background value.
ChildOnCIter beginChildOn() const
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
ValueOnCIter beginValueOn() const
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
**But if you need a or simply need to know when the task has note that the like this
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...
**But if you need a result
void stealNodes(ArrayT &array)
Steals all nodes of a certain type from the tree and adds them to a container with the following API:...
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...
void combine(RootNode &other, CombineOp &, bool prune=false)
typename NodeChain< RootNode, LEVEL >::Type NodeChainType
NodeChainType is a list of this tree's node types, from LeafNodeType to RootNode. ...
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Tag dispatch class that distinguishes constructors during file input.
typename NodeChain< typename HeadT::ChildNodeType, HeadLevel-1 >::Type SubtreeT
#define OPENVDB_ABI_VERSION_NUMBER
The ABI version that OpenVDB was built with.
Index32 FindHighestOn(Index32 v)
Return the most significant on bit of the given 32-bit value.
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of a RootNode ...
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.
ValueIter< RootNode, MapIter, ValueAllPred, ValueType > ValueAllIter
static void getNodeLog2Dims(std::vector< Index > &dims)
ValueOnCIter cbeginValueOn() const
static bool hasSameConfiguration(const RootNode< OtherChildType > &other)
Return false if the other node's dimensions don't match this node's.
ChildOffIter beginChildOff()
bool isValueOn(const Coord &xyz) const
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
ChildAllIter beginChildAll()
typename ChildType::ValueType ValueType
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
void load(std::istream &is)
ValueOffIter beginValueOff()
Index64 onTileCount() const
typename SubtreeT::template Append< HeadT > Type
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don't change its value.
Index getTableSize() const
Return the number of entries in this node's table.
static bool hasCompatibleValueType(const RootNode< OtherChildType > &other)
ImageBuf OIIO_API sub(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
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, ValueOnPred, const ValueType > ValueOnCIter
T truncateRealToHalf(const T &val)
Return the given value truncated to 16-bit float precision.
ChildOnCIter cbeginChildOn() const
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.
typename ChildType::BuildType BuildType
bool resultIsActive() const
RootNode()
Construct a new tree with a background value of 0.
Index64 onVoxelCount() const
typename ChildType::LeafNodeType LeafNodeType
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
static void combine2(RootT &self, const RootT &, const OtherRootT &other1, CombineOp &, bool)
bool hasActiveTiles() const
Return true if this root node, or any of its child nodes, have active tiles.
const ValueType & getValue(const Coord &xyz) const
ValueIter< const RootNode, MapCIter, ValueOffPred, const ValueType > ValueOffCIter
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...
ValueOffCIter cbeginValueOff() const
void combine2(const RootNode &other0, const OtherRootNode &other1, CombineOp &op, bool prune=false)
IMATH_HOSTDEVICE constexpr Color4< T > operator*(S a, const Color4< T > &v) IMATH_NOEXCEPT
Reverse multiplication: S * Color4.
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...
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.
bool expand(const Coord &xyz)
Expand this node's table so that (x, y, z) is included in the index range.
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...
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...
GLuint const GLchar * name
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:...
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
DenseIter< const RootNode, MapCIter, const ChildType, const ValueType > ChildAllCIter
GLboolean GLboolean GLboolean b
Coord getMinIndex() const
Return the smallest index of the current tree.
bool writeTopology(std::ostream &, bool toHalf=false) const
GLenum GLenum GLsizei void * table
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
ChildIter< RootNode, MapIter, ChildOnPred, ChildType > ChildOnIter
static void copyWithValueConversion(RootT &self, const OtherRootT &other)
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...
void readBuffers(std::istream &, bool fromHalf=false)
CanConvertType<FromType, ToType>::value is true if a value of type ToType can be constructed from a v...
ValueAllCIter beginValueAll() const
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
Library and file format version numbers.
RootNode(const RootNode< OtherChildType > &other)
Construct a new tree that reproduces the topology and active states of a tree of a different ValueTyp...
size_t eraseBackgroundTiles()
Remove all background tiles.
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
size_t numBackgroundTiles() const
Return the number of background tiles.
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.
ChildOffCIter beginChildOff() const
void sparseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
static Index getChildDim()
GA_API const UT_StringHolder N
bool addChild(ChildType *child)
Add the given child node at the root level. If a child node with the same origin already exists...
ValueIter< RootNode, MapIter, ChildOffPred, const ValueType > ChildOffIter
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...
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.
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...
**If you just want to fire and args
ValueIter< RootNode, MapIter, ValueOnPred, ValueType > ValueOnIter
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
void modifyValueAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Index64 onLeafVoxelCount() const
bool readTopology(std::istream &, bool fromHalf=false)
ChildAllCIter cbeginChildAll() const
NodeT * probeNodeAndCache(const Coord &xyz, AccessorT &acc)
Same as probeNode() but, if necessary, update the given accessor with pointers to the nodes along the...
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
bool operator!=(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Index32 nonLeafCount() const
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 ...
SIM_API const UT_StringHolder distance
ChildIter< const RootNode, MapCIter, ChildOnPred, const ChildType > ChildOnCIter
void setValueOn(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T clip(const T &p, const Box< T > &box) IMATH_NOEXCEPT
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
A list of types (not necessarily unique)
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...
static CoordBBox getNodeBoundingBox()
Return the bounding box of this RootNode, i.e., an infinite bounding box.
ValueAllIter beginValueAll()
int getValueDepth(const Coord &xyz) const
Return the tree depth (0 = root) at which the value of voxel (x, y, z) resides.
void nodeCount(std::vector< Index32 > &vec) const
ValueIter< RootNode, MapIter, ValueOffPred, ValueType > ValueOffIter
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...
RootNode(const RootNode &other)
ChildOnIter beginChildOn()
#define OPENVDB_THROW(exception, message)
void addLeafAndCache(LeafNodeType *leaf, AccessorT &)
Same as addLeaf() but, if necessary, update the given accessor with pointers to the nodes along the p...
void fill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
Index64 offVoxelCount() const
ValueIter< const RootNode, MapCIter, ValueAllPred, const ValueType > ValueAllCIter
NodeChain<RootNodeType, RootNodeType::LEVEL>::Type is a openvdb::TypeList that lists the types of the...
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
void clip(const CoordBBox &)
Set all voxels that lie outside the given axis-aligned box to the background.
shared_ptr< Node > NodePtr
A shared pointer to a Node.
NodeT * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists, return nullptr.