8#ifndef OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
9#define OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
16#include <openvdb/version.h>
20#include <tbb/parallel_for.h>
30template<
typename, Index,
typename>
struct SameInternalConfig;
33template<
typename _ChildNodeType, Index Log2Dim>
39 using ValueType =
typename ChildNodeType::ValueType;
40 using BuildType =
typename ChildNodeType::BuildType;
46 TOTAL = Log2Dim + ChildNodeType::TOTAL,
48 NUM_VALUES = 1 << (3 * Log2Dim),
49 LEVEL = 1 + ChildNodeType::LEVEL;
51 NUM_VOXELS = uint64_t(1) << (3 * TOTAL);
55 template<
typename OtherValueType>
58 OtherValueType>::Type, Log2Dim>;
64 template<
typename OtherNodeType>
66 static const bool value =
83 InternalNode(
const Coord& origin,
const ValueType& fillValue,
bool active =
false);
95 template<
typename OtherChildNodeType>
101 template<
typename OtherChildNodeType>
108 template<
typename OtherChildNodeType>
110 const ValueType& offValue,
const ValueType& onValue,
TopologyCopy);
127 template<
typename NodeT,
typename ChildT,
typename MaskIterT,
typename TagT>
129 MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>
133 MaskIterT,
ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>(iter, parent) {}
138 return *(this->parent().getChildNode(pos));
142 void setItem(
Index pos,
const ChildT& c)
const { this->parent().resetChildNode(pos, &c); }
148 template<
typename NodeT,
typename ValueT,
typename MaskIterT,
typename TagT>
150 MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>
154 MaskIterT,
ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>(iter, parent) {}
156 const ValueT&
getItem(
Index pos)
const {
return this->parent().mNodes[pos].getValue(); }
159 void setItem(
Index pos,
const ValueT& v)
const { this->parent().mNodes[pos].setValue(v); }
162 template<
typename ModifyOp>
165 op(this->parent().mNodes[pos].getValue());
170 template<
typename NodeT,
typename ChildT,
typename ValueT,
typename TagT>
172 MaskDenseIterator, DenseIter<NodeT, ChildT, ValueT, TagT>, NodeT, ChildT, ValueT>
183 if (this->parent().isChildMaskOn(pos)) {
184 child = this->parent().getChildNode(pos);
188 value = this->parent().mNodes[pos].getValue();
195 this->parent().resetChildNode(pos, child);
201 this->parent().unsetChildNode(pos, value);
253 static void getNodeLog2Dims(std::vector<Index>& dims);
263 static void offsetToLocalCoord(
Index n,
Coord& xyz);
279 void nodeCount(std::vector<Index64> &vec)
const;
281 void nodeCount(
std::vector<
Index32> &vec) const;
285 Index64 onLeafVoxelCount() const;
286 Index64 offLeafVoxelCount() const;
296 void evalActiveBoundingBox(
CoordBBox& bbox,
bool visitVoxels = true) const;
300 CoordBBox getNodeBoundingBox()
const {
return CoordBBox::createCube(mOrigin, DIM); }
303 bool isEmpty()
const {
return mChildMask.isOff(); }
310 bool isConstant(ValueType& firstValue,
bool& state,
311 const ValueType& tolerance = zeroVal<ValueType>())
const;
327 bool isConstant(ValueType& minValue, ValueType& maxValue,
328 bool& state,
const ValueType& tolerance = zeroVal<ValueType>())
const;
331 bool isInactive()
const {
return this->isChildMaskOff() && this->isValueMaskOff(); }
334 bool isValueOn(
const Coord& xyz)
const;
338 bool isValueOff(
const Coord& xyz)
const;
343 bool hasActiveTiles()
const;
345 const ValueType& getValue(
const Coord& xyz)
const;
346 bool probeValue(
const Coord& xyz, ValueType& value)
const;
354 const ValueType& getFirstValue()
const;
357 const ValueType& getLastValue()
const;
360 void setActiveState(
const Coord& xyz,
bool on);
362 void setValueOnly(
const Coord& xyz,
const ValueType& value);
364 void setValueOn(
const Coord& xyz);
366 void setValueOn(
const Coord& xyz,
const ValueType& value);
368 void setValueOff(
const Coord& xyz);
370 void setValueOff(
const Coord& xyz,
const ValueType& value);
374 template<
typename ModifyOp>
375 void modifyValue(
const Coord& xyz,
const ModifyOp& op);
377 template<
typename ModifyOp>
378 void modifyValueAndActiveState(
const Coord& xyz,
const ModifyOp& op);
384 template<
typename AccessorT>
391 template<
typename AccessorT>
392 bool isValueOnAndCache(
const Coord& xyz, AccessorT&)
const;
398 template<
typename AccessorT>
399 void setValueAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
405 template<
typename AccessorT>
406 void setValueOnlyAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
413 template<
typename ModifyOp,
typename AccessorT>
414 void modifyValueAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
420 template<
typename ModifyOp,
typename AccessorT>
421 void modifyValueAndActiveStateAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
427 template<
typename AccessorT>
428 void setValueOffAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
434 template<
typename AccessorT>
435 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&);
442 template<
typename AccessorT>
443 bool probeValueAndCache(
const Coord& xyz,
ValueType& value, AccessorT&)
const;
451 template<
typename AccessorT>
452 Index getValueLevelAndCache(
const Coord& xyz, AccessorT&)
const;
460 void writeTopology(std::ostream&,
bool toHalf =
false)
const;
461 void readTopology(std::istream&,
bool fromHalf =
false);
462 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
463 void readBuffers(std::istream&,
bool fromHalf =
false);
464 void readBuffers(std::istream&,
const CoordBBox&,
bool fromHalf =
false);
501 void setActiveStateUnsafe(
Index offset,
bool on);
509 void setValueOnUnsafe(
Index offset);
517 void setValueOffUnsafe(
Index offset);
538 void deleteChildUnsafe(
Index offset,
const ValueType& value,
bool active);
569 void voxelizeActiveTiles(
bool threaded =
true);
578 template<
typename DenseT>
579 void copyToDense(
const CoordBBox& bbox, DenseT& dense)
const;
583 template<MergePolicy Policy>
588 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive);
602 template<
typename OtherChildNodeType>
618 template<
typename OtherChildNodeType>
633 template<
typename OtherChildNodeType>
637 template<
typename CombineOp>
639 template<
typename CombineOp>
640 void combine(
const ValueType& value,
bool valueIsActive, CombineOp&);
642 template<
typename CombineOp,
typename OtherNodeType >
643 void combine2(
const InternalNode& other0,
const OtherNodeType& other1, CombineOp&);
644 template<
typename CombineOp,
typename OtherNodeType >
645 void combine2(
const ValueType& value,
const OtherNodeType& other,
bool valIsActive, CombineOp&);
646 template<
typename CombineOp,
typename OtherValueType>
647 void combine2(
const InternalNode& other,
const OtherValueType&,
bool valIsActive, CombineOp&);
655 void prune(
const ValueType& tolerance = zeroVal<ValueType>());
663 template<
typename AccessorT>
674 template<
typename NodeT>
675 NodeT* stealNode(
const Coord& xyz,
const ValueType& value,
bool state);
694 template<
typename AccessorT>
695 void addTileAndCache(
Index level,
const Coord& xyz,
const ValueType&,
bool state, AccessorT&);
702 template<
typename NodeType>
const NodeType*
probeNode(
const Coord& xyz)
const {
return this->probeConstNode<NodeType>(xyz); }
708 ChildNodeType* probeChild(
const Coord& xyz);
709 const ChildNodeType* probeConstChild(
const Coord& xyz)
const;
716 ChildNodeType* probeChild(
const Coord& xyz, ValueType& value,
bool& active);
717 const ChildNodeType* probeConstChild(
const Coord& xyz, ValueType& value,
bool& active)
const;
726 ChildNodeType* probeChildUnsafe(
Index offset);
727 const ChildNodeType* probeConstChildUnsafe(
Index offset)
const;
736 ChildNodeType* probeChildUnsafe(
Index offset, ValueType& value,
bool& active);
737 const ChildNodeType* probeConstChildUnsafe(
Index offset, ValueType& value,
bool& active)
const;
744 template<
typename NodeType,
typename AccessorT>
746 template<
typename NodeType,
typename AccessorT>
761 template<
typename AccessorT>
763 template<
typename AccessorT>
765 template<
typename AccessorT>
779 template<
typename AccessorT>
805 template<
typename ArrayT>
806 void getNodes(ArrayT& array);
807 template<
typename ArrayT>
808 void getNodes(ArrayT& array)
const;
834 template<
typename ArrayT>
835 void stealNodes(ArrayT& array,
const ValueType& value,
bool state);
843 template<
typename OtherChildNodeType, Index OtherLog2Dim>
885 void makeChildNodeEmpty(
Index n,
const ValueType& value);
886 void setChildNode(
Index i, ChildNodeType* child);
887 void resetChildNode(
Index i, ChildNodeType* child);
888 ChildNodeType* unsetChildNode(
Index i,
const ValueType& value);
894 ChildNodeType* getChildNode(
Index n);
895 const ChildNodeType* getChildNode(
Index n)
const;
900 struct VoxelizeActiveTiles;
901 template<
typename OtherInternalNode>
struct DeepCopy;
902 template<
typename OtherInternalNode>
struct TopologyCopy1;
903 template<
typename OtherInternalNode>
struct TopologyCopy2;
904 template<
typename OtherInternalNode>
struct TopologyUnion;
905 template<
typename OtherInternalNode>
struct TopologyDifference;
906 template<
typename OtherInternalNode>
struct TopologyIntersection;
924template<
typename ChildT1, Index Dim1,
typename NodeT2>
926 static const bool value =
false;
929template<
typename ChildT1, Index Dim1,
typename ChildT2>
931 static const bool value = ChildT1::template SameConfiguration<ChildT2>::value;
939template<
typename ChildT, Index Log2Dim>
943 for (
Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(background);
947template<
typename ChildT, Index Log2Dim>
950 mOrigin(origin[0] & ~(DIM - 1),
951 origin[1] & ~(DIM - 1),
952 origin[2] & ~(DIM - 1))
961template<
typename ChildT, Index Log2Dim>
965 : mOrigin(origin[0] & ~(DIM-1), origin[1] & ~(DIM-1), origin[2] & ~(DIM-1))
971template<
typename ChildT, Index Log2Dim>
972template<
typename OtherInternalNode>
976 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
980 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
981 if (s->mChildMask.isOff(i)) {
982 t->mNodes[i].setValue(
ValueType(s->mNodes[i].getValue()));
984 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild())));
988 const OtherInternalNode*
s;
992template<
typename ChildT, Index Log2Dim>
995 : mChildMask(other.mChildMask)
996 , mValueMask(other.mValueMask)
997 , mOrigin(other.mOrigin)
998 , mTransientData(other.mTransientData)
1005template<
typename ChildT, Index Log2Dim>
1006template<
typename OtherChildNodeType>
1009 : mChildMask(other.mChildMask)
1010 , mValueMask(other.mValueMask)
1011 , mOrigin(other.mOrigin)
1012 , mTransientData(other.mTransientData)
1017template<
typename ChildT, Index Log2Dim>
1018template<
typename OtherInternalNode>
1022 const ValueType& background) : s(source), t(target), b(background) {
1023 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
1027 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
1028 if (s->isChildMaskOn(i)) {
1029 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild()),
1032 t->mNodes[i].setValue(b);
1036 const OtherInternalNode*
s;
1041template<
typename ChildT, Index Log2Dim>
1042template<
typename OtherChildNodeType>
1046 : mChildMask(other.mChildMask)
1047 , mValueMask(other.mValueMask)
1048 , mOrigin(other.mOrigin)
1049 , mTransientData(other.mTransientData)
1054template<
typename ChildT, Index Log2Dim>
1055template<
typename OtherInternalNode>
1060 : s(source), t(target), offV(offValue), onV(onValue) {
1061 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
1064 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
1065 if (s->isChildMaskOn(i)) {
1066 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild()),
1069 t->mNodes[i].setValue(s->isValueMaskOn(i) ? onV : offV);
1073 const OtherInternalNode*
s;
1078template<
typename ChildT, Index Log2Dim>
1079template<
typename OtherChildNodeType>
1084 : mChildMask(other.mChildMask)
1085 , mValueMask(other.mValueMask)
1086 , mOrigin(other.mOrigin)
1087 , mTransientData(other.mTransientData)
1093template<
typename ChildT, Index Log2Dim>
1097 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1098 delete mNodes[iter.pos()].getChild();
1106template<
typename ChildT, Index Log2Dim>
1110 if (ChildNodeType::getLevel() == 0)
return mChildMask.countOn();
1112 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1113 sum += iter->leafCount();
1118template<
typename ChildT, Index Log2Dim>
1123 const auto count = mChildMask.countOn();
1124 if (ChildNodeType::LEVEL > 0 && count > 0) {
1125 for (
auto iter = this->cbeginChildOn(); iter; ++iter) iter->nodeCount(vec);
1127 vec[ChildNodeType::LEVEL] += count;
1130template<
typename ChildT, Index Log2Dim>
1135 const auto count = mChildMask.countOn();
1136 if (ChildNodeType::LEVEL > 0 && count > 0) {
1137 for (
auto iter = this->cbeginChildOn(); iter; ++iter) {
1139 iter->nodeCount(vec);
1143 vec[ChildNodeType::LEVEL] += count;
1147template<
typename ChildT, Index Log2Dim>
1152 if (ChildNodeType::getLevel() == 0)
return sum;
1153 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1154 sum += iter->nonLeafCount();
1160template<
typename ChildT, Index Log2Dim>
1164 return this->getChildMask().countOn();
1168template<
typename ChildT, Index Log2Dim>
1172 Index64 sum = ChildT::NUM_VOXELS * mValueMask.countOn();
1173 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1174 sum += iter->onVoxelCount();
1180template<
typename ChildT, Index Log2Dim>
1184 Index64 sum = ChildT::NUM_VOXELS * (NUM_VALUES-mValueMask.countOn()-mChildMask.countOn());
1185 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1186 sum += iter->offVoxelCount();
1192template<
typename ChildT, Index Log2Dim>
1197 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1198 sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount();
1204template<
typename ChildT, Index Log2Dim>
1209 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1210 sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount();
1215template<
typename ChildT, Index Log2Dim>
1219 Index64 sum = mValueMask.countOn();
1220 for (
ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) {
1221 sum += iter->onTileCount();
1226template<
typename ChildT, Index Log2Dim>
1231 + mValueMask.memUsage() +
sizeof(mOrigin);
1232 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1233 sum += iter->memUsage();
1239template<
typename ChildT, Index Log2Dim>
1243 if (bbox.
isInside(this->getNodeBoundingBox()))
return;
1246 bbox.
expand(i.getCoord(), ChildT::DIM);
1249 i->evalActiveBoundingBox(bbox, visitVoxels);
1257template<
typename ChildT, Index Log2Dim>
1263 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1264 const Index i = iter.pos();
1265 ChildT* child = mNodes[i].getChild();
1266 child->prune(tolerance);
1267 if (child->isConstant(value, state, tolerance)) {
1269 mChildMask.setOff(i);
1270 mValueMask.set(i, state);
1271 mNodes[i].setValue(value);
1280template<
typename ChildT, Index Log2Dim>
1281template<
typename NodeT>
1285 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1286 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1288 const Index n = this->coordToOffset(xyz);
1289 if (mChildMask.isOff(n))
return nullptr;
1290 ChildT* child = mNodes[n].getChild();
1291 if (std::is_same<NodeT, ChildT>::value) {
1292 mChildMask.setOff(n);
1293 mValueMask.set(n, state);
1294 mNodes[n].setValue(value);
1296 return (std::is_same<NodeT, ChildT>::value)
1297 ?
reinterpret_cast<NodeT*
>(child)
1298 : child->template stealNode<NodeT>(xyz, value, state);
1306template<
typename ChildT, Index Log2Dim>
1307template<
typename NodeT>
1311 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1312 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1314 const Index n = this->coordToOffset(xyz);
1315 if (mChildMask.isOff(n))
return nullptr;
1316 ChildT* child = mNodes[n].getChild();
1317 return (std::is_same<NodeT, ChildT>::value)
1318 ?
reinterpret_cast<NodeT*
>(child)
1319 : child->template probeNode<NodeT>(xyz);
1324template<
typename ChildT, Index Log2Dim>
1325template<
typename NodeT,
typename AccessorT>
1329 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1330 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1332 const Index n = this->coordToOffset(xyz);
1333 if (mChildMask.isOff(n))
return nullptr;
1334 ChildT* child = mNodes[n].getChild();
1335 acc.insert(xyz, child);
1336 return (std::is_same<NodeT, ChildT>::value)
1337 ?
reinterpret_cast<NodeT*
>(child)
1338 : child->template probeNodeAndCache<NodeT>(xyz, acc);
1343template<
typename ChildT, Index Log2Dim>
1344template<
typename NodeT>
1348 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1349 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1351 const Index n = this->coordToOffset(xyz);
1352 if (mChildMask.isOff(n))
return nullptr;
1353 const ChildT* child = mNodes[n].getChild();
1354 return (std::is_same<NodeT, ChildT>::value)
1355 ?
reinterpret_cast<const NodeT*
>(child)
1356 : child->template probeConstNode<NodeT>(xyz);
1361template<
typename ChildT, Index Log2Dim>
1362template<
typename NodeT,
typename AccessorT>
1366 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1367 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1369 const Index n = this->coordToOffset(xyz);
1370 if (mChildMask.isOff(n))
return nullptr;
1371 const ChildT* child = mNodes[n].getChild();
1372 acc.insert(xyz, child);
1373 return (std::is_same<NodeT, ChildT>::value)
1374 ?
reinterpret_cast<const NodeT*
>(child)
1375 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
1383template<
typename ChildT, Index Log2Dim>
1387 const Index n = this->coordToOffset(xyz);
1388 return this->probeChildUnsafe(n);
1391template<
typename ChildT, Index Log2Dim>
1395 const Index n = this->coordToOffset(xyz);
1396 return this->probeConstChildUnsafe(n);
1399template<
typename ChildT, Index Log2Dim>
1403 const Index n = this->coordToOffset(xyz);
1404 return this->probeChildUnsafe(n, value, active);
1407template<
typename ChildT, Index Log2Dim>
1411 const Index n = this->coordToOffset(xyz);
1412 return this->probeConstChildUnsafe(n, value, active);
1415template<
typename ChildT, Index Log2Dim>
1420 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1424template<
typename ChildT, Index Log2Dim>
1429 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1433template<
typename ChildT, Index Log2Dim>
1438 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1439 value = mNodes[offset].getValue();
1440 active = mValueMask.isOn(offset);
1444template<
typename ChildT, Index Log2Dim>
1449 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1450 value = mNodes[offset].getValue();
1451 active = mValueMask.isOn(offset);
1459template<
typename ChildT, Index Log2Dim>
1460inline typename ChildT::LeafNodeType*
1463 return this->
template probeNode<LeafNodeType>(xyz);
1467template<
typename ChildT, Index Log2Dim>
1468template<
typename AccessorT>
1469inline typename ChildT::LeafNodeType*
1472 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
1476template<
typename ChildT, Index Log2Dim>
1477template<
typename AccessorT>
1478inline const typename ChildT::LeafNodeType*
1481 return this->probeConstLeafAndCache(xyz, acc);
1485template<
typename ChildT, Index Log2Dim>
1486inline const typename ChildT::LeafNodeType*
1489 return this->
template probeConstNode<LeafNodeType>(xyz);
1493template<
typename ChildT, Index Log2Dim>
1494template<
typename AccessorT>
1495inline const typename ChildT::LeafNodeType*
1498 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
1505template<
typename ChildT, Index Log2Dim>
1510 const Coord& xyz = leaf->origin();
1511 const Index n = this->coordToOffset(xyz);
1512 ChildT* child =
nullptr;
1513 if (mChildMask.isOff(n)) {
1514 if (ChildT::LEVEL>0) {
1515 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1517 child =
reinterpret_cast<ChildT*
>(leaf);
1519 this->setChildNode(n, child);
1521 if (ChildT::LEVEL>0) {
1522 child = mNodes[n].getChild();
1524 delete mNodes[n].getChild();
1525 child =
reinterpret_cast<ChildT*
>(leaf);
1526 mNodes[n].setChild(child);
1529 child->addLeaf(leaf);
1533template<
typename ChildT, Index Log2Dim>
1534template<
typename AccessorT>
1539 const Coord& xyz = leaf->origin();
1540 const Index n = this->coordToOffset(xyz);
1541 ChildT* child =
nullptr;
1542 if (mChildMask.isOff(n)) {
1543 if (ChildT::LEVEL>0) {
1544 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1545 acc.insert(xyz, child);
1547 child =
reinterpret_cast<ChildT*
>(leaf);
1549 this->setChildNode(n, child);
1551 if (ChildT::LEVEL>0) {
1552 child = mNodes[n].getChild();
1553 acc.insert(xyz, child);
1555 delete mNodes[n].getChild();
1556 child =
reinterpret_cast<ChildT*
>(leaf);
1557 mNodes[n].setChild(child);
1560 child->addLeafAndCache(leaf, acc);
1567template<
typename ChildT, Index Log2Dim>
1572 const Coord& xyz = child->origin();
1574 if (
Coord((xyz & ~(DIM-1))) != this->origin())
return false;
1576 const Index n = this->coordToOffset(xyz);
1578 this->resetChildNode(n, child);
1583template<
typename ChildT, Index Log2Dim>
1588 this->makeChildNodeEmpty(n, value);
1589 mValueMask.set(n, state);
1593template<
typename ChildT, Index Log2Dim>
1598 if (LEVEL >= level) {
1599 const Index n = this->coordToOffset(xyz);
1600 if (mChildMask.isOff(n)) {
1601 if (LEVEL > level) {
1602 ChildT* child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1603 this->setChildNode(n, child);
1604 child->addTile(level, xyz, value, state);
1606 mValueMask.set(n, state);
1607 mNodes[n].setValue(value);
1610 ChildT* child = mNodes[n].getChild();
1611 if (LEVEL > level) {
1612 child->addTile(level, xyz, value, state);
1615 mChildMask.setOff(n);
1616 mValueMask.set(n, state);
1617 mNodes[n].setValue(value);
1624template<
typename ChildT, Index Log2Dim>
1625template<
typename AccessorT>
1628 const ValueType& value,
bool state, AccessorT& acc)
1630 if (LEVEL >= level) {
1631 const Index n = this->coordToOffset(xyz);
1632 if (mChildMask.isOff(n)) {
1633 if (LEVEL > level) {
1634 ChildT* child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1635 this->setChildNode(n, child);
1636 acc.insert(xyz, child);
1637 child->addTileAndCache(level, xyz, value, state, acc);
1639 mValueMask.set(n, state);
1640 mNodes[n].setValue(value);
1643 ChildT* child = mNodes[n].getChild();
1644 if (LEVEL > level) {
1645 acc.insert(xyz, child);
1646 child->addTileAndCache(level, xyz, value, state, acc);
1649 mChildMask.setOff(n);
1650 mValueMask.set(n, state);
1651 mNodes[n].setValue(value);
1661template<
typename ChildT, Index Log2Dim>
1662inline typename ChildT::LeafNodeType*
1665 const Index n = this->coordToOffset(xyz);
1666 ChildT* child =
nullptr;
1667 if (mChildMask.isOff(n)) {
1668 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1669 this->setChildNode(n, child);
1671 child = mNodes[n].getChild();
1673 return child->touchLeaf(xyz);
1677template<
typename ChildT, Index Log2Dim>
1678template<
typename AccessorT>
1679inline typename ChildT::LeafNodeType*
1682 const Index n = this->coordToOffset(xyz);
1683 if (mChildMask.isOff(n)) {
1684 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), mValueMask.isOn(n)));
1686 acc.insert(xyz, mNodes[n].getChild());
1687 return mNodes[n].getChild()->touchLeafAndCache(xyz, acc);
1694template<
typename ChildT, Index Log2Dim>
1699 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1701 firstValue = mNodes[0].getValue();
1702 for (
Index i = 1; i < NUM_VALUES; ++i) {
1714template<
typename ChildT, Index Log2Dim>
1722 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1723 minValue = maxValue = mNodes[0].getValue();
1724 for (
Index i = 1; i < NUM_VALUES; ++i) {
1725 const ValueType& v = mNodes[i].getValue();
1727 if ((maxValue - v) > tolerance)
return false;
1729 }
else if (v > maxValue) {
1730 if ((v - minValue) > tolerance)
return false;
1741template<
typename ChildT, Index Log2Dim>
1746 const bool anyActiveTiles = !mValueMask.isOff();
1747 if (LEVEL==1 || anyActiveTiles)
return anyActiveTiles;
1748 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1749 if (iter->hasActiveTiles())
return true;
1756template<
typename ChildT, Index Log2Dim>
1760 const Index n = this->coordToOffset(xyz);
1761 return this->isChildMaskOff(n) ? this->isValueMaskOn(n)
1762 : mNodes[n].getChild()->isValueOn(xyz);
1765template<
typename ChildT, Index Log2Dim>
1769 const Index n = this->coordToOffset(xyz);
1770 return this->isChildMaskOff(n) ? this->isValueMaskOn(n)
1771 : mNodes[n].getChild()->isValueOff(xyz);
1774template<
typename ChildT, Index Log2Dim>
1775template<
typename AccessorT>
1779 const Index n = this->coordToOffset(xyz);
1780 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1781 acc.insert(xyz, mNodes[n].getChild());
1782 return mNodes[n].getChild()->isValueOnAndCache(xyz, acc);
1786template<
typename ChildT, Index Log2Dim>
1787inline const typename ChildT::ValueType&
1790 const Index n = this->coordToOffset(xyz);
1791 return this->isChildMaskOff(n) ? mNodes[n].getValue()
1792 : mNodes[n].getChild()->getValue(xyz);
1795template<
typename ChildT, Index Log2Dim>
1796template<
typename AccessorT>
1797inline const typename ChildT::ValueType&
1800 const Index n = this->coordToOffset(xyz);
1801 if (this->isChildMaskOn(n)) {
1802 acc.insert(xyz, mNodes[n].getChild());
1803 return mNodes[n].getChild()->getValueAndCache(xyz, acc);
1805 return mNodes[n].getValue();
1809template<
typename ChildT, Index Log2Dim>
1813 const Index n = this->coordToOffset(xyz);
1814 return this->isChildMaskOff(n) ? LEVEL : mNodes[n].getChild()->getValueLevel(xyz);
1817template<
typename ChildT, Index Log2Dim>
1818template<
typename AccessorT>
1822 const Index n = this->coordToOffset(xyz);
1823 if (this->isChildMaskOn(n)) {
1824 acc.insert(xyz, mNodes[n].getChild());
1825 return mNodes[n].getChild()->getValueLevelAndCache(xyz, acc);
1831template<
typename ChildT, Index Log2Dim>
1835 const Index n = this->coordToOffset(xyz);
1836 if (this->isChildMaskOff(n)) {
1837 value = mNodes[n].getValue();
1838 return this->isValueMaskOn(n);
1840 return mNodes[n].getChild()->probeValue(xyz, value);
1843template<
typename ChildT, Index Log2Dim>
1844template<
typename AccessorT>
1849 const Index n = this->coordToOffset(xyz);
1850 if (this->isChildMaskOn(n)) {
1851 acc.insert(xyz, mNodes[n].getChild());
1852 return mNodes[n].getChild()->probeValueAndCache(xyz, value, acc);
1854 value = mNodes[n].getValue();
1855 return this->isValueMaskOn(n);
1859template<
typename ChildT, Index Log2Dim>
1863 const Index n = this->coordToOffset(xyz);
1864 bool hasChild = this->isChildMaskOn(n);
1865 if (!hasChild && this->isValueMaskOn(n)) {
1869 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
true));
1871 if (hasChild) mNodes[n].getChild()->setValueOff(xyz);
1875template<
typename ChildT, Index Log2Dim>
1879 const Index n = this->coordToOffset(xyz);
1880 bool hasChild = this->isChildMaskOn(n);
1881 if (!hasChild && !this->isValueMaskOn(n)) {
1885 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
false));
1887 if (hasChild) mNodes[n].getChild()->setValueOn(xyz);
1891template<
typename ChildT, Index Log2Dim>
1896 bool hasChild = this->isChildMaskOn(n);
1898 const bool active = this->isValueMaskOn(n);
1904 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1907 if (hasChild) mNodes[n].getChild()->setValueOff(xyz, value);
1910template<
typename ChildT, Index Log2Dim>
1911template<
typename AccessorT>
1917 bool hasChild = this->isChildMaskOn(n);
1919 const bool active = this->isValueMaskOn(n);
1925 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1929 ChildT* child = mNodes[n].getChild();
1930 acc.insert(xyz, child);
1931 child->setValueOffAndCache(xyz, value, acc);
1936template<
typename ChildT, Index Log2Dim>
1940 const Index n = this->coordToOffset(xyz);
1941 bool hasChild = this->isChildMaskOn(n);
1943 const bool active = this->isValueMaskOn(n);
1949 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1952 if (hasChild) mNodes[n].getChild()->setValueOn(xyz, value);
1955template<
typename ChildT, Index Log2Dim>
1956template<
typename AccessorT>
1961 const Index n = this->coordToOffset(xyz);
1962 bool hasChild = this->isChildMaskOn(n);
1964 const bool active = this->isValueMaskOn(n);
1970 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1974 acc.insert(xyz, mNodes[n].getChild());
1975 mNodes[n].getChild()->setValueAndCache(xyz, value, acc);
1980template<
typename ChildT, Index Log2Dim>
1984 const Index n = this->coordToOffset(xyz);
1985 bool hasChild = this->isChildMaskOn(n);
1989 const bool active = this->isValueMaskOn(n);
1991 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1993 if (hasChild) mNodes[n].getChild()->setValueOnly(xyz, value);
1996template<
typename ChildT, Index Log2Dim>
1997template<
typename AccessorT>
2002 const Index n = this->coordToOffset(xyz);
2003 bool hasChild = this->isChildMaskOn(n);
2007 const bool active = this->isValueMaskOn(n);
2009 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
2012 acc.insert(xyz, mNodes[n].getChild());
2013 mNodes[n].getChild()->setValueOnlyAndCache(xyz, value, acc);
2018template<
typename ChildT, Index Log2Dim>
2022 const Index n = this->coordToOffset(xyz);
2023 bool hasChild = this->isChildMaskOn(n);
2025 if (on != this->isValueMaskOn(n)) {
2030 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
2033 if (hasChild) mNodes[n].getChild()->setActiveState(xyz, on);
2036template<
typename ChildT, Index Log2Dim>
2037template<
typename AccessorT>
2041 const Index n = this->coordToOffset(xyz);
2042 bool hasChild = this->isChildMaskOn(n);
2044 if (on != this->isValueMaskOn(n)) {
2049 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
2053 ChildT* child = mNodes[n].getChild();
2054 acc.insert(xyz, child);
2055 child->setActiveStateAndCache(xyz, on, acc);
2060template<
typename ChildT, Index Log2Dim>
2064 mValueMask = !mChildMask;
2065 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2066 mNodes[iter.pos()].getChild()->setValuesOn();
2071template<
typename ChildT, Index Log2Dim>
2072template<
typename ModifyOp>
2077 bool hasChild = this->isChildMaskOn(n);
2081 const bool active = this->isValueMaskOn(n);
2082 bool createChild = !active;
2086 const ValueType& tileVal = mNodes[n].getValue();
2093 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
2096 if (hasChild) mNodes[n].getChild()->modifyValue(xyz, op);
2099template<
typename ChildT, Index Log2Dim>
2100template<
typename ModifyOp,
typename AccessorT>
2106 bool hasChild = this->isChildMaskOn(n);
2110 const bool active = this->isValueMaskOn(n);
2111 bool createChild = !active;
2115 const ValueType& tileVal = mNodes[n].getValue();
2122 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
2127 acc.insert(xyz, child);
2128 child->modifyValueAndCache(xyz, op, acc);
2133template<
typename ChildT, Index Log2Dim>
2134template<
typename ModifyOp>
2139 bool hasChild = this->isChildMaskOn(n);
2141 const bool tileState = this->isValueMaskOn(n);
2142 const ValueType& tileVal = mNodes[n].getValue();
2143 bool modifiedState = !tileState;
2145 op(modifiedVal, modifiedState);
2150 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
2153 if (hasChild) mNodes[n].getChild()->modifyValueAndActiveState(xyz, op);
2156template<
typename ChildT, Index Log2Dim>
2157template<
typename ModifyOp,
typename AccessorT>
2160 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
2163 bool hasChild = this->isChildMaskOn(n);
2165 const bool tileState = this->isValueMaskOn(n);
2166 const ValueType& tileVal = mNodes[n].getValue();
2167 bool modifiedState = !tileState;
2169 op(modifiedVal, modifiedState);
2174 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
2179 acc.insert(xyz, child);
2180 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
2188template<
typename ChildT, Index Log2Dim>
2192 CoordBBox nodeBBox = this->getNodeBoundingBox();
2195 this->fill(nodeBBox, background,
false);
2196 }
else if (clipBBox.
isInside(nodeBBox)) {
2205 for (
Index pos = 0; pos < NUM_VALUES; ++pos) {
2206 const Coord xyz = this->offsetToGlobalCoord(pos);
2211 this->makeChildNodeEmpty(pos, background);
2212 mValueMask.setOff(pos);
2213 }
else if (!clipBBox.
isInside(tileBBox)) {
2216 if (this->isChildMaskOn(pos)) {
2217 mNodes[pos].getChild()->clip(clipBBox, background);
2222 const ValueType val = mNodes[pos].getValue();
2223 const bool on = this->isValueMaskOn(pos);
2224 mNodes[pos].setValue(background);
2225 mValueMask.setOff(pos);
2226 this->fill(tileBBox, val, on);
2238template<
typename ChildT, Index Log2Dim>
2242 auto clippedBBox = this->getNodeBoundingBox();
2243 clippedBBox.intersect(bbox);
2244 if (!clippedBBox)
return;
2248 Coord xyz, tileMin, tileMax;
2249 for (
int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.
x() + 1) {
2251 for (
int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.
y() + 1) {
2253 for (
int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.
z() + 1) {
2257 const Index n = this->coordToOffset(xyz);
2258 tileMin = this->offsetToGlobalCoord(n);
2259 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2265 ChildT* child =
nullptr;
2266 if (this->isChildMaskOff(n)) {
2269 child =
new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)};
2270 this->setChildNode(n, child);
2272 child = mNodes[n].getChild();
2278 child->fill(
CoordBBox(xyz, tmp), value, active);
2285 this->makeChildNodeEmpty(n, value);
2286 mValueMask.set(n, active);
2294template<
typename ChildT, Index Log2Dim>
2298 auto clippedBBox = this->getNodeBoundingBox();
2299 clippedBBox.intersect(bbox);
2300 if (!clippedBBox)
return;
2304 Coord xyz, tileMin, tileMax;
2305 for (
int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.
x() + 1) {
2307 for (
int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.
y() + 1) {
2309 for (
int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.
z() + 1) {
2313 const auto n = this->coordToOffset(xyz);
2316 ChildT* child =
nullptr;
2317 if (this->isChildMaskOn(n)) {
2318 child = mNodes[n].getChild();
2322 child =
new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)};
2323 this->setChildNode(n, child);
2327 tileMin = this->offsetToGlobalCoord(n);
2328 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2331 child->denseFill(
CoordBBox{xyz, clippedBBox.
max()}, value, active);
2341template<
typename ChildT, Index Log2Dim>
2342template<
typename DenseT>
2346 using DenseValueType =
typename DenseT::ValueType;
2348 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2349 const Coord& min = dense.bbox().min();
2350 for (
Coord xyz = bbox.
min(), max; xyz[0] <= bbox.
max()[0]; xyz[0] = max[0] + 1) {
2351 for (xyz[1] = bbox.
min()[1]; xyz[1] <= bbox.
max()[1]; xyz[1] = max[1] + 1) {
2352 for (xyz[2] = bbox.
min()[2]; xyz[2] <= bbox.
max()[2]; xyz[2] = max[2] + 1) {
2353 const Index n = this->coordToOffset(xyz);
2355 max = this->offsetToGlobalCoord(n).offsetBy(ChildT::DIM-1);
2360 if (this->isChildMaskOn(n)) {
2361 mNodes[n].getChild()->copyToDense(sub, dense);
2363 const ValueType value = mNodes[n].getValue();
2365 DenseValueType* a0 = dense.data() + zStride*sub.
min()[2];
2366 for (
Int32 x=sub.
min()[0], ex=sub.
max()[0]+1; x<ex; ++x) {
2367 DenseValueType* a1 = a0 + x*xStride;
2368 for (
Int32 y=sub.
min()[1], ey=sub.
max()[1]+1; y<ey; ++y) {
2369 DenseValueType* a2 = a1 + y*yStride;
2371 z < ez; ++z, a2 += zStride)
2373 *a2 = DenseValueType(value);
2387template<
typename ChildT, Index Log2Dim>
2391 mChildMask.save(os);
2392 mValueMask.save(os);
2396 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[NUM_VALUES]);
2399 for (
Index i = 0; i < NUM_VALUES; ++i) {
2400 values[i] = (mChildMask.isOff(i) ? mNodes[i].getValue() : zero);
2406 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2407 iter->writeTopology(os, toHalf);
2412template<
typename ChildT, Index Log2Dim>
2419 mChildMask.load(is);
2420 mValueMask.load(is);
2423 for (
Index i = 0; i < NUM_VALUES; ++i) {
2424 if (this->isChildMaskOn(i)) {
2427 mNodes[i].setChild(child);
2428 child->readTopology(is);
2431 is.read(
reinterpret_cast<char*
>(&value),
sizeof(
ValueType));
2432 mNodes[i].setValue(value);
2436 const bool oldVersion =
2438 const Index numValues = (oldVersion ? mChildMask.countOff() : NUM_VALUES);
2442 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[numValues]);
2449 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2450 mNodes[iter.pos()].setValue(values[n++]);
2454 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2455 mNodes[iter.pos()].setValue(values[iter.pos()]);
2460 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2462 mNodes[iter.pos()].setChild(child);
2463 child->readTopology(is, fromHalf);
2472template<
typename ChildT, Index Log2Dim>
2473inline const typename ChildT::ValueType&
2476 return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].getValue());
2480template<
typename ChildT, Index Log2Dim>
2481inline const typename ChildT::ValueType&
2484 const Index n = NUM_VALUES - 1;
2485 return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].getValue());
2492template<
typename ChildT, Index Log2Dim>
2493inline const typename ChildT::ValueType&
2498 return mNodes[n].getValue();
2501template<
typename ChildT, Index Log2Dim>
2507 value = mNodes[n].getValue();
2508 return mValueMask.isOn(n);
2511template<
typename ChildT, Index Log2Dim>
2517 return mNodes[n].getChild();
2520template<
typename ChildT, Index Log2Dim>
2526 return mNodes[n].getChild();
2529template<
typename ChildT, Index Log2Dim>
2533 return this->getConstChildUnsafe(n);
2536template<
typename ChildT, Index Log2Dim>
2542 mValueMask.set(n, on);
2545template<
typename ChildT, Index Log2Dim>
2551 mNodes[n].setValue(value);
2554template<
typename ChildT, Index Log2Dim>
2560 mValueMask.setOn(n);
2563template<
typename ChildT, Index Log2Dim>
2569 mNodes[n].setValue(value);
2570 mValueMask.setOn(n);
2573template<
typename ChildT, Index Log2Dim>
2579 mValueMask.setOff(n);
2582template<
typename ChildT, Index Log2Dim>
2588 mNodes[n].setValue(value);
2589 mValueMask.setOff(n);
2592template<
typename ChildT, Index Log2Dim>
2599 mNodes[n].setChild(child);
2600 mChildMask.setOn(n);
2601 mValueMask.setOff(n);
2604template<
typename ChildT, Index Log2Dim>
2612 delete mNodes[n].getChild();
2613 mNodes[n].setChild(child);
2616template<
typename ChildT, Index Log2Dim>
2623 auto* child = mNodes[n].getChild();
2624 mChildMask.setOff(n);
2625 mValueMask.set(n, active);
2626 mNodes[n].setValue(value);
2630template<
typename ChildT, Index Log2Dim>
2635 delete this->stealChildUnsafe(n, value, active);
2642template<
typename ChildT, Index Log2Dim>
2646 for (
Index i = 0; i < NUM_VALUES; ++i) {
2647 if (this->isChildMaskOn(i)) {
2648 mNodes[i].getChild()->negate();
2660template<
typename ChildT, Index Log2Dim>
2665 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2672 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2673 if (mNode->mChildMask.isOn(i)) {
2674 mNode->mNodes[i].getChild()->voxelizeActiveTiles(
true);
2675 }
else if (mNode->mValueMask.isOn(i)) {
2676 const Coord &ijk = mNode->offsetToGlobalCoord(i);
2678 child->voxelizeActiveTiles(
true);
2679 mNode->mNodes[i].setChild(child);
2686template<
typename ChildT, Index Log2Dim>
2693 for (
ValueOnIter iter = this->beginValueOn(); iter; ++iter) {
2694 this->setChildNode(iter.pos(),
2697 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter)
2698 iter->voxelizeActiveTiles(
false);
2706template<
typename ChildT, Index Log2Dim>
2707template<MergePolicy Policy>
2720 const Index n = iter.pos();
2721 if (mChildMask.isOn(n)) {
2723 mNodes[n].getChild()->template merge<MERGE_ACTIVE_STATES>(*iter,
2724 background, otherBackground);
2725 }
else if (mValueMask.isOff(n)) {
2732 child->resetBackground(otherBackground, background);
2733 this->setChildNode(n, child);
2739 const Index n = iter.pos();
2740 if (mValueMask.isOff(n)) {
2742 this->makeChildNodeEmpty(n, iter.getValue());
2743 mValueMask.setOn(n);
2752 const Index n = iter.pos();
2753 if (mChildMask.isOn(n)) {
2755 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2763 child->resetBackground(otherBackground, background);
2764 this->setChildNode(n, child);
2774 const Index n = iter.pos();
2775 if (mChildMask.isOn(n)) {
2777 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2784 child->resetBackground(otherBackground, background);
2785 if (mValueMask.isOn(n)) {
2787 child->template merge<Policy>(mNodes[n].getValue(),
true);
2788 mValueMask.setOff(n);
2790 mChildMask.setOn(n);
2791 mNodes[n].setChild(child);
2797 const Index n = iter.pos();
2798 if (mChildMask.isOn(n)) {
2800 mNodes[n].getChild()->template merge<Policy>(iter.getValue(),
true);
2801 }
else if (mValueMask.isOff(n)) {
2803 mNodes[n].setValue(iter.getValue());
2804 mValueMask.setOn(n);
2815template<
typename ChildT, Index Log2Dim>
2816template<MergePolicy Policy>
2825 if (!tileActive)
return;
2828 for (
ValueOffIter iter = this->beginValueOff(); iter; ++iter) {
2829 const Index n = iter.pos();
2830 if (mChildMask.isOn(n)) {
2832 mNodes[n].getChild()->template merge<Policy>(tileValue,
true);
2835 iter.setValue(tileValue);
2836 mValueMask.setOn(n);
2846template<
typename ChildT, Index Log2Dim>
2847template<
typename OtherInternalNode>
2852 { tV = (tV | sV) & ~tC; }
2855 : s(source), t(target), mPreserveTiles(preserveTiles) {
2857 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2860 if (!mPreserveTiles) t->mChildMask |= s->mChildMask;
2861 else t->mChildMask |= (s->mChildMask & !t->mValueMask);
2864 t->mValueMask.foreach(s->mValueMask, t->mChildMask, op);
2868 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2869 if (s->mChildMask.isOn(i)) {
2870 const typename OtherInternalNode::ChildNodeType& other = *(s->mNodes[i].getChild());
2871 if (t->mChildMask.isOn(i)) {
2872 t->mNodes[i].getChild()->topologyUnion(other, mPreserveTiles);
2874 if (!mPreserveTiles || t->mValueMask.isOff(i)) {
2875 ChildT* child =
new ChildT(other, t->mNodes[i].getValue(),
TopologyCopy());
2876 if (t->mValueMask.isOn(i)) child->setValuesOn();
2877 t->mNodes[i].setChild(child);
2880 }
else if (s->mValueMask.isOn(i) && t->mChildMask.isOn(i)) {
2881 t->mNodes[i].getChild()->setValuesOn();
2885 const OtherInternalNode*
s;
2890template<
typename ChildT, Index Log2Dim>
2891template<
typename OtherChildT>
2898template<
typename ChildT, Index Log2Dim>
2899template<
typename OtherInternalNode>
2904 { tC = (tC & (sC | sV)) | (tV & sC); }
2907 const ValueType& background) : s(source), t(target), b(background) {
2909 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
2913 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op);
2915 t->mValueMask &= s->mValueMask;
2919 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2920 if (t->mChildMask.isOn(i)) {
2921 ChildT* child = t->mNodes[i].getChild();
2922 if (s->mChildMask.isOn(i)) {
2923 child->topologyIntersection(*(s->mNodes[i].getChild()), b);
2924 }
else if (s->mValueMask.isOff(i)) {
2926 t->mNodes[i].setValue(b);
2928 }
else if (t->mValueMask.isOn(i) && s->mChildMask.isOn(i)) {
2929 t->mNodes[i].setChild(
new ChildT(*(s->mNodes[i].getChild()),
2934 const OtherInternalNode*
s;
2939template<
typename ChildT, Index Log2Dim>
2940template<
typename OtherChildT>
2948template<
typename ChildT, Index Log2Dim>
2949template<
typename OtherInternalNode>
2954 { tC = (tC & (sC | ~sV)) | (tV & sC); }
2957 { tV &= ~((tC & sV) | (sC | sV)); }
2960 const ValueType& background) : s(source), t(target), b(background) {
2962 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
2967 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op1);
2970 t->mValueMask.foreach(t->mChildMask, s->mValueMask, oldChildMask, op2);
2974 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2975 if (t->mChildMask.isOn(i)) {
2976 ChildT* child = t->mNodes[i].getChild();
2977 if (s->mChildMask.isOn(i)) {
2978 child->topologyDifference(*(s->mNodes[i].getChild()), b);
2979 }
else if (s->mValueMask.isOn(i)) {
2981 t->mNodes[i].setValue(b);
2983 }
else if (t->mValueMask.isOn(i)) {
2984 if (s->mChildMask.isOn(i)) {
2985 const typename OtherInternalNode::ChildNodeType& other =
2986 *(s->mNodes[i].getChild());
2987 ChildT* child =
new ChildT(other.origin(), t->mNodes[i].getValue(),
true);
2988 child->topologyDifference(other, b);
2989 t->mNodes[i].setChild(child);
2994 const OtherInternalNode*
s;
2999template<
typename ChildT, Index Log2Dim>
3000template<
typename OtherChildT>
3012template<
typename ChildT, Index Log2Dim>
3013template<
typename CombineOp>
3021 for (
Index i = 0; i < NUM_VALUES; ++i) {
3025 op(args.
setARef(mNodes[i].getValue())
3029 mNodes[i].setValue(args.
result());
3038 }
else if (this->isChildMaskOff(i) && other.
isChildMaskOn(i)) {
3047 child->combine(mNodes[i].getValue(), isValueMaskOn(i), swappedOp);
3052 this->setChildNode(i, child);
3058 *child = mNodes[i].getChild(),
3062 if (child && otherChild) {
3063 child->combine(*otherChild, op);
3070template<
typename ChildT, Index Log2Dim>
3071template<
typename CombineOp>
3077 for (
Index i = 0; i < NUM_VALUES; ++i) {
3078 if (this->isChildMaskOff(i)) {
3080 op(args.
setARef(mNodes[i].getValue())
3083 .setBIsActive(valueIsActive));
3084 mNodes[i].setValue(args.
result());
3090 if (child) child->combine(value, valueIsActive, op);
3099template<
typename ChildT, Index Log2Dim>
3100template<
typename CombineOp,
typename OtherNodeType>
3107 for (
Index i = 0; i < NUM_VALUES; ++i) {
3111 .
setBRef(other1.mNodes[i].getValue())
3114 this->makeChildNodeEmpty(i, args.
result());
3117 if (this->isChildMaskOff(i)) {
3121 : other1.mNodes[i].getChild()->origin();
3122 this->setChildNode(i,
new ChildNodeType(childOrigin, mNodes[i].getValue()));
3130 }
else if (other1.isChildMaskOff(i)) {
3134 other1.mNodes[i].getValue(), other1.isValueMaskOn(i), op);
3139 *other1.mNodes[i].getChild(), op);
3146template<
typename ChildT, Index Log2Dim>
3147template<
typename CombineOp,
typename OtherNodeType>
3150 bool valueIsActive, CombineOp& op)
3154 for (
Index i = 0; i < NUM_VALUES; ++i) {
3155 if (other.isChildMaskOff(i)) {
3158 .
setBRef(other.mNodes[i].getValue())
3161 this->makeChildNodeEmpty(i, args.
result());
3164 typename OtherNodeType::ChildNodeType* otherChild = other.mNodes[i].getChild();
3166 if (this->isChildMaskOff(i)) {
3173 mNodes[i].getChild()->combine2(value, *otherChild, valueIsActive, op);
3179template<
typename ChildT, Index Log2Dim>
3180template<
typename CombineOp,
typename OtherValueType>
3183 bool valueIsActive, CombineOp& op)
3187 for (
Index i = 0; i < NUM_VALUES; ++i) {
3194 this->makeChildNodeEmpty(i, args.
result());
3199 if (this->isChildMaskOff(i)) {
3201 this->setChildNode(i,
3202 new ChildNodeType(otherChild->origin(), mNodes[i].getValue()));
3206 mNodes[i].getChild()->combine2(*otherChild, value, valueIsActive, op);
3215template<
typename ChildT, Index Log2Dim>
3219 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3220 iter->writeBuffers(os, toHalf);
3225template<
typename ChildT, Index Log2Dim>
3229 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3230 iter->readBuffers(is, fromHalf);
3235template<
typename ChildT, Index Log2Dim>
3238 const CoordBBox& clipBBox,
bool fromHalf)
3240 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3245 iter->readBuffers(is, clipBBox, fromHalf);
3251 background = *
static_cast<const ValueType*
>(bgPtr);
3253 this->clip(clipBBox, background);
3260template<
typename ChildT, Index Log2Dim>
3264 dims.push_back(Log2Dim);
3265 ChildNodeType::getNodeLog2Dims(dims);
3269template<
typename ChildT, Index Log2Dim>
3274 xyz.
setX(n >> 2*Log2Dim);
3275 n &= ((1<<2*Log2Dim)-1);
3276 xyz.
setY(n >> Log2Dim);
3277 xyz.
setZ(n & ((1<<Log2Dim)-1));
3281template<
typename ChildT, Index Log2Dim>
3285 return (((xyz[0] & (DIM-1u)) >> ChildNodeType::TOTAL) << 2*Log2Dim)
3286 + (((xyz[1] & (DIM-1u)) >> ChildNodeType::TOTAL) << Log2Dim)
3287 + ((xyz[2] & (DIM-1u)) >> ChildNodeType::TOTAL);
3291template<
typename ChildT, Index Log2Dim>
3296 this->offsetToLocalCoord(n, local);
3297 local <<= ChildT::TOTAL;
3298 return local + this->origin();
3305template<
typename ChildT, Index Log2Dim>
3306template<
typename ArrayT>
3310 using T =
typename ArrayT::value_type;
3311 static_assert(std::is_pointer<T>::value,
"argument to getNodes() must be a pointer array");
3312 using ArrayChildT =
typename std::conditional<
3313 std::is_const<typename std::remove_pointer<T>::type>::value,
const ChildT, ChildT>::type;
3314 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3316 if (std::is_same<T, ArrayChildT*>::value) {
3317 array.push_back(
reinterpret_cast<T
>(mNodes[iter.pos()].getChild()));
3319 iter->getNodes(array);
3325template<
typename ChildT, Index Log2Dim>
3326template<
typename ArrayT>
3330 using T =
typename ArrayT::value_type;
3331 static_assert(std::is_pointer<T>::value,
"argument to getNodes() must be a pointer array");
3332 static_assert(std::is_const<typename std::remove_pointer<T>::type>::value,
3333 "argument to getNodes() must be an array of const node pointers");
3334 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3336 if (std::is_same<T, const ChildT*>::value) {
3337 array.push_back(
reinterpret_cast<T
>(mNodes[iter.pos()].getChild()));
3339 iter->getNodes(array);
3349template<
typename ChildT, Index Log2Dim>
3350template<
typename ArrayT>
3354 using T =
typename ArrayT::value_type;
3355 static_assert(std::is_pointer<T>::value,
"argument to stealNodes() must be a pointer array");
3356 using ArrayChildT =
typename std::conditional<
3357 std::is_const<typename std::remove_pointer<T>::type>::value,
const ChildT, ChildT>::type;
3359 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3360 const Index n = iter.pos();
3361 if (std::is_same<T, ArrayChildT*>::value) {
3362 array.push_back(
reinterpret_cast<T
>(mNodes[n].getChild()));
3363 mValueMask.set(n, state);
3364 mNodes[n].setValue(value);
3366 iter->stealNodes(array, value, state);
3369 if (std::is_same<T, ArrayChildT*>::value) mChildMask.setOff();
3377template<
typename ChildT, Index Log2Dim>
3383 for (
Index i = 0; i < NUM_VALUES; ++i) {
3384 if (this->isChildMaskOn(i)) {
3385 mNodes[i].getChild()->resetBackground(oldBackground, newBackground);
3386 }
else if (this->isValueMaskOff(i)) {
3388 mNodes[i].setValue(newBackground);
3396template<
typename ChildT, Index Log2Dim>
3397template<
typename OtherChildNodeType, Index OtherLog2Dim>
3402 if (Log2Dim != OtherLog2Dim || mChildMask != other->
mChildMask ||
3403 mValueMask != other->
mValueMask)
return false;
3404 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3405 if (!iter->hasSameTopology(other->
mNodes[iter.pos()].
getChild()))
return false;
3411template<
typename ChildT, Index Log2Dim>
3416 if (this->isChildMaskOn(i)) {
3417 delete mNodes[i].getChild();
3419 mChildMask.setOn(i);
3420 mValueMask.setOff(i);
3422 mNodes[i].setChild(child);
3425template<
typename ChildT, Index Log2Dim>
3431 mChildMask.setOn(i);
3432 mValueMask.setOff(i);
3433 mNodes[i].setChild(child);
3437template<
typename ChildT, Index Log2Dim>
3441 if (this->isChildMaskOff(i)) {
3442 mNodes[i].setValue(value);
3446 mChildMask.setOff(i);
3447 mNodes[i].setValue(value);
3452template<
typename ChildT, Index Log2Dim>
3456 delete this->unsetChildNode(n, value);
3459template<
typename ChildT, Index Log2Dim>
3464 return mNodes[n].getChild();
3468template<
typename ChildT, Index Log2Dim>
3473 return mNodes[n].getChild();
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition Types.h:569
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition Types.h:621
const AValueType & result() const
Get the output value.
Definition Types.h:613
CombineArgs & setBIsActive(bool b)
Set the active state of the B value.
Definition Types.h:637
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
Definition Types.h:623
bool resultIsActive() const
Definition Types.h:632
CombineArgs & setAIsActive(bool b)
Set the active state of the A value.
Definition Types.h:635
Tag dispatch class that distinguishes constructors that deep copy.
Definition Types.h:685
Tag dispatch class that distinguishes constructors during file input.
Definition Types.h:689
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition Types.h:683
Axis-aligned bounding box of signed integer coordinates.
Definition Coord.h:252
void translate(const Coord &t)
Translate this bounding box by (tx, ty, tz).
Definition Coord.h:461
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition Coord.h:421
const Coord & min() const
Definition Coord.h:324
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition Coord.h:415
const Coord & max() const
Definition Coord.h:325
bool isInside(const Coord &xyz) const
Return true if point (x, y, z) is inside this bounding box.
Definition Coord.h:403
void intersect(const CoordBBox &bbox)
Intersect this bounding box with the given bounding box.
Definition Coord.h:447
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
Int32 y() const
Definition Coord.h:132
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition Coord.h:92
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition Coord.h:176
Int32 x() const
Definition Coord.h:131
Coord & setZ(Int32 z)
Definition Coord.h:82
Coord & setY(Int32 y)
Definition Coord.h:81
static Coord max()
Return the largest possible coordinate.
Definition Coord.h:47
static bool lessThan(const Coord &a, const Coord &b)
Definition Coord.h:209
Int32 z() const
Definition Coord.h:133
Coord & setX(Int32 x)
Definition Coord.h:80
Definition InternalNode.h:35
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition InternalNode.h:1958
ChildNodeType * getChildUnsafe(Index offset)
Return the child node at offset.
Definition InternalNode.h:2513
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Definition InternalNode.h:336
void merge(InternalNode &other, const ValueType &background, const ValueType &otherBackground)
Efficiently merge another tree into this tree using one of several schemes.
Definition InternalNode.h:2709
ChildOnCIter cbeginChildOn() const
Definition InternalNode.h:221
const ValueType & getFirstValue() const
If the first entry in this node's table is a tile, return the tile's value. Otherwise,...
Definition InternalNode.h:2474
ChildOnCIter beginChildOn() const
Definition InternalNode.h:224
const ChildNodeType * probeConstChildUnsafe(Index offset) const
Definition InternalNode.h:1426
ChildOnIter beginChildOn()
Definition InternalNode.h:227
NodeType * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists,...
const NodeType * probeNode(const Coord &xyz) const
Definition InternalNode.h:702
bool isChildMaskOff(Index n) const
Definition InternalNode.h:866
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition InternalNode.h:1758
const ValueType & getValueUnsafe(Index offset) const
Return the tile value at offset.
Definition InternalNode.h:2494
const ChildNodeType * probeChildUnsafe(Index offset, ValueType &value, bool &active) const
Definition InternalNode.h:738
void writeTopology(std::ostream &, bool toHalf=false) const
Definition InternalNode.h:2389
void copyToDense(const CoordBBox &bbox, DenseT &dense) const
Copy into a dense grid the values of the voxels that lie within a given bounding box.
Definition InternalNode.h:2344
void setChildNode(Index i, ChildNodeType *child)
Definition InternalNode.h:3427
bool isChildMaskOff() const
Definition InternalNode.h:867
ValueOffCIter cbeginValueOff() const
Definition InternalNode.h:233
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
Index32 transientData() const
Return the transient data value.
Definition InternalNode.h:273
void addLeafAndCache(LeafNodeType *leaf, AccessorT &)
Same as addLeaf() except, if necessary, update the accessor with pointers to the nodes along the path...
Definition InternalNode.h:1536
static Index getChildDim()
Definition InternalNode.h:257
const NodeMaskType & getChildMask() const
Definition InternalNode.h:869
void topologyIntersection(const InternalNode< OtherChildNodeType, Log2Dim > &other, const ValueType &background)
Intersects this tree's set of active values with the active values of the other tree,...
NodeMaskType mChildMask
Definition InternalNode.h:910
bool isValueMaskOff() const
Definition InternalNode.h:864
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition InternalNode.h:3308
bool isValueMaskOn() const
Definition InternalNode.h:862
Index64 nonLeafCount() const
Definition InternalNode.h:1149
NodeT * stealNode(const Coord &xyz, const ValueType &value, bool state)
Return a pointer to the node of type NodeT that contains voxel (x, y, z) and replace it with a tile o...
Definition InternalNode.h:1283
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition InternalNode.h:2688
NodeMaskType mValueMask
Definition InternalNode.h:910
InternalNode()
Default constructor.
Definition InternalNode.h:73
bool isChildMaskOn(Index n) const
Definition InternalNode.h:865
~InternalNode()
Definition InternalNode.h:1095
Index64 onLeafVoxelCount() const
Definition InternalNode.h:1194
const LeafNodeType * probeConstLeafAndCache(const Coord &xyz, AccessorT &acc) const
NodeMaskType getValueOffMask() const
Definition InternalNode.h:870
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition InternalNode.h:1461
ValueAllCIter cbeginValueAll() const
Definition InternalNode.h:234
void prune(const ValueType &tolerance=zeroVal< ValueType >())
Reduce the memory footprint of this tree by replacing with tiles any nodes whose values are all the s...
Definition InternalNode.h:1259
ValueOnCIter beginValueOn() const
Definition InternalNode.h:235
void setValueOnlyUnsafe(Index offset, const ValueType &value)
Set the tile value at offset but don't change its value.
Definition InternalNode.h:2547
Index64 offLeafVoxelCount() const
Definition InternalNode.h:1206
void resetBackground(const ValueType &oldBackground, const ValueType &newBackground)
Change inactive tiles or voxels with value oldBackground to newBackground or -oldBackground to -newBa...
Definition InternalNode.h:3379
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly creating a parent bran...
Definition InternalNode.h:1595
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
Definition InternalNode.h:270
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition InternalNode.h:268
bool isInactive() const
Return true if this node has no children and only contains inactive values.
Definition InternalNode.h:331
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition InternalNode.h:2136
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition InternalNode.h:1999
void combine2(const InternalNode &other0, const OtherNodeType &other1, CombineOp &)
Definition InternalNode.h:3102
friend class InternalNode
During topology-only construction, access is needed to protected/private members of other template in...
Definition InternalNode.h:857
bool isValueMaskOff(Index n) const
Definition InternalNode.h:863
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates but don't change its active state.
Definition InternalNode.h:1982
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Definition InternalNode.h:1487
void deleteChildUnsafe(Index offset, const ValueType &value, bool active)
Delete a child node at offset and replace with the given value and active state.
Definition InternalNode.h:2632
ChildNodeType * probeChild(const Coord &xyz)
Return a pointer to the child node that contains voxel (x, y, z). If no such node exists,...
Definition InternalNode.h:1385
Index getValueLevelAndCache(const Coord &xyz, AccessorT &) const
Return the level of the tree (0 = leaf) at which the value at the given coordinates resides.
Definition InternalNode.h:1820
const NodeType * probeConstNodeAndCache(const Coord &xyz, AccessorT &) const
void setActiveStateUnsafe(Index offset, bool on)
Set the tile active state at offset but don't change its value.
Definition InternalNode.h:2538
void fill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
Definition InternalNode.h:2240
ValueOffCIter beginValueOff() const
Definition InternalNode.h:237
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition InternalNode.h:1913
void addLeaf(LeafNodeType *leaf)
Add the specified leaf to this node, possibly creating a child branch in the process....
Definition InternalNode.h:1507
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
ChildAllCIter cbeginChildAll() const
Definition InternalNode.h:223
void clip(const CoordBBox &, const ValueType &background)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition InternalNode.h:2190
Index64 leafCount() const
Definition InternalNode.h:1108
ChildAllIter beginChildAll()
Definition InternalNode.h:229
static Index getLevel()
Definition InternalNode.h:250
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Definition InternalNode.h:1777
const ChildNodeType * probeChildUnsafe(Index offset) const
Definition InternalNode.h:728
void topologyDifference(const InternalNode< OtherChildNodeType, Log2Dim > &other, const ValueType &background)
Difference this node's set of active values with the active values of the other node,...
ChildNodeType * stealChildUnsafe(Index offset, const ValueType &value, bool active)
Replace a child node at offset with the given value and active state.
Definition InternalNode.h:2618
bool probeValue(const Coord &xyz, ValueType &value) const
Definition InternalNode.h:1833
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don't change its value.
Definition InternalNode.h:2020
ValueOnIter beginValueOn()
Definition InternalNode.h:239
void modifyValueAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active....
Definition InternalNode.h:2102
void topologyUnion(const InternalNode< OtherChildNodeType, Log2Dim > &other, const bool preserveTiles=false)
Union this branch's set of active values with the other branch's active values. The value type of the...
void resetChildUnsafe(Index offset, ChildNodeType *child)
Replace a child node at offset with the given child node.
Definition InternalNode.h:2606
ChildOffCIter cbeginChildOff() const
Definition InternalNode.h:222
ChildOffIter beginChildOff()
Definition InternalNode.h:228
Index64 onVoxelCount() const
Definition InternalNode.h:1170
ChildOffCIter beginChildOff() const
Definition InternalNode.h:225
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition InternalNode.h:3283
void addTileAndCache(Index level, const Coord &xyz, const ValueType &, bool state, AccessorT &)
Same as addTile() except, if necessary, update the accessor with pointers to the nodes along the path...
Definition InternalNode.h:1627
typename ChildNodeType::LeafNodeType LeafNodeType
Definition InternalNode.h:38
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition InternalNode.h:1861
NodeType * probeNodeAndCache(const Coord &xyz, AccessorT &)
Same as probeNode() except, if necessary, update the accessor with pointers to the nodes along the pa...
void writeBuffers(std::ostream &, bool toHalf=false) const
Definition InternalNode.h:3217
void nodeCount(std::vector< Index64 > &vec) const
Definition InternalNode.h:1120
ValueOnCIter cbeginValueOn() const
Definition InternalNode.h:231
typename ChildNodeType::ValueType ValueType
Definition InternalNode.h:39
const LeafNodeType * probeLeaf(const Coord &xyz) const
void setValueOnUnsafe(Index offset)
Mark the tile active at offset but don't change its value.
Definition InternalNode.h:2556
void resetChildNode(Index i, ChildNodeType *child)
Definition InternalNode.h:3413
Index32 childCount() const
Definition InternalNode.h:1162
Index getValueLevel(const Coord &xyz) const
Return the level of the tree (0 = leaf) at which the value at the given coordinates resides.
Definition InternalNode.h:1811
Index64 onTileCount() const
Definition InternalNode.h:1217
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active.
Definition InternalNode.h:2074
bool hasSameTopology(const InternalNode< OtherChildNodeType, OtherLog2Dim > *other) const
Return true if the given tree branch has the same node and active value topology as this tree branch ...
Definition InternalNode.h:3399
void setValueMask(Index n, bool on)
Definition InternalNode.h:882
Index64 offVoxelCount() const
Definition InternalNode.h:1182
typename NodeMaskType::OffIterator MaskOffIterator
Definition InternalNode.h:116
bool isConstant(ValueType &firstValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
Definition InternalNode.h:1696
LeafNodeType * touchLeaf(const Coord &xyz)
Return the leaf node that contains voxel (x, y, z). If no such node exists, create one,...
Definition InternalNode.h:1663
const ChildNodeType * getConstChildUnsafe(Index offset) const
Return the child node at offset.
Definition InternalNode.h:2522
void denseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value and ensure that those voxels are a...
Definition InternalNode.h:2296
static const Index NUM_VALUES
Definition InternalNode.h:48
UnionType mNodes[NUM_VALUES]
Definition InternalNode.h:909
void negate()
Change the sign of all the values represented in this node and its child nodes.
Definition InternalNode.h:2644
void readTopology(std::istream &, bool fromHalf=false)
Definition InternalNode.h:2414
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Definition InternalNode.h:3293
ChildAllCIter beginChildAll() const
Definition InternalNode.h:226
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Definition InternalNode.h:2039
void setValuesOn()
Mark all values (both tiles and voxels) as active.
Definition InternalNode.h:2062
void makeChildNodeEmpty(Index n, const ValueType &value)
Definition InternalNode.h:3454
void setTransientData(Index32 transientData)
Set the transient data value.
Definition InternalNode.h:275
typename ChildNodeType::BuildType BuildType
Definition InternalNode.h:40
LeafNodeType * touchLeafAndCache(const Coord &xyz, AccessorT &)
Same as touchLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
void stealNodes(ArrayT &array, const ValueType &value, bool state)
Steals all nodes of a certain type from the tree and adds them to a container with the following API:
Definition InternalNode.h:3352
ChildNodeType * getChildNode(Index n)
Returns a pointer to the child node at the linear offset n.
Definition InternalNode.h:3461
typename NodeMaskType::OnIterator MaskOnIterator
Definition InternalNode.h:115
const LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc) const
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Definition InternalNode.h:1846
bool addChild(ChildNodeType *child)
Add the given child node at this level deducing the offset from it's origin. If a child node with thi...
Definition InternalNode.h:1569
ChildNodeType * probeChildUnsafe(Index offset)
Return a pointer to the child node for a specific offset. If no such node exists, return nullptr.
Definition InternalNode.h:1417
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Expand the specified bounding box so that it includes the active tiles of this internal node as well ...
Definition InternalNode.h:1241
const ChildNodeType * probeChild(const Coord &xyz) const
Definition InternalNode.h:710
bool isEmpty() const
Definition InternalNode.h:303
const UnionType * getTable() const
Definition InternalNode.h:877
static void getNodeLog2Dims(std::vector< Index > &dims)
Populated an std::vector with the dimension of all the nodes in the branch starting with this node.
Definition InternalNode.h:3262
ValueOffIter beginValueOff()
Definition InternalNode.h:241
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition InternalNode.h:1877
const ChildNodeType * probeConstChild(const Coord &xyz) const
Definition InternalNode.h:1393
_ChildNodeType ChildNodeType
Definition InternalNode.h:37
static void offsetToLocalCoord(Index n, Coord &xyz)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0,...
Definition InternalNode.h:3271
const NodeMaskType & getValueMask() const
Definition InternalNode.h:868
const NodeType * probeConstNode(const Coord &xyz) const
bool hasActiveTiles() const
Return true if this node or any of its child nodes have any active tiles.
Definition InternalNode.h:1743
void combine(InternalNode &other, CombineOp &)
Definition InternalNode.h:3015
void setChildUnsafe(Index offset, ChildNodeType *child)
Replace a tile at offset with the given child node.
Definition InternalNode.h:2594
const ValueType & getValue(const Coord &xyz) const
Definition InternalNode.h:1788
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
Definition InternalNode.h:1228
bool isValueOff(const Coord &xyz) const
Return true if the voxel at the given coordinates is inactive.
Definition InternalNode.h:1767
void setValueOffUnsafe(Index offset)
Mark the tile inactive at offset but don't change its value.
Definition InternalNode.h:2575
ChildNodeType * unsetChildNode(Index i, const ValueType &value)
Definition InternalNode.h:3439
const ChildNodeType * probeChild(const Coord &xyz, ValueType &value, bool &active) const
Definition InternalNode.h:718
void readBuffers(std::istream &, bool fromHalf=false)
Definition InternalNode.h:3227
typename NodeMaskType::DenseIterator MaskDenseIterator
Definition InternalNode.h:117
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition InternalNode.h:2159
bool isValueOff(Index offset) const
Return true if the voxel at the given offset is inactive.
Definition InternalNode.h:340
ValueAllCIter beginValueAll() const
Definition InternalNode.h:238
Coord mOrigin
Global grid index coordinates (x,y,z) of the local origin of this node.
Definition InternalNode.h:912
static Index dim()
Definition InternalNode.h:247
bool isValueMaskOn(Index n) const
Definition InternalNode.h:861
ValueAllIter beginValueAll()
Definition InternalNode.h:242
const ValueType & getLastValue() const
If the last entry in this node's table is a tile, return the tile's value. Otherwise,...
Definition InternalNode.h:2482
Base class for iterators over internal and leaf nodes.
Definition Iterator.h:30
const ValueT & getValue() const
Definition NodeUnion.h:43
ChildT * getChild() const
Definition NodeUnion.h:40
void setValue(const ValueT &val)
Definition NodeUnion.h:45
Definition NodeMasks.h:271
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation.
Definition NodeMasks.h:308
Index64 Word
Definition NodeMasks.h:316
void toggle(Index32 n)
Toggle the state of the nth bit.
Definition NodeMasks.h:483
void setOff(Index32 n)
Set the nth bit off.
Definition NodeMasks.h:457
void setOn(Index32 n)
Set the nth bit on.
Definition NodeMasks.h:452
Definition NodeMasks.h:240
Definition NodeMasks.h:209
void writeCompressedValues(std::ostream &os, ValueT *srcBuf, Index srcCount, const MaskT &valueMask, const MaskT &childMask, bool toHalf)
Definition Compression.h:646
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
void readCompressedValues(std::istream &is, ValueT *destBuf, Index destCount, const MaskT &valueMask, bool fromHalf)
Definition Compression.h:466
OPENVDB_API const void * getGridBackgroundValuePtr(std::ios_base &)
Return a pointer to the background value of the grid currently being read from or written to the give...
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
Definition Math.h:406
T negative(const T &val)
Return the unary negation of the given value.
Definition Math.h:128
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition Math.h:443
Index32 Index
Definition Types.h:54
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:70
uint32_t Index32
Definition Types.h:52
@ OPENVDB_FILE_VERSION_NODE_MASK_COMPRESSION
Definition version.h.in:262
@ OPENVDB_FILE_VERSION_INTERNALNODE_COMPRESSION
Definition version.h.in:253
int32_t Int32
Definition Types.h:56
uint64_t Index64
Definition Types.h:53
@ MERGE_ACTIVE_STATES
Definition Types.h:507
@ MERGE_NODES
Definition Types.h:508
@ MERGE_ACTIVE_STATES_AND_NODES
Definition Types.h:509
Definition Exceptions.h:13
Base class for dense iterators over internal and leaf nodes.
Definition Iterator.h:179
typename std::remove_const< UnsetItemT >::type NonConstValueType
Definition Iterator.h:184
Definition InternalNode.h:130
ChildIter(const MaskIterT &iter, NodeT *parent)
Definition InternalNode.h:132
ChildIter()
Definition InternalNode.h:131
ChildT & getItem(Index pos) const
Definition InternalNode.h:135
void setItem(Index pos, const ChildT &c) const
Definition InternalNode.h:142
Definition InternalNode.h:121
Definition InternalNode.h:121
Definition InternalNode.h:974
DeepCopy(const OtherInternalNode *source, InternalNode *target)
Definition InternalNode.h:975
InternalNode * t
Definition InternalNode.h:989
const OtherInternalNode * s
Definition InternalNode.h:988
void operator()(const tbb::blocked_range< Index > &r) const
Definition InternalNode.h:979
Definition InternalNode.h:173
DenseIter(const MaskDenseIterator &iter, NodeT *parent)
Definition InternalNode.h:178
void unsetItem(Index pos, const ValueT &value) const
Definition InternalNode.h:199
void setItem(Index pos, ChildT *child) const
Definition InternalNode.h:193
DenseIter()
Definition InternalNode.h:177
bool getItem(Index pos, ChildT *&child, NonConstValueT &value) const
Definition InternalNode.h:181
typename BaseT::NonConstValueType NonConstValueT
Definition InternalNode.h:175
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of an Intern...
Definition InternalNode.h:65
Definition InternalNode.h:1020
TopologyCopy1(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition InternalNode.h:1021
InternalNode * t
Definition InternalNode.h:1037
const OtherInternalNode * s
Definition InternalNode.h:1036
const ValueType & b
Definition InternalNode.h:1038
void operator()(const tbb::blocked_range< Index > &r) const
Definition InternalNode.h:1026
Definition InternalNode.h:1057
const ValueType & offV
Definition InternalNode.h:1075
TopologyCopy2(const OtherInternalNode *source, InternalNode *target, const ValueType &offValue, const ValueType &onValue)
Definition InternalNode.h:1058
InternalNode * t
Definition InternalNode.h:1074
const OtherInternalNode * s
Definition InternalNode.h:1073
void operator()(const tbb::blocked_range< Index > &r) const
Definition InternalNode.h:1063
Definition InternalNode.h:2953
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
Definition InternalNode.h:2953
Definition InternalNode.h:2956
void operator()(W &tV, const W &sC, const W &sV, const W &tC) const
Definition InternalNode.h:2956
Definition InternalNode.h:2951
TopologyDifference(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition InternalNode.h:2959
typename NodeMaskType::Word W
Definition InternalNode.h:2952
InternalNode * t
Definition InternalNode.h:2995
const OtherInternalNode * s
Definition InternalNode.h:2994
const ValueType & b
Definition InternalNode.h:2996
void operator()(const tbb::blocked_range< Index > &r) const
Definition InternalNode.h:2973
Definition InternalNode.h:2903
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
Definition InternalNode.h:2903
Definition InternalNode.h:2901
TopologyIntersection(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition InternalNode.h:2906
typename NodeMaskType::Word W
Definition InternalNode.h:2902
InternalNode * t
Definition InternalNode.h:2935
const OtherInternalNode * s
Definition InternalNode.h:2934
const ValueType & b
Definition InternalNode.h:2936
void operator()(const tbb::blocked_range< Index > &r) const
Definition InternalNode.h:2918
Definition InternalNode.h:2851
void operator()(W &tV, const W &sV, const W &tC) const
Definition InternalNode.h:2851
Definition InternalNode.h:2849
typename NodeMaskType::Word W
Definition InternalNode.h:2850
InternalNode * t
Definition InternalNode.h:2886
const bool mPreserveTiles
Definition InternalNode.h:2887
const OtherInternalNode * s
Definition InternalNode.h:2885
void operator()(const tbb::blocked_range< Index > &r) const
Definition InternalNode.h:2867
TopologyUnion(const OtherInternalNode *source, InternalNode *target, const bool preserveTiles)
Definition InternalNode.h:2854
ValueConverter<T>::Type is the type of an InternalNode having the same child hierarchy and dimensions...
Definition InternalNode.h:56
Definition InternalNode.h:151
void modifyItem(Index pos, const ModifyOp &op) const
Definition InternalNode.h:163
ValueIter(const MaskIterT &iter, NodeT *parent)
Definition InternalNode.h:153
const ValueT & getItem(Index pos) const
Definition InternalNode.h:156
ValueIter()
Definition InternalNode.h:152
void setItem(Index pos, const ValueT &v) const
Definition InternalNode.h:159
Definition InternalNode.h:120
Definition InternalNode.h:120
Definition InternalNode.h:2662
InternalNode * mNode
Definition InternalNode.h:2683
void operator()(const tbb::blocked_range< Index > &r) const
Definition InternalNode.h:2670
VoxelizeActiveTiles(InternalNode &node)
Definition InternalNode.h:2663
Definition InternalNode.h:925
Base class for sparse iterators over internal and leaf nodes.
Definition Iterator.h:115
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218