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>
2394 is.read(reinterpret_cast<char*>(&mBackground),
sizeof(
ValueType));
2396 is.read(reinterpret_cast<char*>(&inside),
sizeof(
ValueType));
2401 Coord rangeMin, rangeMax;
2402 is.read(reinterpret_cast<char*>(rangeMin.asPointer()), 3 *
sizeof(
Int32));
2403 is.read(reinterpret_cast<char*>(rangeMax.asPointer()), 3 *
sizeof(
Int32));
2405 Index tableSize = 0, log2Dim[4] = { 0, 0, 0, 0 };
2407 for (
int i = 0; i < 3; ++i) {
2408 offset[i] = rangeMin[i] >> ChildT::TOTAL;
2409 rangeMin[i] = offset[i] << ChildT::TOTAL;
2411 tableSize += log2Dim[i];
2412 rangeMax[i] = (((1 << log2Dim[i]) + offset[i]) << ChildT::TOTAL) - 1;
2414 log2Dim[3] = log2Dim[1] + log2Dim[2];
2415 tableSize = 1U << tableSize;
2423 for (
Index i = 0; i < tableSize; ++i) {
2427 origin[0] = (n >> log2Dim[3]) + offset[0];
2428 n &= (1U << log2Dim[3]) - 1;
2429 origin[1] = (n >> log2Dim[2]) + offset[1];
2430 origin[2] = (n & ((1U << log2Dim[2]) - 1)) + offset[1];
2431 origin <<= ChildT::TOTAL;
2433 if (childMask.isOn(i)) {
2435 ChildT* child =
new ChildT(
PartialCreate(), origin, mBackground);
2436 child->readTopology(is);
2437 mTable.emplace(origin, *child);
2442 is.read(reinterpret_cast<char*>(&value),
sizeof(
ValueType));
2444 mTable.emplace(origin, Tile(value, valueMask.
isOn(i)));
2453 is.read(reinterpret_cast<char*>(&mBackground),
sizeof(
ValueType));
2456 Index numTiles = 0, numChildren = 0;
2457 is.read(reinterpret_cast<char*>(&numTiles),
sizeof(
Index));
2458 is.read(reinterpret_cast<char*>(&numChildren),
sizeof(
Index));
2460 if (numTiles == 0 && numChildren == 0)
return false;
2467 for (
Index n = 0; n < numTiles; ++
n) {
2468 is.read(reinterpret_cast<char*>(vec), 3 *
sizeof(
Int32));
2469 is.read(reinterpret_cast<char*>(&value),
sizeof(
ValueType));
2470 is.read(reinterpret_cast<char*>(&active),
sizeof(
bool));
2471 mTable.emplace(Coord(vec), Tile(value, active));
2475 for (
Index n = 0; n < numChildren; ++
n) {
2476 is.read(reinterpret_cast<char*>(vec), 3 *
sizeof(
Int32));
2478 ChildT* child =
new ChildT(
PartialCreate(), origin, mBackground);
2479 child->readTopology(is, fromHalf);
2480 mTable.emplace(Coord(vec), *child);
2487 template<
typename ChildT>
2491 for (MapCIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2492 if (isChild(i)) getChild(i).writeBuffers(os, toHalf);
2497 template<
typename ChildT>
2501 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2502 if (isChild(i)) getChild(i).readBuffers(is, fromHalf);
2507 template<
typename ChildT>
2511 const Tile bgTile(mBackground,
false);
2513 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2519 ChildT& child = getChild(i);
2520 child.readBuffers(is, clipBBox, fromHalf);
2524 this->
clip(clipBBox);
2531 template<
typename ChildT>
2535 const Tile bgTile(mBackground,
false);
2539 MapType copyOfTable(mTable);
2540 for (MapIter i = copyOfTable.begin(), e = copyOfTable.end(); i != e; ++i) {
2541 const Coord& xyz = i->first;
2542 CoordBBox tileBBox(xyz, xyz.offsetBy(ChildT::DIM - 1));
2543 if (!clipBBox.hasOverlap(tileBBox)) {
2545 setTile(this->findCoord(xyz), bgTile);
2547 }
else if (!clipBBox.isInside(tileBBox)) {
2551 getChild(i).clip(clipBBox, mBackground);
2555 tileBBox.intersect(clipBBox);
2556 const Tile& origTile = getTile(i);
2557 setTile(this->findCoord(xyz), bgTile);
2558 this->sparseFill(tileBBox, origTile.value, origTile.active);
2571 template<
typename ChildT>
2577 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
2578 if (this->isTile(i))
continue;
2579 this->getChild(i).prune(tolerance);
2580 if (this->getChild(i).isConstant(value, state, tolerance)) {
2581 this->setTile(i, Tile(value, state));
2584 this->eraseBackgroundTiles();
2591 template<
typename ChildT>
2592 template<
typename NodeT>
2597 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2599 MapIter iter = this->findCoord(xyz);
2600 if (iter == mTable.end() || isTile(iter))
return nullptr;
2602 ?
reinterpret_cast<NodeT*
>(&stealChild(iter, Tile(value, state)))
2603 : getChild(iter).template stealNode<NodeT>(xyz,
value,
state);
2611 template<
typename ChildT>
2615 if (leaf ==
nullptr)
return;
2616 ChildT* child =
nullptr;
2617 const Coord& xyz = leaf->origin();
2618 const Coord key = this->coordToKey(xyz);
2619 MapIter iter = this->findKey(key);
2620 if (iter == mTable.end()) {
2621 if (ChildT::LEVEL>0) {
2622 child =
new ChildT(xyz, mBackground,
false);
2624 child =
reinterpret_cast<ChildT*
>(leaf);
2626 mTable.emplace(key, *child);
2627 }
else if (isChild(iter)) {
2628 if (ChildT::LEVEL>0) {
2629 child = &getChild(iter);
2631 child =
reinterpret_cast<ChildT*
>(leaf);
2632 setChild(iter, *child);
2635 if (ChildT::LEVEL>0) {
2636 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2638 child =
reinterpret_cast<ChildT*
>(leaf);
2640 setChild(iter, *child);
2642 child->addLeaf(leaf);
2646 template<
typename ChildT>
2647 template<
typename AccessorT>
2651 if (leaf ==
nullptr)
return;
2652 ChildT* child =
nullptr;
2653 const Coord& xyz = leaf->origin();
2654 const Coord key = this->coordToKey(xyz);
2655 MapIter iter = this->findKey(key);
2656 if (iter == mTable.end()) {
2657 if (ChildT::LEVEL>0) {
2658 child =
new ChildT(xyz, mBackground,
false);
2660 child =
reinterpret_cast<ChildT*
>(leaf);
2662 mTable.emplace(key, *child);
2663 }
else if (isChild(iter)) {
2664 if (ChildT::LEVEL>0) {
2665 child = &getChild(iter);
2667 child =
reinterpret_cast<ChildT*
>(leaf);
2668 setChild(iter, *child);
2671 if (ChildT::LEVEL>0) {
2672 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2674 child =
reinterpret_cast<ChildT*
>(leaf);
2676 setChild(iter, *child);
2678 acc.insert(xyz, child);
2679 child->addLeafAndCache(leaf, acc);
2682 template<
typename ChildT>
2686 if (!child)
return false;
2687 const Coord& xyz = child->origin();
2688 const Coord key = this->coordToKey(xyz);
2689 MapIter iter = this->findKey(key);
2690 if (iter == mTable.end()) {
2691 mTable.emplace(key, *child);
2693 setChild(iter, *child);
2698 template<
typename ChildT>
2702 if (origin != Coord(0,0,0)) {
2703 OPENVDB_THROW(ValueError,
"RootNode::setOrigin: non-zero offsets are currently not supported");
2708 template<
typename ChildT>
2712 const Coord key = this->coordToKey(xyz);
2713 MapIter iter = this->findKey(key);
2714 if (iter == mTable.end()) {
2715 mTable.emplace(key, Tile(value, state));
2717 setTile(iter, Tile(value, state));
2721 template<
typename ChildT>
2726 if (LEVEL >= level) {
2727 const Coord key = this->coordToKey(xyz);
2728 MapIter iter = this->findKey(key);
2729 if (iter == mTable.end()) {
2730 if (LEVEL > level) {
2731 ChildT* child =
new ChildT(xyz, mBackground,
false);
2732 mTable.emplace(key, *child);
2733 child->addTile(level, xyz, value, state);
2735 mTable.emplace(key, Tile(value, state));
2737 }
else if (isChild(iter)) {
2738 if (LEVEL > level) {
2739 getChild(iter).addTile(level, xyz, value, state);
2741 setTile(iter, Tile(value, state));
2744 if (LEVEL > level) {
2745 ChildT* child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2746 setChild(iter, *child);
2747 child->addTile(level, xyz, value, state);
2749 setTile(iter, Tile(value, state));
2756 template<
typename ChildT>
2757 template<
typename AccessorT>
2760 bool state, AccessorT& acc)
2762 if (LEVEL >= level) {
2763 const Coord key = this->coordToKey(xyz);
2764 MapIter iter = this->findKey(key);
2765 if (iter == mTable.end()) {
2766 if (LEVEL > level) {
2767 ChildT* child =
new ChildT(xyz, mBackground,
false);
2768 acc.insert(xyz, child);
2769 mTable.emplace(key, *child);
2770 child->addTileAndCache(level, xyz, value, state, acc);
2772 mTable.emplace(key, Tile(value, state));
2774 }
else if (isChild(iter)) {
2775 if (LEVEL > level) {
2776 ChildT* child = &getChild(iter);
2777 acc.insert(xyz, child);
2778 child->addTileAndCache(level, xyz, value, state, acc);
2780 setTile(iter, Tile(value, state));
2783 if (LEVEL > level) {
2784 ChildT* child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2785 acc.insert(xyz, child);
2786 setChild(iter, *child);
2787 child->addTileAndCache(level, xyz, value, state, acc);
2789 setTile(iter, Tile(value, state));
2796 template<
typename ChildT>
2800 Coord key = this->coordToKey(xyz);
2801 MapIter iter = this->findKey(key);
2802 if (iter != mTable.end()) {
2804 if (isChild(iter))
delete iter->second.child;
2815 template<
typename ChildT>
2816 inline typename ChildT::LeafNodeType*
2819 ChildT* child =
nullptr;
2820 const Coord key = this->coordToKey(xyz);
2821 MapIter iter = this->findKey(key);
2822 if (iter == mTable.end()) {
2823 child =
new ChildT(xyz, mBackground,
false);
2824 mTable.emplace(key, *child);
2825 }
else if (isChild(iter)) {
2826 child = &getChild(iter);
2828 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2829 setChild(iter, *child);
2831 return child->touchLeaf(xyz);
2835 template<
typename ChildT>
2836 template<
typename AccessorT>
2837 inline typename ChildT::LeafNodeType*
2840 ChildT* child =
nullptr;
2841 const Coord key = this->coordToKey(xyz);
2842 MapIter iter = this->findKey(key);
2843 if (iter == mTable.end()) {
2844 child =
new ChildT(xyz, mBackground,
false);
2845 mTable.emplace(key, *child);
2846 }
else if (isChild(iter)) {
2847 child = &getChild(iter);
2849 child =
new ChildT(xyz, getTile(iter).value, isTileOn(iter));
2850 setChild(iter, *child);
2852 acc.insert(xyz, child);
2853 return child->touchLeafAndCache(xyz, acc);
2860 template<
typename ChildT>
2861 template<
typename NodeT>
2866 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2868 MapIter iter = this->findCoord(xyz);
2869 if (iter == mTable.end() || isTile(iter))
return nullptr;
2870 ChildT* child = &getChild(iter);
2872 ?
reinterpret_cast<NodeT*
>(child)
2873 : child->template probeNode<NodeT>(xyz);
2878 template<
typename ChildT>
2879 template<
typename NodeT>
2883 return this->
template probeConstNode<NodeT>(xyz);
2887 template<
typename ChildT>
2888 template<
typename NodeT>
2893 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
2895 MapCIter iter = this->findCoord(xyz);
2896 if (iter == mTable.end() || isTile(iter))
return nullptr;
2897 const ChildT* child = &getChild(iter);
2899 ?
reinterpret_cast<const NodeT*
>(child)
2900 : child->template probeConstNode<NodeT>(xyz);
2905 template<
typename ChildT>
2909 MapIter iter = this->findCoord(xyz);
2910 if (iter == mTable.end()) {
2913 }
else if (isChild(iter)) {
2914 child = &getChild(iter);
2917 const Tile& tile = getTile(iter);
2920 active = tile.active;
2925 template<
typename ChildT>
2929 MapCIter iter = this->findCoord(xyz);
2930 if (iter == mTable.end()) {
2933 }
else if (isChild(iter)) {
2934 child = &getChild(iter);
2937 const Tile& tile = getTile(iter);
2940 active = tile.active;
2945 template<
typename ChildT>
2949 return this->
template probeNode<ChildT>(xyz);
2953 template<
typename ChildT>
2954 inline const ChildT*
2957 return this->
template probeConstNode<ChildT>(xyz);
2961 template<
typename ChildT>
2962 inline typename ChildT::LeafNodeType*
2965 return this->
template probeNode<LeafNodeType>(xyz);
2969 template<
typename ChildT>
2970 inline const typename ChildT::LeafNodeType*
2973 return this->
template probeConstNode<LeafNodeType>(xyz);
2977 template<
typename ChildT>
2978 template<
typename AccessorT>
2979 inline typename ChildT::LeafNodeType*
2982 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
2986 template<
typename ChildT>
2987 template<
typename AccessorT>
2988 inline const typename ChildT::LeafNodeType*
2991 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
2995 template<
typename ChildT>
2996 template<
typename AccessorT>
2997 inline const typename ChildT::LeafNodeType*
3000 return this->probeConstLeafAndCache(xyz, acc);
3004 template<
typename ChildT>
3005 template<
typename NodeT,
typename AccessorT>
3010 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
3012 MapIter iter = this->findCoord(xyz);
3013 if (iter == mTable.end() || isTile(iter))
return nullptr;
3014 ChildT* child = &getChild(iter);
3015 acc.insert(xyz, child);
3017 ?
reinterpret_cast<NodeT*
>(child)
3018 : child->template probeNodeAndCache<NodeT>(xyz, acc);
3023 template<
typename ChildT>
3024 template<
typename NodeT,
typename AccessorT>
3029 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
3031 MapCIter iter = this->findCoord(xyz);
3032 if (iter == mTable.end() || isTile(iter))
return nullptr;
3033 const ChildT* child = &getChild(iter);
3034 acc.insert(xyz, child);
3036 ?
reinterpret_cast<const NodeT*
>(child)
3037 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
3045 template<
typename ChildT>
3049 MapCIter iter = this->findCoord(xyz);
3052 return getTile(iter).value;
3056 template<
typename ChildT>
3060 MapCIter iter = this->findCoord(xyz);
3063 const Tile& tile = getTile(iter);
3069 template<
typename ChildT>
3073 MapIter iter = this->findCoord(xyz);
3076 return &getChild(iter);
3080 template<
typename ChildT>
3081 inline const ChildT*
3084 MapCIter iter = this->findCoord(xyz);
3087 return &getChild(iter);
3091 template<
typename ChildT>
3092 inline const ChildT*
3095 return this->getConstChildUnsafe(xyz);
3102 template<
typename ChildT>
3103 template<
typename ArrayT>
3109 "argument to getNodes() must be a pointer array");
3112 static_assert(NodeChainType::template Contains<NonConstNodeType>,
3113 "can't extract non-const nodes from a const tree");
3114 using ArrayChildT =
typename std::conditional<
3117 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
3118 if (ChildT* child = iter->second.child) {
3121 array.push_back(reinterpret_cast<NodePtr>(iter->second.child));
3123 child->getNodes(array);
3130 template<
typename ChildT>
3131 template<
typename ArrayT>
3137 "argument to getNodes() must be a pointer array");
3140 "argument to getNodes() must be an array of const node pointers");
3142 static_assert(NodeChainType::template Contains<NonConstNodeType>,
3143 "can't extract non-const nodes from a const tree");
3145 for (MapCIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
3149 array.push_back(reinterpret_cast<NodePtr>(iter->second.child));
3151 child->getNodes(array);
3160 template<
typename ChildT>
3161 template<
typename ArrayT>
3167 "argument to stealNodes() must be a pointer array");
3170 static_assert(NodeChainType::template Contains<NonConstNodeType>,
3171 "can't extract non-const nodes from a const tree");
3172 using ArrayChildT =
typename std::conditional<
3175 for (MapIter iter=mTable.begin(); iter!=mTable.end(); ++iter) {
3176 if (ChildT* child = iter->second.child) {
3179 array.push_back(reinterpret_cast<NodePtr>(&stealChild(iter, Tile(value, state))));
3181 child->stealNodes(array, value, state);
3192 template<
typename ChildT>
3193 template<MergePolicy Policy>
3203 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3204 MapIter
j = mTable.find(i->first);
3205 if (other.isChild(i)) {
3206 if (j == mTable.end()) {
3207 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3208 child.resetBackground(other.mBackground, mBackground);
3209 mTable.emplace(i->first, child);
3210 }
else if (isTile(j)) {
3212 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3213 child.resetBackground(other.mBackground, mBackground);
3217 getChild(j).template merge<MERGE_ACTIVE_STATES>(getChild(i),
3218 other.mBackground, mBackground);
3220 }
else if (other.isTileOn(i)) {
3221 if (j == mTable.end()) {
3222 mTable.emplace(i->first, i->second);
3223 }
else if (!isTileOn(j)) {
3225 setTile(j, Tile(other.getTile(i).value,
true));
3232 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3233 MapIter
j = mTable.find(i->first);
3234 if (other.isChild(i)) {
3235 if (j == mTable.end()) {
3236 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3237 child.resetBackground(other.mBackground, mBackground);
3238 mTable.emplace(i->first, child);
3239 }
else if (isTile(j)) {
3240 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3241 child.resetBackground(other.mBackground, mBackground);
3244 getChild(j).template merge<MERGE_NODES>(
3245 getChild(i), other.mBackground, mBackground);
3252 for (MapIter i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3253 MapIter
j = mTable.find(i->first);
3254 if (other.isChild(i)) {
3255 if (j == mTable.end()) {
3257 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3258 child.resetBackground(other.mBackground, mBackground);
3259 mTable.emplace(i->first, child);
3260 }
else if (isTile(j)) {
3262 ChildNodeType& child = stealChild(i, Tile(other.mBackground,
false));
3263 child.resetBackground(other.mBackground, mBackground);
3264 const Tile tile = getTile(j);
3268 child.template merge<MERGE_ACTIVE_STATES_AND_NODES>(
3269 tile.value, tile.active);
3273 getChild(j).template merge<MERGE_ACTIVE_STATES_AND_NODES>(getChild(i),
3274 other.mBackground, mBackground);
3276 }
else if (other.isTileOn(i)) {
3277 if (j == mTable.end()) {
3279 mTable.emplace(i->first, i->second);
3280 }
else if (isTileOff(j)) {
3282 setTile(j, Tile(other.getTile(i).value,
true));
3283 }
else if (isChild(j)) {
3285 const Tile& tile = getTile(i);
3286 getChild(j).template merge<MERGE_ACTIVE_STATES_AND_NODES>(
3287 tile.value, tile.active);
3304 template<
typename ChildT>
3305 template<
typename OtherChildType>
3310 using OtherCIterT =
typename OtherRootT::MapCIter;
3312 enforceSameConfiguration(other);
3314 for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3315 MapIter
j = mTable.find(i->first);
3316 if (other.isChild(i)) {
3317 if (j == mTable.end()) {
3318 mTable.emplace(i->first,
3319 *(
new ChildT(other.getChild(i), mBackground,
TopologyCopy())));
3320 }
else if (this->isChild(j)) {
3321 this->getChild(j).topologyUnion(other.getChild(i), preserveTiles);
3323 if (!preserveTiles || this->isTileOff(j)) {
3324 ChildT* child =
new ChildT(
3325 other.getChild(i), this->getTile(j).value,
TopologyCopy());
3326 if (this->isTileOn(j)) child->setValuesOn();
3327 this->setChild(j, *child);
3330 }
else if (other.isTileOn(i)) {
3331 if (j == mTable.end()) {
3332 mTable.emplace(i->first, Tile(mBackground,
true));
3333 }
else if (this->isChild(j)) {
3334 this->getChild(j).setValuesOn();
3335 }
else if (this->isTileOff(j)) {
3336 this->setTile(j, Tile(this->getTile(j).value,
true));
3342 template<
typename ChildT>
3343 template<
typename OtherChildType>
3348 using OtherCIterT =
typename OtherRootT::MapCIter;
3350 enforceSameConfiguration(other);
3352 std::set<Coord> tmp;
3353 for (MapIter i = mTable.begin(), e = mTable.end(); i != e; ++i) {
3354 OtherCIterT
j = other.mTable.find(i->first);
3355 if (this->isChild(i)) {
3356 if (j == other.mTable.end() || other.isTileOff(j)) {
3357 tmp.insert(i->first);
3358 }
else if (other.isChild(j)) {
3359 this->getChild(i).topologyIntersection(other.getChild(j), mBackground);
3361 }
else if (this->isTileOn(i)) {
3362 if (j == other.mTable.end() || other.isTileOff(j)) {
3363 this->setTile(i, Tile(this->getTile(i).value,
false));
3364 }
else if (other.isChild(j)) {
3366 new ChildT(other.getChild(j), this->getTile(i).value,
TopologyCopy());
3367 this->setChild(i, *child);
3371 for (std::set<Coord>::iterator i = tmp.begin(), e = tmp.end(); i != e; ++i) {
3372 MapIter it = this->findCoord(*i);
3373 setTile(it, Tile());
3378 template<
typename ChildT>
3379 template<
typename OtherChildType>
3384 using OtherCIterT =
typename OtherRootT::MapCIter;
3386 enforceSameConfiguration(other);
3388 for (OtherCIterT i = other.mTable.begin(), e = other.mTable.end(); i != e; ++i) {
3389 MapIter
j = mTable.find(i->first);
3390 if (other.isChild(i)) {
3391 if (j == mTable.end() || this->isTileOff(j)) {
3393 }
else if (this->isChild(j)) {
3394 this->getChild(j).topologyDifference(other.getChild(i), mBackground);
3395 }
else if (this->isTileOn(j)) {
3397 ChildT* child =
new ChildT(j->first,
this->getTile(j).value,
true);
3398 child->topologyDifference(other.getChild(i), mBackground);
3399 this->setChild(j, *child);
3401 }
else if (other.isTileOn(i)) {
3402 if (j == mTable.end() || this->isTileOff(j)) {
3404 }
else if (this->isChild(j)) {
3407 }
else if (this->isTileOn(j)) {
3408 this->setTile(j, Tile(this->getTile(j).value,
false));
3417 template<
typename ChildT>
3418 template<
typename CombineOp>
3425 this->insertKeys(keys);
3426 other.insertKeys(keys);
3428 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3429 MapIter iter = findOrAddCoord(*i), otherIter = other.findOrAddCoord(*i);
3430 if (isTile(iter) && isTile(otherIter)) {
3434 .setAIsActive(isTileOn(iter))
3435 .setBRef(getTile(otherIter).value)
3436 .setBIsActive(isTileOn(otherIter)));
3439 }
else if (isChild(iter) && isTile(otherIter)) {
3441 ChildT& child = getChild(iter);
3442 child.combine(getTile(otherIter).value, isTileOn(otherIter), op);
3444 }
else if (isTile(iter) && isChild(otherIter)) {
3449 ChildT& child = getChild(otherIter);
3450 child.combine(getTile(iter).value, isTileOn(iter), swappedOp);
3453 setChild(iter, stealChild(otherIter, Tile()));
3457 ChildT &child = getChild(iter), &otherChild = getChild(otherIter);
3458 child.combine(otherChild, op);
3460 if (prune && isChild(iter)) getChild(iter).prune();
3464 op(args.
setARef(mBackground).setBRef(other.mBackground));
3465 mBackground = args.
result();
3477 template<
typename CombineOp,
typename RootT,
typename OtherRootT,
bool Compatible = false>
3480 static inline void combine2(RootT&
self,
const RootT&,
const OtherRootT& other1,
3485 self.enforceSameConfiguration(other1);
3486 self.enforceCompatibleValueTypes(other1);
3488 std::ostringstream ostr;
3489 ostr <<
"cannot combine a " <<
typeid(OtherRootT).
name()
3490 <<
" into a " <<
typeid(RootT).
name();
3496 template<
typename CombineOp,
typename RootT,
typename OtherRootT>
3499 static inline void combine2(RootT&
self,
const RootT& other0,
const OtherRootT& other1,
3500 CombineOp& op,
bool prune)
3502 self.doCombine2(other0, other1, op, prune);
3507 template<
typename ChildT>
3508 template<
typename CombineOp,
typename OtherRootNode>
3511 CombineOp& op,
bool prune)
3517 *
this, other0, other1, op, prune);
3521 template<
typename ChildT>
3522 template<
typename CombineOp,
typename OtherRootNode>
3525 CombineOp& op,
bool prune)
3527 enforceSameConfiguration(other1);
3530 using OtherTileT =
typename OtherRootNode::Tile;
3531 using OtherNodeStructT =
typename OtherRootNode::NodeStruct;
3532 using OtherMapCIterT =
typename OtherRootNode::MapCIter;
3537 other0.insertKeys(keys);
3538 other1.insertKeys(keys);
3540 const NodeStruct bg0(Tile(other0.mBackground,
false));
3541 const OtherNodeStructT bg1(OtherTileT(other1.mBackground,
false));
3543 for (CoordSetCIter i = keys.begin(), e = keys.end(); i != e; ++i) {
3544 MapIter thisIter = this->findOrAddCoord(*i);
3545 MapCIter iter0 = other0.findKey(*i);
3546 OtherMapCIterT iter1 = other1.findKey(*i);
3547 const NodeStruct& ns0 = (iter0 != other0.mTable.end()) ? iter0->second : bg0;
3548 const OtherNodeStructT& ns1 = (iter1 != other1.mTable.end()) ? iter1->second : bg1;
3549 if (ns0.isTile() && ns1.isTile()) {
3553 .setAIsActive(ns0.isTileOn())
3554 .setBRef(ns1.tile.value)
3555 .setBIsActive(ns1.isTileOn()));
3558 if (!isChild(thisIter)) {
3560 const Coord& childOrigin =
3561 ns0.isChild() ? ns0.child->origin() : ns1.child->origin();
3562 setChild(thisIter, *(
new ChildT(childOrigin, getTile(thisIter).value)));
3564 ChildT& child = getChild(thisIter);
3569 child.combine2(ns0.tile.value, *ns1.child, ns0.isTileOn(),
op);
3570 }
else if (ns1.isTile()) {
3573 child.combine2(*ns0.child, ns1.tile.value, ns1.isTileOn(),
op);
3577 child.combine2(*ns0.child, *ns1.child, op);
3580 if (prune && isChild(thisIter)) getChild(thisIter).prune();
3584 op(args.
setARef(other0.mBackground).setBRef(other1.mBackground));
3585 mBackground = args.
result();
3593 #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
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
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
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)
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.
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.
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
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.
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.