8 #ifndef OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED
9 #define OPENVDB_TREE_ROOTNODE_HAS_BEEN_INCLUDED
19 #include <tbb/parallel_for.h>
32 template<
typename HeadType,
int HeadLevel>
struct NodeChain;
38 template<
typename ChildType>
51 static_assert(NodeChainType::Size ==
LEVEL + 1,
52 "wrong number of entries in RootNode node chain");
56 template<
typename OtherValueType>
64 template<
typename OtherNodeType>
84 template<
typename OtherChildType>
95 template<
typename OtherChildType>
109 template<
typename OtherChildType>
121 template<
typename OtherChildType>
139 NodeStruct(): child(nullptr) {}
140 NodeStruct(ChildType&
c): child(&c) {}
141 NodeStruct(
const Tile&
t): child(nullptr), tile(t) {}
142 NodeStruct(
const NodeStruct&) =
default;
143 NodeStruct(NodeStruct&&) noexcept = default;
144 NodeStruct& operator=(const NodeStruct&) = default;
147 bool isChild()
const {
return child !=
nullptr; }
148 bool isTile()
const {
return child ==
nullptr; }
149 bool isTileOff()
const {
return isTile() && !tile.active; }
150 bool isTileOn()
const {
return isTile() && tile.active; }
152 void set(ChildType&
c) {
delete child; child = &
c; }
153 void set(
const Tile&
t) {
delete child; child =
nullptr; tile =
t; }
154 ChildType& steal(
const Tile&
t) { ChildType*
c=child; child=
nullptr; tile=
t;
return *
c; }
157 using MapType = std::map<Coord, NodeStruct>;
158 using MapIter =
typename MapType::iterator;
159 using MapCIter =
typename MapType::const_iterator;
161 using CoordSet = std::set<Coord>;
162 using CoordSetIter =
typename CoordSet::iterator;
163 using CoordSetCIter =
typename CoordSet::const_iterator;
165 static void setTile(
const MapIter& i,
const Tile&
t) { i->second.set(t); }
166 static void setChild(
const MapIter& i, ChildType&
c) { i->second.set(c); }
167 static Tile& getTile(
const MapIter& i) {
return i->second.tile; }
168 static const Tile& getTile(
const MapCIter& i) {
return i->second.tile; }
169 static ChildType& getChild(
const MapIter& i) {
return *(i->second.child); }
170 static const ChildType& getChild(
const MapCIter& i) {
return *(i->second.child); }
171 static ChildType& stealChild(
const MapIter& i,
const Tile& t) {
return i->second.steal(t);}
172 static const ChildType& stealChild(
const MapCIter& i,
const Tile& t) {
return i->second.steal(t);}
174 static bool isChild(
const MapCIter& i) {
return i->second.isChild(); }
175 static bool isChild(
const MapIter& i) {
return i->second.isChild(); }
176 static bool isTile(
const MapCIter& i) {
return i->second.isTile(); }
177 static bool isTile(
const MapIter& i) {
return i->second.isTile(); }
178 static bool isTileOff(
const MapCIter& i) {
return i->second.isTileOff(); }
179 static bool isTileOff(
const MapIter& i) {
return i->second.isTileOff(); }
180 static bool isTileOn(
const MapCIter& i) {
return i->second.isTileOn(); }
181 static bool isTileOn(
const MapIter& i) {
return i->second.isTileOn(); }
184 static inline bool test(
const MapIter&) {
return true; }
185 static inline bool test(
const MapCIter&) {
return true; }
188 static inline bool test(
const MapIter& i) {
return isTileOn(i); }
189 static inline bool test(
const MapCIter& i) {
return isTileOn(i); }
191 struct ValueOffPred {
192 static inline bool test(
const MapIter& i) {
return isTileOff(i); }
193 static inline bool test(
const MapCIter& i) {
return isTileOff(i); }
195 struct ValueAllPred {
196 static inline bool test(
const MapIter& i) {
return isTile(i); }
197 static inline bool test(
const MapCIter& i) {
return isTile(i); }
200 static inline bool test(
const MapIter& i) {
return isChild(i); }
201 static inline bool test(
const MapCIter& i) {
return isChild(i); }
203 struct ChildOffPred {
204 static inline bool test(
const MapIter& i) {
return isTile(i); }
205 static inline bool test(
const MapCIter& i) {
return isTile(i); }
208 template<
typename _RootNodeT,
typename _MapIterT,
typename FilterPredT>
212 using RootNodeT = _RootNodeT;
213 using MapIterT = _MapIterT;
217 return (mParentNode == other.mParentNode) && (mIter == other.mIter);
219 bool operator!=(
const BaseIter& other)
const {
return !(*
this == other); }
221 RootNodeT* getParentNode()
const {
return mParentNode; }
223 RootNodeT& parent()
const
225 if (!mParentNode)
OPENVDB_THROW(ValueError,
"iterator references a null parent node");
229 bool test()
const {
OPENVDB_ASSERT(mParentNode);
return mIter != mParentNode->mTable.end(); }
230 operator bool()
const {
return this->
test(); }
232 void increment() {
if (this->
test()) { ++mIter; } this->
skip(); }
233 bool next() { this->increment();
return this->
test(); }
234 void increment(Index
n) {
for (Index i = 0; i < n && this->next(); ++i) {} }
243 bool isValueOn()
const {
return RootNodeT::isTileOn(mIter); }
244 bool isValueOff()
const {
return RootNodeT::isTileOff(mIter); }
245 void setValueOn(
bool on =
true)
const { mIter->second.tile.active = on; }
246 void setValueOff()
const { mIter->second.tile.active =
false; }
249 Coord getCoord()
const {
return mIter->first; }
251 void getCoord(Coord& xyz)
const { xyz = this->getCoord(); }
254 BaseIter(): mParentNode(nullptr) {}
255 BaseIter(RootNodeT& parent,
const MapIterT& iter): mParentNode(&parent), mIter(iter) {}
259 RootNodeT* mParentNode;
263 template<
typename RootNodeT,
typename MapIterT,
typename FilterPredT,
typename ChildNodeT>
264 class ChildIter:
public BaseIter<RootNodeT, MapIterT, FilterPredT>
267 using BaseT = BaseIter<RootNodeT, MapIterT, FilterPredT>;
268 using NodeType = RootNodeT;
277 ChildIter(RootNodeT& parent,
const MapIterT& iter):
BaseT(parent, iter) {
BaseT::skip(); }
279 ChildIter& operator++() { BaseT::increment();
return *
this; }
281 ChildNodeT&
getValue()
const {
return getChild(mIter); }
283 ChildNodeT* operator->()
const {
return &this->
getValue(); }
286 template<
typename RootNodeT,
typename MapIterT,
typename FilterPredT,
typename ValueT>
287 class ValueIter:
public BaseIter<RootNodeT, MapIterT, FilterPredT>
290 using BaseT = BaseIter<RootNodeT, MapIterT, FilterPredT>;
291 using NodeType = RootNodeT;
298 ValueIter(RootNodeT& parent,
const MapIterT& iter):
BaseT(parent, iter) {
BaseT::skip(); }
300 ValueIter& operator++() { BaseT::increment();
return *
this; }
302 ValueT&
getValue()
const {
return getTile(mIter).value; }
304 ValueT* operator->()
const {
return &(this->
getValue()); }
308 template<
typename ModifyOp>
316 template<
typename RootNodeT,
typename MapIterT,
typename ChildNodeT,
typename ValueT>
317 class DenseIter:
public BaseIter<RootNodeT, MapIterT, NullPred>
320 using BaseT = BaseIter<RootNodeT, MapIterT, NullPred>;
321 using NodeType = RootNodeT;
330 DenseIter(RootNodeT& parent,
const MapIterT& iter):
BaseT(parent, iter) {}
332 DenseIter& operator++() { BaseT::increment();
return *
this; }
334 bool isChildNode()
const {
return isChild(mIter); }
338 if (isChild(mIter))
return &getChild(mIter);
339 value = getTile(mIter).value;
342 bool probeChild(ChildNodeT*& child, NonConstValueType& value)
const
345 return child !=
nullptr;
349 void setChild(ChildNodeT& c)
const { RootNodeT::setChild(mIter, c); }
350 void setChild(ChildNodeT* c)
const {
OPENVDB_ASSERT(c !=
nullptr); RootNodeT::setChild(mIter, *c); }
351 void setValue(
const ValueT& v)
const
353 if (isTile(mIter)) getTile(mIter).value =
v;
357 else stealChild(mIter, Tile(v,
true));
362 using ChildOnIter = ChildIter<RootNode, MapIter, ChildOnPred, ChildType>;
363 using ChildOnCIter = ChildIter<const RootNode, MapCIter, ChildOnPred, const ChildType>;
364 using ChildOffIter = ValueIter<RootNode, MapIter, ChildOffPred, const ValueType>;
365 using ChildOffCIter = ValueIter<const RootNode, MapCIter, ChildOffPred, ValueType>;
366 using ChildAllIter = DenseIter<RootNode, MapIter, ChildType, ValueType>;
367 using ChildAllCIter = DenseIter<const RootNode, MapCIter, const ChildType, const ValueType>;
369 using ValueOnIter = ValueIter<RootNode, MapIter, ValueOnPred, ValueType>;
370 using ValueOnCIter = ValueIter<const RootNode, MapCIter, ValueOnPred, const ValueType>;
371 using ValueOffIter = ValueIter<RootNode, MapIter, ValueOffPred, ValueType>;
372 using ValueOffCIter = ValueIter<const RootNode, MapCIter, ValueOffPred, const ValueType>;
373 using ValueAllIter = ValueIter<RootNode, MapIter, ValueAllPred, ValueType>;
374 using ValueAllCIter = ValueIter<const RootNode, MapCIter, ValueAllPred, const ValueType>;
453 bool expand(
const Coord& xyz);
475 template<
typename OtherChildType>
479 template<
typename OtherChildType>
484 template<
typename OtherChildType>
498 void nodeCount(std::vector<Index64> &vec)
const;
528 template<typename ModifyOp>
529 void modifyValue(const Coord& xyz, const ModifyOp& op);
531 template<typename ModifyOp>
574 template<
typename DenseT>
581 bool writeTopology(std::ostream&,
bool toHalf =
false)
const;
582 bool readTopology(std::istream&,
bool fromHalf =
false);
584 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
585 void readBuffers(std::istream&,
bool fromHalf =
false);
596 template<
typename AccessorT>
602 template<
typename AccessorT>
609 template<
typename AccessorT>
616 template<
typename AccessorT>
624 template<
typename ModifyOp,
typename AccessorT>
631 template<
typename ModifyOp,
typename AccessorT>
638 template<
typename AccessorT>
645 template<
typename AccessorT>
653 template<
typename AccessorT>
661 template<
typename AccessorT>
680 template<
typename AccessorT>
691 template<
typename NodeT>
712 template<
typename AccessorT>
730 template<
typename AccessorT>
736 template <
typename NodeT>
738 template <
typename NodeT>
739 const NodeT*
probeNode(
const Coord& xyz)
const;
740 template <
typename NodeT>
756 template<
typename NodeT,
typename AccessorT>
758 template<
typename NodeT,
typename AccessorT>
781 template<
typename AccessorT>
783 template<
typename AccessorT>
785 template<
typename AccessorT>
846 template<
typename ArrayT>
void getNodes(ArrayT& array);
847 template<
typename ArrayT>
void getNodes(ArrayT& array)
const;
874 template<
typename ArrayT>
876 template<
typename ArrayT>
905 template<
typename OtherChildType>
921 template<
typename OtherChildType>
934 template<
typename OtherChildType>
937 template<
typename CombineOp>
940 template<
typename CombineOp,
typename OtherRootNode >
942 CombineOp& op,
bool prune =
false);
945 const Coord&
origin()
const {
return mOrigin; }
954 Coord
coordToKey(
const Coord& xyz)
const {
return (xyz - mOrigin) & ~(ChildType::DIM - 1); }
957 bool hasKey(
const Coord& key)
const {
return mTable.find(key) != mTable.end(); }
968 void insertKeys(CoordSet&)
const;
973 MapIter findKey(
const Coord& key) {
return mTable.find(key); }
974 MapCIter findKey(
const Coord& key)
const {
return mTable.find(key); }
979 MapIter findCoord(
const Coord& xyz) {
return mTable.find(
coordToKey(xyz)); }
980 MapCIter findCoord(
const Coord& xyz)
const {
return mTable.find(
coordToKey(xyz)); }
985 MapIter findOrAddCoord(
const Coord& xyz);
991 template<
typename OtherChildType>
992 static void enforceSameConfiguration(
const RootNode<OtherChildType>& other);
999 template<
typename OtherChildType>
1000 static void enforceCompatibleValueTypes(
const RootNode<OtherChildType>& other);
1002 template<
typename CombineOp,
typename OtherRootNode >
1003 void doCombine2(
const RootNode&,
const OtherRootNode&, CombineOp&,
bool prune);
1036 template<
typename HeadT,
int HeadLevel>
1039 using Type =
typename SubtreeT::template Append<HeadT>;
1043 template<
typename HeadT>
1055 template<
typename ChildT1,
typename NodeT2>
1057 static const bool value =
false;
1060 template<
typename ChildT1,
typename ChildT2>
1070 template<
typename ChildT>
1079 template<
typename ChildT>
1082 : mBackground(background)
1088 template<
typename ChildT>
1089 template<
typename OtherChildType>
1093 : mBackground(backgd)
1094 , mOrigin(other.mOrigin)
1095 , mTransientData(other.mTransientData)
1099 if (mOrigin != Coord(0,0,0)) {
1100 OPENVDB_THROW(ValueError,
"RootNode::RootNode: non-zero offsets are currently not supported");
1103 enforceSameConfiguration(other);
1105 const Tile bgTile(backgd,
false), fgTile(foregd,
true);
1107 for (
typename OtherRootT::MapCIter i=other.mTable.begin(), e=other.mTable.end(); i != e; ++i) {
1108 mTable.emplace(i->first, OtherRootT::isTile(i)
1109 ? NodeStruct(OtherRootT::isTileOn(i) ? fgTile : bgTile)
1110 : NodeStruct(*(
new ChildT(OtherRootT::getChild(i), backgd, foregd,
TopologyCopy()))));
1115 template<
typename ChildT>
1116 template<
typename OtherChildType>
1120 : mBackground(backgd)
1121 , mOrigin(other.mOrigin)
1122 , mTransientData(other.mTransientData)
1126 if (mOrigin != Coord(0,0,0)) {
1127 OPENVDB_THROW(ValueError,
"RootNode::RootNode: non-zero offsets are currently not supported");
1130 enforceSameConfiguration(other);
1132 const Tile bgTile(backgd,
false), fgTile(backgd,
true);
1134 for (
typename OtherRootT::MapCIter i=other.mTable.begin(), e=other.mTable.end(); i != e; ++i) {
1135 mTable.emplace(i->first,
1136 OtherRootT::isTile(i)
1137 ? NodeStruct(OtherRootT::isTileOn(i) ? fgTile : bgTile)
1138 : NodeStruct(*(
new ChildT(OtherRootT::getChild(i), backgd,
TopologyCopy()))));
1149 template<
typename RootT,
typename OtherRootT,
bool Compatible = false>
1156 self.enforceSameConfiguration(other);
1157 self.enforceCompatibleValueTypes(other);
1159 std::ostringstream ostr;
1160 ostr <<
"cannot convert a " <<
typeid(OtherRootT).
name()
1161 <<
" to a " <<
typeid(RootT).
name();
1167 template<
typename RootT,
typename OtherRootT>
1173 using ChildT =
typename RootT::ChildNodeType;
1174 using Tile =
typename RootT::Tile;
1176 using OtherMapCIter =
typename OtherRootT::MapCIter;
1177 using OtherTile =
typename OtherRootT::Tile;
1181 static inline ValueT convertValue(
const OtherValueT&
val) {
return ValueT(val); }
1184 self.mBackground = Local::convertValue(other.mBackground);
1185 if (other.mOrigin != Coord(0,0,0)) {
1186 OPENVDB_THROW(ValueError,
"RootNodeCopyHelper::copyWithValueConversion: non-zero offsets are currently not supported");
1188 self.mOrigin = other.mOrigin;
1189 self.mTransientData = other.mTransientData;
1193 for (OtherMapCIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
1194 if (other.isTile(i)) {
1196 const OtherTile& otherTile = other.getTile(i);
1197 self.mTable.emplace(i->first,
1198 Tile(Local::convertValue(otherTile.value), otherTile.active));
1201 self.mTable.emplace(i->first, *(
new ChildT(other.getChild(i))));
1209 template<
typename ChildT>
1210 inline RootNode<ChildT>&
1213 if (&other !=
this) {
1214 mBackground = other.mBackground;
1215 mOrigin = other.mOrigin;
1216 if (mOrigin != Coord(0,0,0)) {
1217 OPENVDB_THROW(ValueError,
"RootNode::operator=: non-zero offsets are currently not supported");
1219 mTransientData = other.mTransientData;
1223 for (MapCIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
1224 mTable.emplace(i->first,
1225 isTile(i) ? NodeStruct(getTile(i)) : NodeStruct(*(
new ChildT(getChild(i)))));
1232 template<
typename ChildT>
1233 template<
typename OtherChildType>
1248 template<
typename ChildT>
1254 if (updateChildNodes) {
1257 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1258 ChildT *child = iter->second.child;
1260 child->resetBackground(mBackground, background);
1262 Tile& tile = getTile(iter);
1263 if (tile.active)
continue;
1265 tile.value = background;
1272 mBackground = background;
1275 template<
typename ChildT>
1282 template<
typename ChildT>
1289 template<
typename ChildT>
1297 template<
typename ChildT>
1302 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1303 if (this->isBackgroundTile(i)) ++count;
1309 template<
typename ChildT>
1313 std::set<Coord> keysToErase;
1314 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1315 if (this->isBackgroundTile(i)) keysToErase.insert(i->first);
1317 for (std::set<Coord>::iterator i = keysToErase.begin(), e = keysToErase.end(); i != e; ++i) {
1320 return keysToErase.size();
1327 template<
typename ChildT>
1331 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1332 keys.insert(i->first);
1337 template<
typename ChildT>
1338 inline typename RootNode<ChildT>::MapIter
1339 RootNode<ChildT>::findOrAddCoord(
const Coord& xyz)
1341 const Coord key = coordToKey(xyz);
1342 std::pair<MapIter, bool>
result = mTable.try_emplace(key,
1343 Tile(mBackground,
false));
1344 return result.first;
1348 template<
typename ChildT>
1352 const Coord key = coordToKey(xyz);
1353 std::pair<MapIter, bool> result = mTable.try_emplace(key,
1354 Tile(mBackground,
false));
1355 return result.second;
1362 template<
typename ChildT>
1367 ChildT::getNodeLog2Dims(dims);
1371 template<
typename ChildT>
1375 return mTable.empty() ? Coord(0) : mTable.begin()->first;
1378 template<
typename ChildT>
1382 return mTable.empty() ? Coord(0) : mTable.rbegin()->first + Coord(ChildT::DIM - 1);
1386 template<
typename ChildT>
1390 bbox.min() = this->getMinIndex();
1391 bbox.max() = this->getMaxIndex();
1398 template<
typename ChildT>
1399 template<
typename OtherChildType>
1404 using OtherMapT =
typename OtherRootT::MapType;
1405 using OtherIterT =
typename OtherRootT::MapIter;
1406 using OtherCIterT =
typename OtherRootT::MapCIter;
1408 if (!hasSameConfiguration(other))
return false;
1411 OtherMapT copyOfOtherTable = other.mTable;
1414 for (MapCIter thisIter = mTable.begin(); thisIter != mTable.end(); ++thisIter) {
1415 if (this->isBackgroundTile(thisIter))
continue;
1418 OtherCIterT otherIter = other.findKey(thisIter->first);
1419 if (otherIter == other.mTable.end())
return false;
1422 if (isChild(thisIter)) {
1423 if (OtherRootT::isTile(otherIter))
return false;
1425 if (!getChild(thisIter).hasSameTopology(&OtherRootT::getChild(otherIter)))
return false;
1427 if (OtherRootT::isChild(otherIter))
return false;
1428 if (getTile(thisIter).active != OtherRootT::getTile(otherIter).active)
return false;
1435 copyOfOtherTable.erase(otherIter->first);
1438 for (OtherIterT i = copyOfOtherTable.begin(), e = copyOfOtherTable.end(); i != e; ++i) {
1445 template<
typename ChildT>
1446 template<
typename OtherChildType>
1450 std::vector<Index> thisDims, otherDims;
1453 return (thisDims == otherDims);
1457 template<
typename ChildT>
1458 template<
typename OtherChildType>
1462 std::vector<Index> thisDims, otherDims;
1465 if (thisDims != otherDims) {
1466 std::ostringstream ostr;
1467 ostr <<
"grids have incompatible configurations (" << thisDims[0];
1468 for (
size_t i = 1,
N = thisDims.size(); i <
N; ++i) ostr <<
" x " << thisDims[i];
1469 ostr <<
" vs. " << otherDims[0];
1470 for (
size_t i = 1, N = otherDims.size(); i <
N; ++i) ostr <<
" x " << otherDims[i];
1477 template<
typename ChildT>
1478 template<
typename OtherChildType>
1487 template<
typename ChildT>
1488 template<
typename OtherChildType>
1494 std::ostringstream ostr;
1495 ostr <<
"values of type " << typeNameAsString<OtherValueType>()
1496 <<
" cannot be converted to type " << typeNameAsString<ValueType>();
1505 template<
typename ChildT>
1510 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1511 if (
const ChildT *child = iter->second.child) {
1512 sum += child->memUsage();
1519 template<
typename ChildT>
1523 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1524 delete i->second.child;
1530 template<
typename ChildT>
1534 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
1535 if (
const ChildT *child = iter->second.child) {
1536 child->evalActiveBoundingBox(bbox, visitVoxels);
1537 }
else if (isTileOn(iter)) {
1538 bbox.expand(iter->first, ChildT::DIM);
1544 template<
typename ChildT>
1549 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1550 if (isChild(i)) sum += getChild(i).leafCount();
1556 template<
typename ChildT>
1561 if (ChildT::LEVEL != 0) {
1562 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1563 if (isChild(i)) sum += getChild(i).nonLeafCount();
1570 template<
typename ChildT>
1575 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1576 if (isChild(i)) ++sum;
1582 template<
typename ChildT>
1587 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1588 if (isTile(i)) ++sum;
1594 template<
typename ChildT>
1599 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1600 if (isTileOn(i)) ++sum;
1606 template<
typename ChildT>
1611 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1612 if (isTileOff(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>
1694 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1697 getChild(i).nodeCount(vec);
1701 vec[ChildNodeType::LEVEL] = sum;
1704 template<
typename ChildT>
1710 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1714 getChild(i).nodeCount(vec);
1719 vec[ChildNodeType::LEVEL] = sum;
1725 template<
typename ChildT>
1729 MapCIter iter = this->findCoord(xyz);
1730 if (iter == mTable.end() || isTileOff(iter))
return false;
1731 return isTileOn(iter) ?
true : getChild(iter).isValueOn(xyz);
1734 template<
typename ChildT>
1738 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
1739 if (isChild(i) ? getChild(i).hasActiveTiles() : getTile(i).active)
return true;
1744 template<
typename ChildT>
1745 template<
typename AccessorT>
1749 MapCIter iter = this->findCoord(xyz);
1750 if (iter == mTable.end() || isTileOff(iter))
return false;
1751 if (isTileOn(iter))
return true;
1752 acc.insert(xyz, &getChild(iter));
1753 return getChild(iter).isValueOnAndCache(xyz, acc);
1757 template<
typename ChildT>
1761 MapCIter iter = this->findCoord(xyz);
1762 return iter == mTable.end() ? mBackground
1763 : (isTile(iter) ? getTile(iter).value : getChild(iter).getValue(xyz));
1766 template<
typename ChildT>
1767 template<
typename AccessorT>
1771 MapCIter iter = this->findCoord(xyz);
1772 if (iter == mTable.end())
return mBackground;
1773 if (isChild(iter)) {
1774 acc.insert(xyz, &getChild(iter));
1775 return getChild(iter).getValueAndCache(xyz, acc);
1777 return getTile(iter).value;
1781 template<
typename ChildT>
1785 MapCIter iter = this->findCoord(xyz);
1786 return iter == mTable.end() ? -1
1787 : (isTile(iter) ? 0 :
int(LEVEL) -
int(getChild(iter).getValueLevel(xyz)));
1790 template<
typename ChildT>
1791 template<
typename AccessorT>
1795 MapCIter iter = this->findCoord(xyz);
1796 if (iter == mTable.end())
return -1;
1797 if (isTile(iter))
return 0;
1798 acc.insert(xyz, &getChild(iter));
1799 return int(LEVEL) -
int(getChild(iter).getValueLevelAndCache(xyz, acc));
1803 template<
typename ChildT>
1807 MapIter iter = this->findCoord(xyz);
1808 if (iter != mTable.end() && !isTileOff(iter)) {
1809 if (isTileOn(iter)) {
1810 setChild(iter, *
new ChildT(xyz, getTile(iter).value,
true));
1812 getChild(iter).setValueOff(xyz);
1817 template<
typename ChildT>
1821 ChildT* child =
nullptr;
1822 const Coord key = this->coordToKey(xyz);
1823 MapIter iter = this->findKey(key);
1824 if (iter == mTable.end()) {
1826 child =
new ChildT(xyz, mBackground);
1827 mTable.emplace(key, *child);
1831 }
else if (isChild(iter)) {
1832 child = &getChild(iter);
1833 }
else if (on != getTile(iter).
active) {
1834 child =
new ChildT(xyz, getTile(iter).value, !on);
1835 setChild(iter, *child);
1837 if (child) child->setActiveState(xyz, on);
1840 template<
typename ChildT>
1841 template<
typename AccessorT>
1845 ChildT* child =
nullptr;
1846 const Coord key = this->coordToKey(xyz);
1847 MapIter iter = this->findKey(key);
1848 if (iter == mTable.end()) {
1850 child =
new ChildT(xyz, mBackground);
1851 mTable.emplace(key, *child);
1855 }
else if (isChild(iter)) {
1856 child = &getChild(iter);
1857 }
else if (on != getTile(iter).
active) {
1858 child =
new ChildT(xyz, getTile(iter).value, !on);
1859 setChild(iter, *child);
1862 acc.insert(xyz, child);
1863 child->setActiveStateAndCache(xyz, on, acc);
1868 template<
typename ChildT>
1872 ChildT* child =
nullptr;
1873 const Coord key = this->coordToKey(xyz);
1874 MapIter iter = this->findKey(key);
1875 if (iter == mTable.end()) {
1877 child =
new ChildT(xyz, mBackground);
1878 mTable.emplace(key, *child);
1880 }
else if (isChild(iter)) {
1881 child = &getChild(iter);
1883 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1884 setChild(iter, *child);
1886 if (child) child->setValueOff(xyz, value);
1889 template<
typename ChildT>
1890 template<
typename AccessorT>
1894 ChildT* child =
nullptr;
1895 const Coord key = this->coordToKey(xyz);
1896 MapIter iter = this->findKey(key);
1897 if (iter == mTable.end()) {
1899 child =
new ChildT(xyz, mBackground);
1900 mTable.emplace(key, *child);
1902 }
else if (isChild(iter)) {
1903 child = &getChild(iter);
1905 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1906 setChild(iter, *child);
1909 acc.insert(xyz, child);
1910 child->setValueOffAndCache(xyz, value, acc);
1915 template<
typename ChildT>
1919 ChildT* child =
nullptr;
1920 const Coord key = this->coordToKey(xyz);
1921 MapIter iter = this->findKey(key);
1922 if (iter == mTable.end()) {
1923 child =
new ChildT(xyz, mBackground);
1924 mTable.emplace(key, *child);
1925 }
else if (isChild(iter)) {
1926 child = &getChild(iter);
1928 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1929 setChild(iter, *child);
1931 if (child) child->setValueOn(xyz, value);
1934 template<
typename ChildT>
1935 template<
typename AccessorT>
1939 ChildT* child =
nullptr;
1940 const Coord key = this->coordToKey(xyz);
1941 MapIter iter = this->findKey(key);
1942 if (iter == mTable.end()) {
1943 child =
new ChildT(xyz, mBackground);
1944 mTable.emplace(key, *child);
1945 }
else if (isChild(iter)) {
1946 child = &getChild(iter);
1948 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1949 setChild(iter, *child);
1952 acc.insert(xyz, child);
1953 child->setValueAndCache(xyz, value, acc);
1958 template<
typename ChildT>
1962 ChildT* child =
nullptr;
1963 const Coord key = this->coordToKey(xyz);
1964 MapIter iter = this->findKey(key);
1965 if (iter == mTable.end()) {
1966 child =
new ChildT(xyz, mBackground);
1967 mTable.emplace(key, *child);
1968 }
else if (isChild(iter)) {
1969 child = &getChild(iter);
1971 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1972 setChild(iter, *child);
1974 if (child) child->setValueOnly(xyz, value);
1977 template<
typename ChildT>
1978 template<
typename AccessorT>
1982 ChildT* child =
nullptr;
1983 const Coord key = this->coordToKey(xyz);
1984 MapIter iter = this->findKey(key);
1985 if (iter == mTable.end()) {
1986 child =
new ChildT(xyz, mBackground);
1987 mTable.emplace(key, *child);
1988 }
else if (isChild(iter)) {
1989 child = &getChild(iter);
1991 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
1992 setChild(iter, *child);
1995 acc.insert(xyz, child);
1996 child->setValueOnlyAndCache(xyz, value, acc);
2001 template<
typename ChildT>
2002 template<
typename ModifyOp>
2006 ChildT* child =
nullptr;
2007 const Coord key = this->coordToKey(xyz);
2008 MapIter iter = this->findKey(key);
2009 if (iter == mTable.end()) {
2010 child =
new ChildT(xyz, mBackground);
2011 mTable.emplace(key, *child);
2012 }
else if (isChild(iter)) {
2013 child = &getChild(iter);
2017 bool createChild = isTileOff(iter);
2021 const ValueType& tileVal = getTile(iter).value;
2027 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2028 setChild(iter, *child);
2031 if (child) child->modifyValue(xyz, op);
2034 template<
typename ChildT>
2035 template<
typename ModifyOp,
typename AccessorT>
2039 ChildT* child =
nullptr;
2040 const Coord key = this->coordToKey(xyz);
2041 MapIter iter = this->findKey(key);
2042 if (iter == mTable.end()) {
2043 child =
new ChildT(xyz, mBackground);
2044 mTable.emplace(key, *child);
2045 }
else if (isChild(iter)) {
2046 child = &getChild(iter);
2050 bool createChild = isTileOff(iter);
2054 const ValueType& tileVal = getTile(iter).value;
2060 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2061 setChild(iter, *child);
2065 acc.insert(xyz, child);
2066 child->modifyValueAndCache(xyz, op, acc);
2071 template<
typename ChildT>
2072 template<
typename ModifyOp>
2076 ChildT* child =
nullptr;
2077 const Coord key = this->coordToKey(xyz);
2078 MapIter iter = this->findKey(key);
2079 if (iter == mTable.end()) {
2080 child =
new ChildT(xyz, mBackground);
2081 mTable.emplace(key, *child);
2082 }
else if (isChild(iter)) {
2083 child = &getChild(iter);
2085 const Tile& tile = getTile(iter);
2086 bool modifiedState = tile.active;
2088 op(modifiedVal, modifiedState);
2092 child =
new ChildT(xyz, tile.value, tile.active);
2093 setChild(iter, *child);
2096 if (child) child->modifyValueAndActiveState(xyz, op);
2099 template<
typename ChildT>
2100 template<
typename ModifyOp,
typename AccessorT>
2103 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
2105 ChildT* child =
nullptr;
2106 const Coord key = this->coordToKey(xyz);
2107 MapIter iter = this->findKey(key);
2108 if (iter == mTable.end()) {
2109 child =
new ChildT(xyz, mBackground);
2110 mTable.emplace(key, *child);
2111 }
else if (isChild(iter)) {
2112 child = &getChild(iter);
2114 const Tile& tile = getTile(iter);
2115 bool modifiedState = tile.active;
2117 op(modifiedVal, modifiedState);
2121 child =
new ChildT(xyz, tile.value, tile.active);
2122 setChild(iter, *child);
2126 acc.insert(xyz, child);
2127 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
2132 template<
typename ChildT>
2136 MapCIter iter = this->findCoord(xyz);
2137 if (iter == mTable.end()) {
2138 value = mBackground;
2140 }
else if (isChild(iter)) {
2141 return getChild(iter).probeValue(xyz, value);
2143 value = getTile(iter).value;
2144 return isTileOn(iter);
2147 template<
typename ChildT>
2148 template<
typename AccessorT>
2152 MapCIter iter = this->findCoord(xyz);
2153 if (iter == mTable.end()) {
2154 value = mBackground;
2156 }
else if (isChild(iter)) {
2157 acc.insert(xyz, &getChild(iter));
2158 return getChild(iter).probeValueAndCache(xyz, value, acc);
2160 value = getTile(iter).value;
2161 return isTileOn(iter);
2168 template<
typename ChildT>
2172 if (bbox.empty())
return;
2177 for (
int x = bbox.min().x();
x <= bbox.max().x();
x = tileMax.x() + 1) {
2179 for (
int y = bbox.min().y();
y <= bbox.max().y();
y = tileMax.y() + 1) {
2181 for (
int z = bbox.min().z();
z <= bbox.max().z();
z = tileMax.z() + 1) {
2185 Coord tileMin = coordToKey(xyz);
2186 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2188 if (xyz != tileMin || Coord::lessThan(bbox.max(), tileMax)) {
2192 ChildT* child =
nullptr;
2193 MapIter iter = this->findKey(tileMin);
2194 if (iter == mTable.end()) {
2197 child =
new ChildT(xyz, mBackground);
2198 mTable.emplace(tileMin, *child);
2199 }
else if (isTile(iter)) {
2202 const Tile& tile = getTile(iter);
2203 child =
new ChildT(xyz, tile.value, tile.active);
2204 setChild(iter, *child);
2205 }
else if (isChild(iter)) {
2206 child = &getChild(iter);
2211 child->fill(
CoordBBox(xyz, tmp), value, active);
2217 MapIter iter = this->findOrAddCoord(tileMin);
2218 setTile(iter, Tile(value, active));
2226 template<
typename ChildT>
2230 if (bbox.empty())
return;
2232 if (active && mTable.empty()) {
2235 sparseFill(bbox, value, active);
2236 voxelizeActiveTiles(
true);
2242 Coord xyz, tileMin, tileMax;
2243 for (
int x = bbox.min().x();
x <= bbox.max().x();
x = tileMax.x() + 1) {
2245 for (
int y = bbox.min().y();
y <= bbox.max().y();
y = tileMax.y() + 1) {
2247 for (
int z = bbox.min().z();
z <= bbox.max().z();
z = tileMax.z() + 1) {
2251 tileMin = coordToKey(xyz);
2252 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2256 const auto iter = findOrAddCoord(tileMin);
2261 const auto& tile = getTile(iter);
2262 auto* child =
new ChildT{tileMin, tile.value, tile.active};
2263 setChild(iter, *child);
2266 getChild(iter).denseFill(bbox, value, active);
2276 template<
typename ChildT>
2284 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2285 if (this->isTileOff(i))
continue;
2286 ChildT* child = i->second.child;
2287 if (child ==
nullptr) {
2290 child =
new ChildT{i->first, this->getTile(i).value,
true};
2291 i->second.child = child;
2293 child->voxelizeActiveTiles(threaded);
2301 template<
typename ChildT>
2302 template<
typename DenseT>
2308 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2309 const Coord&
min = dense.bbox().min();
2311 for (Coord xyz = bbox.min(); xyz[0] <= bbox.max()[0]; xyz[0] = nodeBBox.max()[0] + 1) {
2312 for (xyz[1] = bbox.min()[1]; xyz[1] <= bbox.max()[1]; xyz[1] = nodeBBox.max()[1] + 1) {
2313 for (xyz[2] = bbox.min()[2]; xyz[2] <= bbox.max()[2]; xyz[2] = nodeBBox.max()[2] + 1) {
2316 nodeBBox = CoordBBox::createCube(coordToKey(xyz), ChildT::DIM);
2321 MapCIter iter = this->findKey(nodeBBox.min());
2322 if (iter != mTable.end() && isChild(iter)) {
2323 getChild(iter).copyToDense(sub, dense);
2325 const ValueType value = iter==mTable.end() ? mBackground : getTile(iter).value;
2326 sub.translate(-min);
2327 DenseValueType* a0 = dense.data() + zStride*sub.min()[2];
2328 for (
Int32 x=sub.min()[0], ex=sub.max()[0]+1;
x<ex; ++
x) {
2329 DenseValueType* a1 = a0 +
x*xStride;
2330 for (
Int32 y=sub.min()[1], ey=sub.max()[1]+1;
y<ey; ++
y) {
2331 DenseValueType* a2 = a1 +
y*yStride;
2332 for (
Int32 z=sub.min()[2], ez=sub.max()[2]+1;
z<ez; ++
z, a2 += zStride) {
2333 *a2 = DenseValueType(value);
2346 template<
typename ChildT>
2351 os.write(reinterpret_cast<const char*>(&mBackground),
sizeof(
ValueType));
2354 os.write(reinterpret_cast<const char*>(&truncatedVal),
sizeof(
ValueType));
2358 const Index numTiles = this->tileCount(), numChildren = this->childCount();
2359 os.write(reinterpret_cast<const char*>(&numTiles),
sizeof(
Index));
2360 os.write(reinterpret_cast<const char*>(&numChildren),
sizeof(
Index));
2362 if (numTiles == 0 && numChildren == 0)
return false;
2365 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2366 if (isChild(i))
continue;
2367 os.write(reinterpret_cast<const char*>(i->first.asPointer()), 3 *
sizeof(
Int32));
2368 os.write(reinterpret_cast<const char*>(&getTile(i).value),
sizeof(
ValueType));
2369 os.write(reinterpret_cast<const char*>(&getTile(i).
active),
sizeof(
bool));
2372 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2373 if (isTile(i))
continue;
2374 os.write(reinterpret_cast<const char*>(i->first.asPointer()), 3 *
sizeof(
Int32));
2375 getChild(i).writeTopology(os, toHalf);
2382 template<
typename ChildT>
2393 is.read(reinterpret_cast<char*>(&mBackground),
sizeof(
ValueType));
2396 Index numTiles = 0, numChildren = 0;
2397 is.read(reinterpret_cast<char*>(&numTiles),
sizeof(
Index));
2398 is.read(reinterpret_cast<char*>(&numChildren),
sizeof(
Index));
2400 if (numTiles == 0 && numChildren == 0)
return false;
2407 for (
Index n = 0; n < numTiles; ++
n) {
2408 is.read(reinterpret_cast<char*>(vec), 3 *
sizeof(
Int32));
2409 is.read(reinterpret_cast<char*>(&value),
sizeof(
ValueType));
2410 is.read(reinterpret_cast<char*>(&active),
sizeof(
bool));
2411 mTable.emplace(Coord(vec), Tile(value, active));
2415 for (
Index n = 0; n < numChildren; ++
n) {
2416 is.read(reinterpret_cast<char*>(vec), 3 *
sizeof(
Int32));
2418 ChildT* child =
new ChildT(
PartialCreate(), origin, mBackground);
2419 child->readTopology(is, fromHalf);
2420 mTable.emplace(Coord(vec), *child);
2427 template<
typename ChildT>
2431 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2432 if (isChild(i)) getChild(i).writeBuffers(os, toHalf);
2437 template<
typename ChildT>
2441 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2442 if (isChild(i)) getChild(i).readBuffers(is, fromHalf);
2447 template<
typename ChildT>
2451 const Tile bgTile(mBackground,
false);
2453 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2459 ChildT& child = getChild(i);
2460 child.readBuffers(is, clipBBox, fromHalf);
2464 this->
clip(clipBBox);
2471 template<
typename ChildT>
2475 const Tile bgTile(mBackground,
false);
2479 MapType copyOfTable(mTable);
2480 for (MapIter i = copyOfTable.begin(), e = copyOfTable.end(); i != e; ++i) {
2481 const Coord& xyz = i->first;
2482 CoordBBox tileBBox(xyz, xyz.offsetBy(ChildT::DIM - 1));
2483 if (!clipBBox.hasOverlap(tileBBox)) {
2485 setTile(this->findCoord(xyz), bgTile);
2487 }
else if (!clipBBox.isInside(tileBBox)) {
2491 getChild(i).clip(clipBBox, mBackground);
2495 tileBBox.intersect(clipBBox);
2496 const Tile& origTile = getTile(i);
2497 setTile(this->findCoord(xyz), bgTile);
2498 this->sparseFill(tileBBox, origTile.value, origTile.active);
2511 template<
typename ChildT>
2517 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2518 if (this->isTile(i))
continue;
2519 this->getChild(i).prune(tolerance);
2520 if (this->getChild(i).isConstant(value, state, tolerance)) {
2521 this->setTile(i, Tile(value, state));
2524 this->eraseBackgroundTiles();
2531 template<
typename ChildT>
2532 template<
typename NodeT>
2537 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2539 MapIter iter = this->findCoord(xyz);
2540 if (iter == mTable.end() || isTile(iter))
return nullptr;
2542 ?
reinterpret_cast<NodeT*
>(&stealChild(iter, Tile(value, state)))
2543 : getChild(iter).template stealNode<NodeT>(xyz,
value,
state);
2551 template<
typename ChildT>
2555 if (leaf ==
nullptr)
return;
2556 ChildT* child =
nullptr;
2557 const Coord& xyz = leaf->origin();
2558 const Coord key = this->coordToKey(xyz);
2559 MapIter iter = this->findKey(key);
2560 if (iter == mTable.end()) {
2561 if (ChildT::LEVEL>0) {
2562 child =
new ChildT(xyz, mBackground,
false);
2564 child =
reinterpret_cast<ChildT*
>(leaf);
2566 mTable.emplace(key, *child);
2567 }
else if (isChild(iter)) {
2568 if (ChildT::LEVEL>0) {
2569 child = &getChild(iter);
2571 child =
reinterpret_cast<ChildT*
>(leaf);
2572 setChild(iter, *child);
2575 if (ChildT::LEVEL>0) {
2576 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2578 child =
reinterpret_cast<ChildT*
>(leaf);
2580 setChild(iter, *child);
2582 child->addLeaf(leaf);
2586 template<
typename ChildT>
2587 template<
typename AccessorT>
2591 if (leaf ==
nullptr)
return;
2592 ChildT* child =
nullptr;
2593 const Coord& xyz = leaf->origin();
2594 const Coord key = this->coordToKey(xyz);
2595 MapIter iter = this->findKey(key);
2596 if (iter == mTable.end()) {
2597 if (ChildT::LEVEL>0) {
2598 child =
new ChildT(xyz, mBackground,
false);
2600 child =
reinterpret_cast<ChildT*
>(leaf);
2602 mTable.emplace(key, *child);
2603 }
else if (isChild(iter)) {
2604 if (ChildT::LEVEL>0) {
2605 child = &getChild(iter);
2607 child =
reinterpret_cast<ChildT*
>(leaf);
2608 setChild(iter, *child);
2611 if (ChildT::LEVEL>0) {
2612 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2614 child =
reinterpret_cast<ChildT*
>(leaf);
2616 setChild(iter, *child);
2618 acc.insert(xyz, child);
2619 child->addLeafAndCache(leaf, acc);
2622 template<
typename ChildT>
2626 if (!child)
return false;
2627 const Coord& xyz = child->origin();
2628 const Coord key = this->coordToKey(xyz);
2629 MapIter iter = this->findKey(key);
2630 if (iter == mTable.end()) {
2631 mTable.emplace(key, *child);
2633 setChild(iter, *child);
2638 template<
typename ChildT>
2642 if (origin != Coord(0,0,0)) {
2643 OPENVDB_THROW(ValueError,
"RootNode::setOrigin: non-zero offsets are currently not supported");
2648 template<
typename ChildT>
2652 const Coord key = this->coordToKey(xyz);
2653 MapIter iter = this->findKey(key);
2654 if (iter == mTable.end()) {
2655 mTable.emplace(key, Tile(value, state));
2657 setTile(iter, Tile(value, state));
2661 template<
typename ChildT>
2666 if (LEVEL >= level) {
2667 const Coord key = this->coordToKey(xyz);
2668 MapIter iter = this->findKey(key);
2669 if (iter == mTable.end()) {
2670 if (LEVEL > level) {
2671 ChildT* child =
new ChildT(xyz, mBackground,
false);
2672 mTable.emplace(key, *child);
2673 child->addTile(level, xyz, value, state);
2675 mTable.emplace(key, Tile(value, state));
2677 }
else if (isChild(iter)) {
2678 if (LEVEL > level) {
2679 getChild(iter).addTile(level, xyz, value, state);
2681 setTile(iter, Tile(value, state));
2684 if (LEVEL > level) {
2685 ChildT* child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2686 setChild(iter, *child);
2687 child->addTile(level, xyz, value, state);
2689 setTile(iter, Tile(value, state));
2696 template<
typename ChildT>
2697 template<
typename AccessorT>
2700 bool state, AccessorT& acc)
2702 if (LEVEL >= level) {
2703 const Coord key = this->coordToKey(xyz);
2704 MapIter iter = this->findKey(key);
2705 if (iter == mTable.end()) {
2706 if (LEVEL > level) {
2707 ChildT* child =
new ChildT(xyz, mBackground,
false);
2708 acc.insert(xyz, child);
2709 mTable.emplace(key, *child);
2710 child->addTileAndCache(level, xyz, value, state, acc);
2712 mTable.emplace(key, Tile(value, state));
2714 }
else if (isChild(iter)) {
2715 if (LEVEL > level) {
2716 ChildT* child = &getChild(iter);
2717 acc.insert(xyz, child);
2718 child->addTileAndCache(level, xyz, value, state, acc);
2720 setTile(iter, Tile(value, state));
2723 if (LEVEL > level) {
2724 ChildT* child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2725 acc.insert(xyz, child);
2726 setChild(iter, *child);
2727 child->addTileAndCache(level, xyz, value, state, acc);
2729 setTile(iter, Tile(value, state));
2736 template<
typename ChildT>
2740 Coord key = this->coordToKey(xyz);
2741 MapIter iter = this->findKey(key);
2742 if (iter != mTable.end()) {
2744 if (isChild(iter))
delete iter->second.child;
2755 template<
typename ChildT>
2756 inline typename ChildT::LeafNodeType*
2759 ChildT* child =
nullptr;
2760 const Coord key = this->coordToKey(xyz);
2761 MapIter iter = this->findKey(key);
2762 if (iter == mTable.end()) {
2763 child =
new ChildT(xyz, mBackground,
false);
2764 mTable.emplace(key, *child);
2765 }
else if (isChild(iter)) {
2766 child = &getChild(iter);
2768 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2769 setChild(iter, *child);
2771 return child->touchLeaf(xyz);
2775 template<
typename ChildT>
2776 template<
typename AccessorT>
2777 inline typename ChildT::LeafNodeType*
2780 ChildT* child =
nullptr;
2781 const Coord key = this->coordToKey(xyz);
2782 MapIter iter = this->findKey(key);
2783 if (iter == mTable.end()) {
2784 child =
new ChildT(xyz, mBackground,
false);
2785 mTable.emplace(key, *child);
2786 }
else if (isChild(iter)) {
2787 child = &getChild(iter);
2789 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2790 setChild(iter, *child);
2792 acc.insert(xyz, child);
2793 return child->touchLeafAndCache(xyz, acc);
2800 template<
typename ChildT>
2801 template<
typename NodeT>
2806 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2808 MapIter iter = this->findCoord(xyz);
2809 if (iter == mTable.end() || isTile(iter))
return nullptr;
2810 ChildT* child = &getChild(iter);
2812 ?
reinterpret_cast<NodeT*
>(child)
2813 : child->template probeNode<NodeT>(xyz);
2818 template<
typename ChildT>
2819 template<
typename NodeT>
2823 return this->
template probeConstNode<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>
2849 MapIter iter = this->findCoord(xyz);
2850 if (iter == mTable.end()) {
2853 }
else if (isChild(iter)) {
2854 child = &getChild(iter);
2857 const Tile& tile = getTile(iter);
2860 active = tile.active;
2865 template<
typename ChildT>
2869 MapCIter iter = this->findCoord(xyz);
2870 if (iter == mTable.end()) {
2873 }
else if (isChild(iter)) {
2874 child = &getChild(iter);
2877 const Tile& tile = getTile(iter);
2880 active = tile.active;
2885 template<
typename ChildT>
2889 return this->
template probeNode<ChildT>(xyz);
2893 template<
typename ChildT>
2894 inline const ChildT*
2897 return this->
template probeConstNode<ChildT>(xyz);
2901 template<
typename ChildT>
2902 inline typename ChildT::LeafNodeType*
2905 return this->
template probeNode<LeafNodeType>(xyz);
2909 template<
typename ChildT>
2910 inline const typename ChildT::LeafNodeType*
2913 return this->
template probeConstNode<LeafNodeType>(xyz);
2917 template<
typename ChildT>
2918 template<
typename AccessorT>
2919 inline typename ChildT::LeafNodeType*
2922 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
2926 template<
typename ChildT>
2927 template<
typename AccessorT>
2928 inline const typename ChildT::LeafNodeType*
2931 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
2935 template<
typename ChildT>
2936 template<
typename AccessorT>
2937 inline const typename ChildT::LeafNodeType*
2940 return this->probeConstLeafAndCache(xyz, acc);
2944 template<
typename ChildT>
2945 template<
typename NodeT,
typename AccessorT>
2950 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2952 MapIter iter = this->findCoord(xyz);
2953 if (iter == mTable.end() || isTile(iter))
return nullptr;
2954 ChildT* child = &getChild(iter);
2955 acc.insert(xyz, child);
2957 ?
reinterpret_cast<NodeT*
>(child)
2958 : child->template probeNodeAndCache<NodeT>(xyz, acc);
2963 template<
typename ChildT>
2964 template<
typename NodeT,
typename AccessorT>
2969 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2971 MapCIter iter = this->findCoord(xyz);
2972 if (iter == mTable.end() || isTile(iter))
return nullptr;
2973 const ChildT* child = &getChild(iter);
2974 acc.insert(xyz, child);
2976 ?
reinterpret_cast<const NodeT*
>(child)
2977 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
2985 template<
typename ChildT>
2989 MapCIter iter = this->findCoord(xyz);
2992 return getTile(iter).value;
2996 template<
typename ChildT>
3000 MapCIter iter = this->findCoord(xyz);
3003 const Tile& tile = getTile(iter);
3009 template<
typename ChildT>
3013 MapIter iter = this->findCoord(xyz);
3016 return &getChild(iter);
3020 template<
typename ChildT>
3021 inline const ChildT*
3024 MapCIter iter = this->findCoord(xyz);
3027 return &getChild(iter);
3031 template<
typename ChildT>
3032 inline const ChildT*
3035 return this->getConstChildUnsafe(xyz);
3042 template<
typename ChildT>
3043 template<
typename ArrayT>
3049 "argument to getNodes() must be a pointer array");
3052 static_assert(NodeChainType::template Contains<NonConstNodeType>,
3053 "can't extract non-const nodes from a const tree");
3054 using ArrayChildT =
typename std::conditional<
3057 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
3058 if (ChildT* child = iter->second.child) {
3061 array.push_back(reinterpret_cast<NodePtr>(iter->second.child));
3063 child->getNodes(array);
3070 template<
typename ChildT>
3071 template<
typename ArrayT>
3077 "argument to getNodes() must be a pointer array");
3080 "argument to getNodes() must be an array of const node pointers");
3082 static_assert(NodeChainType::template Contains<NonConstNodeType>,
3083 "can't extract non-const nodes from a const tree");
3085 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
3089 array.push_back(reinterpret_cast<NodePtr>(iter->second.child));
3091 child->getNodes(array);
3100 template<
typename ChildT>
3101 template<
typename ArrayT>
3107 "argument to stealNodes() must be a pointer array");
3110 static_assert(NodeChainType::template Contains<NonConstNodeType>,
3111 "can't extract non-const nodes from a const tree");
3112 using ArrayChildT =
typename std::conditional<
3115 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
3116 if (ChildT* child = iter->second.child) {
3119 array.push_back(reinterpret_cast<NodePtr>(&stealChild(iter, Tile(value, state))));
3121 child->stealNodes(array, value, state);
3132 template<
typename ChildT>
3133 template<MergePolicy Policy>
3143 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3144 MapIter
j = mTable.find(i->first);
3145 if (other.isChild(i)) {
3146 if (j == mTable.end()) {
3147 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3148 child.resetBackground(other.mBackground, mBackground);
3149 mTable.emplace(i->first, child);
3150 }
else if (isTile(j)) {
3152 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3153 child.resetBackground(other.mBackground, mBackground);
3157 getChild(j).template merge<MERGE_ACTIVE_STATES>(getChild(i),
3158 other.mBackground, mBackground);
3160 }
else if (other.isTileOn(i)) {
3161 if (j == mTable.end()) {
3162 mTable.emplace(i->first, i->second);
3163 }
else if (!isTileOn(j)) {
3165 setTile(j, Tile(other.getTile(i).value,
true));
3172 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3173 MapIter
j = mTable.find(i->first);
3174 if (other.isChild(i)) {
3175 if (j == mTable.end()) {
3176 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3177 child.resetBackground(other.mBackground, mBackground);
3178 mTable.emplace(i->first, child);
3179 }
else if (isTile(j)) {
3180 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3181 child.resetBackground(other.mBackground, mBackground);
3184 getChild(j).template merge<MERGE_NODES>(
3185 getChild(i), other.mBackground, mBackground);
3192 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3193 MapIter
j = mTable.find(i->first);
3194 if (other.isChild(i)) {
3195 if (j == mTable.end()) {
3197 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3198 child.resetBackground(other.mBackground, mBackground);
3199 mTable.emplace(i->first, child);
3200 }
else if (isTile(j)) {
3202 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3203 child.resetBackground(other.mBackground, mBackground);
3204 const Tile tile = getTile(j);
3208 child.template merge<MERGE_ACTIVE_STATES_AND_NODES>(
3209 tile.value, tile.active);
3213 getChild(j).template merge<MERGE_ACTIVE_STATES_AND_NODES>(getChild(i),
3214 other.mBackground, mBackground);
3216 }
else if (other.isTileOn(i)) {
3217 if (j == mTable.end()) {
3219 mTable.emplace(i->first, i->second);
3220 }
else if (isTileOff(j)) {
3222 setTile(j, Tile(other.getTile(i).value,
true));
3223 }
else if (isChild(j)) {
3225 const Tile& tile = getTile(i);
3226 getChild(j).template merge<MERGE_ACTIVE_STATES_AND_NODES>(
3227 tile.value, tile.active);
3244 template<
typename ChildT>
3245 template<
typename OtherChildType>
3250 using OtherCIterT =
typename OtherRootT::MapCIter;
3252 enforceSameConfiguration(other);
3254 for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3255 MapIter
j = mTable.find(i->first);
3256 if (other.isChild(i)) {
3257 if (j == mTable.end()) {
3258 mTable.emplace(i->first,
3259 *(
new ChildT(other.getChild(i), mBackground,
TopologyCopy())));
3260 }
else if (this->isChild(j)) {
3261 this->getChild(j).topologyUnion(other.getChild(i), preserveTiles);
3263 if (!preserveTiles || this->isTileOff(j)) {
3264 ChildT* child =
new ChildT(
3265 other.getChild(i), this->getTile(j).value,
TopologyCopy());
3266 if (this->isTileOn(j)) child->setValuesOn();
3267 this->setChild(j, *child);
3270 }
else if (other.isTileOn(i)) {
3271 if (j == mTable.end()) {
3272 mTable.emplace(i->first, Tile(mBackground,
true));
3273 }
else if (this->isChild(j)) {
3274 this->getChild(j).setValuesOn();
3275 }
else if (this->isTileOff(j)) {
3276 this->setTile(j, Tile(this->getTile(j).value,
true));
3282 template<
typename ChildT>
3283 template<
typename OtherChildType>
3288 using OtherCIterT =
typename OtherRootT::MapCIter;
3290 enforceSameConfiguration(other);
3292 std::set<Coord> tmp;
3293 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
3294 OtherCIterT
j = other.mTable.find(i->first);
3295 if (this->isChild(i)) {
3296 if (j == other.mTable.end() || other.isTileOff(j)) {
3297 tmp.insert(i->first);
3298 }
else if (other.isChild(j)) {
3299 this->getChild(i).topologyIntersection(other.getChild(j), mBackground);
3301 }
else if (this->isTileOn(i)) {
3302 if (j == other.mTable.end() || other.isTileOff(j)) {
3303 this->setTile(i, Tile(this->getTile(i).value,
false));
3304 }
else if (other.isChild(j)) {
3306 new ChildT(other.getChild(j), this->getTile(i).value,
TopologyCopy());
3307 this->setChild(i, *child);
3311 for (std::set<Coord>::iterator i = tmp.begin(), e = tmp.end(); i != e; ++i) {
3312 MapIter it = this->findCoord(*i);
3313 setTile(it, Tile());
3318 template<
typename ChildT>
3319 template<
typename OtherChildType>
3324 using OtherCIterT =
typename OtherRootT::MapCIter;
3326 enforceSameConfiguration(other);
3328 for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3329 MapIter
j = mTable.find(i->first);
3330 if (other.isChild(i)) {
3331 if (j == mTable.end() || this->isTileOff(j)) {
3333 }
else if (this->isChild(j)) {
3334 this->getChild(j).topologyDifference(other.getChild(i), mBackground);
3335 }
else if (this->isTileOn(j)) {
3337 ChildT* child =
new ChildT(j->first,
this->getTile(j).value,
true);
3338 child->topologyDifference(other.getChild(i), mBackground);
3339 this->setChild(j, *child);
3341 }
else if (other.isTileOn(i)) {
3342 if (j == mTable.end() || this->isTileOff(j)) {
3344 }
else if (this->isChild(j)) {
3347 }
else if (this->isTileOn(j)) {
3348 this->setTile(j, Tile(this->getTile(j).value,
false));
3357 template<
typename ChildT>
3358 template<
typename CombineOp>
3365 this->insertKeys(keys);
3366 other.insertKeys(keys);
3368 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3369 MapIter iter = findOrAddCoord(*i), otherIter = other.findOrAddCoord(*i);
3370 if (isTile(iter) && isTile(otherIter)) {
3374 .setAIsActive(isTileOn(iter))
3375 .setBRef(getTile(otherIter).value)
3376 .setBIsActive(isTileOn(otherIter)));
3379 }
else if (isChild(iter) && isTile(otherIter)) {
3381 ChildT& child = getChild(iter);
3382 child.combine(getTile(otherIter).value, isTileOn(otherIter), op);
3384 }
else if (isTile(iter) && isChild(otherIter)) {
3389 ChildT& child = getChild(otherIter);
3390 child.combine(getTile(iter).value, isTileOn(iter), swappedOp);
3393 setChild(iter, stealChild(otherIter, Tile()));
3397 ChildT &child = getChild(iter), &otherChild = getChild(otherIter);
3398 child.combine(otherChild, op);
3400 if (prune && isChild(iter)) getChild(iter).prune();
3404 op(args.
setARef(mBackground).setBRef(other.mBackground));
3405 mBackground = args.
result();
3417 template<
typename CombineOp,
typename RootT,
typename OtherRootT,
bool Compatible = false>
3420 static inline void combine2(RootT&
self,
const RootT&,
const OtherRootT& other1,
3425 self.enforceSameConfiguration(other1);
3426 self.enforceCompatibleValueTypes(other1);
3428 std::ostringstream ostr;
3429 ostr <<
"cannot combine a " <<
typeid(OtherRootT).
name()
3430 <<
" into a " <<
typeid(RootT).
name();
3436 template<
typename CombineOp,
typename RootT,
typename OtherRootT>
3439 static inline void combine2(RootT&
self,
const RootT& other0,
const OtherRootT& other1,
3440 CombineOp& op,
bool prune)
3442 self.doCombine2(other0, other1, op, prune);
3447 template<
typename ChildT>
3448 template<
typename CombineOp,
typename OtherRootNode>
3451 CombineOp& op,
bool prune)
3457 *
this, other0, other1, op, prune);
3461 template<
typename ChildT>
3462 template<
typename CombineOp,
typename OtherRootNode>
3465 CombineOp& op,
bool prune)
3467 enforceSameConfiguration(other1);
3470 using OtherTileT =
typename OtherRootNode::Tile;
3471 using OtherNodeStructT =
typename OtherRootNode::NodeStruct;
3472 using OtherMapCIterT =
typename OtherRootNode::MapCIter;
3477 other0.insertKeys(keys);
3478 other1.insertKeys(keys);
3480 const NodeStruct bg0(Tile(other0.mBackground,
false));
3481 const OtherNodeStructT bg1(OtherTileT(other1.mBackground,
false));
3483 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3484 MapIter thisIter = this->findOrAddCoord(*i);
3485 MapCIter iter0 = other0.findKey(*i);
3486 OtherMapCIterT iter1 = other1.findKey(*i);
3487 const NodeStruct& ns0 = (iter0 != other0.mTable.end()) ? iter0->second : bg0;
3488 const OtherNodeStructT& ns1 = (iter1 != other1.mTable.end()) ? iter1->second : bg1;
3489 if (ns0.isTile() && ns1.isTile()) {
3493 .setAIsActive(ns0.isTileOn())
3494 .setBRef(ns1.tile.value)
3495 .setBIsActive(ns1.isTileOn()));
3498 if (!isChild(thisIter)) {
3500 const Coord& childOrigin =
3501 ns0.isChild() ? ns0.child->origin() : ns1.child->origin();
3502 setChild(thisIter, *(
new ChildT(childOrigin, getTile(thisIter).value)));
3504 ChildT& child = getChild(thisIter);
3509 child.combine2(ns0.tile.value, *ns1.child, ns0.isTileOn(),
op);
3510 }
else if (ns1.isTile()) {
3513 child.combine2(*ns0.child, ns1.tile.value, ns1.isTileOn(),
op);
3517 child.combine2(*ns0.child, *ns1.child, op);
3520 if (prune && isChild(thisIter)) getChild(thisIter).prune();
3524 op(args.
setARef(other0.mBackground).setBRef(other1.mBackground));
3525 mBackground = args.
result();
3533 #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;)
Index32 inactiveTileCount() const
ValueOffCIter beginValueOff() const
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
bool addChild(ChildType *child)
Add the given child node at the root level. If a child node with the same origin already exists...
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.
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Coord coordToKey(const Coord &xyz) const
Return a MapType key for the given coordinates, offset by the mOrigin.
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
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
const ValueType & background() const
Return this node's background value.
const ValueType & getTileValueUnsafe(const Coord &xyz) const
Return the tile value at the given coordinate.
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
Return a pointer to the root child node that contains voxel (x, y, z). If no such node exists...
Index32 transientData() const
Return the transient data value.
**But if you need a result
__hostdev__ void setValue(uint32_t offset, bool v)
Index32 tileCount() const
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
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of a RootNode ...
OPENVDB_API void checkFormatVersion(std::ios_base &)
Throws an IoError if the file format version number is not supported.
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)
void setTransientData(Index32 transientData)
Set the transient data value.
#define OPENVDB_ASSERT(X)
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.
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.
Index64 nonLeafCount() const
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.
void nodeCount(std::vector< Index64 > &vec) const
Index64 onVoxelCount() const
constexpr auto set(type rhs) -> int
ChildNodeType * probeChild(const Coord &xyz)
Return a pointer to the root child node that contains voxel (x, y, z). If no such node exists...
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)
const ChildNodeType * getConstChildUnsafe(const Coord &xyz) const
Return the child node at the given coordinate.
bool deleteChildOrTile(const Coord &xyz)
Delete any child or tile containing voxel (x, y, z) at the root level. Do nothing if no child or tile...
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
bool hasKey(const Coord &key) const
Return true if this node's mTable contains the given key.
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.
LeafFnBase< CoordT, MaskT, LOG2DIM > BaseT
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
that also have some descendant prim *whose name begins with which in turn has a child named baz where *the predicate active
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
Index64 leafCount() 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.
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
ChildOffCIter beginChildOff() const
bool probe(const Coord &xyz, ChildNodeType *&child, ValueType &value, bool &active)
Return a pointer to the root child node that contains voxel (x, y, z). If no such node exists...
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
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.
bool probeConst(const Coord &xyz, const ChildNodeType *&child, ValueType &value, bool &active) const
Return a pointer to the root child node that contains voxel (x, y, z). If no such node exists...
ChildNodeType * getChildUnsafe(const Coord &xyz)
Return the child node at the given coordinate.
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)
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
const ChildNodeType * probeConstChild(const Coord &xyz) const
Return a pointer to the root child node that contains voxel (x, y, z). If no such node exists...
bool probe(const Coord &xyz, const ChildNodeType *&child, ValueType &value, bool &active) const
Return a pointer to the root child node that contains voxel (x, y, z). If no such node exists...
const ChildNodeType * probeChild(const Coord &xyz) const
Return a pointer to the root child node that contains voxel (x, y, z). If no such node exists...
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.
Index32 activeTileCount() const
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.
ValueIter< RootNode, MapIter, ValueOffPred, ValueType > ValueOffIter
void setOrigin(const Coord &origin)
change the origin on this root node
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)
const LeafNodeType * probeLeaf(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 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.