8 #ifndef OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
9 #define OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
20 #include <tbb/parallel_for.h>
22 #include <type_traits>
33 template<
typename _ChildNodeType, Index Log2Dim>
46 TOTAL = Log2Dim + ChildNodeType::TOTAL,
49 LEVEL = 1 + ChildNodeType::LEVEL;
55 template<
typename OtherValueType>
64 template<
typename OtherNodeType>
95 template<
typename OtherChildNodeType>
101 template<
typename OtherChildNodeType>
108 template<
typename OtherChildNodeType>
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));
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) {}
162 template<
typename ModifyOp>
170 template<
typename NodeT,
typename ChildT,
typename ValueT,
typename TagT>
172 MaskDenseIterator, DenseIter<NodeT, ChildT, ValueT, TagT>, NodeT, ChildT, ValueT>
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);
279 void nodeCount(std::vector<Index64> &vec)
const;
311 const ValueType& tolerance = zeroVal<ValueType>())
const;
328 bool& state,
const ValueType& tolerance = zeroVal<ValueType>())
const;
374 template<
typename ModifyOp>
377 template<
typename ModifyOp>
384 template<
typename AccessorT>
391 template<
typename AccessorT>
398 template<
typename AccessorT>
405 template<
typename AccessorT>
413 template<
typename ModifyOp,
typename AccessorT>
420 template<
typename ModifyOp,
typename AccessorT>
427 template<
typename AccessorT>
434 template<
typename AccessorT>
442 template<
typename AccessorT>
451 template<
typename AccessorT>
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);
583 template<
typename DenseT>
588 template<MergePolicy Policy>
593 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive);
607 template<
typename OtherChildNodeType>
623 template<
typename OtherChildNodeType>
638 template<
typename OtherChildNodeType>
642 template<
typename CombineOp>
644 template<
typename CombineOp>
647 template<
typename CombineOp,
typename OtherNodeType >
649 template<
typename CombineOp,
typename OtherNodeType >
651 template<
typename CombineOp,
typename OtherValueType>
668 template<
typename AccessorT>
679 template<
typename NodeT>
699 template<
typename AccessorT>
705 template<
typename NodeType> NodeType*
probeNode(
const Coord& xyz);
706 template<
typename NodeType>
const NodeType*
probeConstNode(
const Coord& xyz)
const;
707 template<
typename NodeType>
const NodeType*
probeNode(
const Coord& xyz)
const {
return this->probeConstNode<NodeType>(xyz); }
749 template<
typename NodeType,
typename AccessorT>
751 template<
typename NodeType,
typename AccessorT>
766 template<
typename AccessorT>
768 template<
typename AccessorT>
770 template<
typename AccessorT>
784 template<
typename AccessorT>
810 template<
typename ArrayT>
812 template<
typename ArrayT>
839 template<
typename ArrayT>
848 template<
typename OtherChildNodeType, Index OtherLog2Dim>
905 struct VoxelizeActiveTiles;
906 template<
typename OtherInternalNode>
struct DeepCopy;
929 template<
typename ChildT1, Index Dim1,
typename NodeT2>
934 template<
typename ChildT1, Index Dim1,
typename ChildT2>
944 template<
typename ChildT, Index Log2Dim>
948 for (
Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(background);
952 template<
typename ChildT, Index Log2Dim>
955 mOrigin(origin[0] & ~(DIM - 1),
956 origin[1] & ~(DIM - 1),
957 origin[2] & ~(DIM - 1))
966 template<
typename ChildT, Index Log2Dim>
970 : mOrigin(origin[0] & ~(DIM-1), origin[1] & ~(DIM-1), origin[2] & ~(DIM-1))
976 template<
typename ChildT, Index Log2Dim>
977 template<
typename OtherInternalNode>
985 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
986 if (
s->mChildMask.isOff(i)) {
987 t->mNodes[i].setValue(
ValueType(
s->mNodes[i].getValue()));
993 const OtherInternalNode*
s;
997 template<
typename ChildT, Index Log2Dim>
1000 : mChildMask(other.mChildMask)
1002 , mOrigin(other.mOrigin)
1003 , mTransientData(other.mTransientData)
1010 template<
typename ChildT, Index Log2Dim>
1011 template<
typename OtherChildNodeType>
1014 : mChildMask(other.mChildMask)
1016 , mOrigin(other.mOrigin)
1017 , mTransientData(other.mTransientData)
1022 template<
typename ChildT, Index Log2Dim>
1023 template<
typename OtherInternalNode>
1027 const ValueType& background) :
s(source),
t(target),
b(background) {
1032 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
1033 if (
s->isChildMaskOn(i)) {
1037 t->mNodes[i].setValue(
b);
1041 const OtherInternalNode*
s;
1046 template<
typename ChildT, Index Log2Dim>
1047 template<
typename OtherChildNodeType>
1051 : mChildMask(other.mChildMask)
1053 , mOrigin(other.mOrigin)
1054 , mTransientData(other.mTransientData)
1059 template<
typename ChildT, Index Log2Dim>
1060 template<
typename OtherInternalNode>
1065 :
s(source),
t(target), offV(offValue), onV(onValue) {
1069 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
1070 if (
s->isChildMaskOn(i)) {
1074 t->mNodes[i].setValue(
s->isValueMaskOn(i) ? onV : offV);
1078 const OtherInternalNode*
s;
1083 template<
typename ChildT, Index Log2Dim>
1084 template<
typename OtherChildNodeType>
1089 : mChildMask(other.mChildMask)
1091 , mOrigin(other.mOrigin)
1092 , mTransientData(other.mTransientData)
1098 template<
typename ChildT, Index Log2Dim>
1102 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1103 delete mNodes[iter.pos()].getChild();
1111 template<
typename ChildT, Index Log2Dim>
1117 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1118 sum += iter->leafCount();
1123 template<
typename ChildT, Index Log2Dim>
1128 const auto count = mChildMask.countOn();
1129 if (ChildNodeType::LEVEL > 0 && count > 0) {
1130 for (
auto iter = this->cbeginChildOn(); iter; ++iter) iter->nodeCount(vec);
1132 vec[ChildNodeType::LEVEL] += count;
1135 template<
typename ChildT, Index Log2Dim>
1140 const auto count = mChildMask.countOn();
1141 if (ChildNodeType::LEVEL > 0 && count > 0) {
1142 for (
auto iter = this->cbeginChildOn(); iter; ++iter) {
1144 iter->nodeCount(vec);
1148 vec[ChildNodeType::LEVEL] += count;
1152 template<
typename ChildT, Index Log2Dim>
1158 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1159 sum += iter->nonLeafCount();
1165 template<
typename ChildT, Index Log2Dim>
1169 return this->getChildMask().countOn();
1173 template<
typename ChildT, Index Log2Dim>
1178 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1179 sum += iter->onVoxelCount();
1185 template<
typename ChildT, Index Log2Dim>
1189 Index64 sum = ChildT::NUM_VOXELS * (NUM_VALUES-
mValueMask.countOn()-mChildMask.countOn());
1190 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1191 sum += iter->offVoxelCount();
1197 template<
typename ChildT, Index Log2Dim>
1202 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1203 sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount();
1209 template<
typename ChildT, Index Log2Dim>
1214 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1215 sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount();
1220 template<
typename ChildT, Index Log2Dim>
1225 for (
ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) {
1226 sum += iter->onTileCount();
1231 template<
typename ChildT, Index Log2Dim>
1237 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1238 sum += iter->memUsage();
1244 template<
typename ChildT, Index Log2Dim>
1248 if (bbox.isInside(
this->getNodeBoundingBox()))
return;
1251 bbox.expand(i.getCoord(), ChildT::DIM);
1254 i->evalActiveBoundingBox(bbox, visitVoxels);
1262 template<
typename ChildT, Index Log2Dim>
1268 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1269 const Index i = iter.pos();
1270 ChildT* child = mNodes[i].getChild();
1271 child->prune(tolerance);
1272 if (child->isConstant(value, state, tolerance)) {
1274 mChildMask.setOff(i);
1276 mNodes[i].setValue(value);
1285 template<
typename ChildT, Index Log2Dim>
1286 template<
typename NodeT>
1291 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1293 const Index n = this->coordToOffset(xyz);
1294 if (mChildMask.isOff(n))
return nullptr;
1295 ChildT* child = mNodes[
n].getChild();
1297 mChildMask.setOff(n);
1299 mNodes[
n].setValue(value);
1302 ?
reinterpret_cast<NodeT*
>(child)
1303 : child->template stealNode<NodeT>(xyz, value, state);
1311 template<
typename ChildT, Index Log2Dim>
1312 template<
typename NodeT>
1317 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1319 const Index n = this->coordToOffset(xyz);
1320 if (mChildMask.isOff(n))
return nullptr;
1321 ChildT* child = mNodes[
n].getChild();
1323 ?
reinterpret_cast<NodeT*
>(child)
1324 : child->template probeNode<NodeT>(xyz);
1329 template<
typename ChildT, Index Log2Dim>
1330 template<
typename NodeT,
typename AccessorT>
1335 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1337 const Index n = this->coordToOffset(xyz);
1338 if (mChildMask.isOff(n))
return nullptr;
1339 ChildT* child = mNodes[
n].getChild();
1340 acc.insert(xyz, child);
1342 ?
reinterpret_cast<NodeT*
>(child)
1343 : child->template probeNodeAndCache<NodeT>(xyz, acc);
1348 template<
typename ChildT, Index Log2Dim>
1349 template<
typename NodeT>
1354 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1356 const Index n = this->coordToOffset(xyz);
1357 if (mChildMask.isOff(n))
return nullptr;
1358 const ChildT* child = mNodes[
n].getChild();
1360 ?
reinterpret_cast<const NodeT*
>(child)
1361 : child->template probeConstNode<NodeT>(xyz);
1366 template<
typename ChildT, Index Log2Dim>
1367 template<
typename NodeT,
typename AccessorT>
1372 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1374 const Index n = this->coordToOffset(xyz);
1375 if (mChildMask.isOff(n))
return nullptr;
1376 const ChildT* child = mNodes[
n].getChild();
1377 acc.insert(xyz, child);
1379 ?
reinterpret_cast<const NodeT*
>(child)
1380 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
1388 template<
typename ChildT, Index Log2Dim>
1392 const Index n = this->coordToOffset(xyz);
1393 return this->probeChildUnsafe(n);
1396 template<
typename ChildT, Index Log2Dim>
1397 inline const ChildT*
1400 const Index n = this->coordToOffset(xyz);
1401 return this->probeConstChildUnsafe(n);
1404 template<
typename ChildT, Index Log2Dim>
1408 const Index n = this->coordToOffset(xyz);
1409 return this->probeChildUnsafe(n, value, active);
1412 template<
typename ChildT, Index Log2Dim>
1413 inline const ChildT*
1416 const Index n = this->coordToOffset(xyz);
1417 return this->probeConstChildUnsafe(n, value, active);
1420 template<
typename ChildT, Index Log2Dim>
1425 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1429 template<
typename ChildT, Index Log2Dim>
1430 inline const ChildT*
1434 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1438 template<
typename ChildT, Index Log2Dim>
1443 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1444 value = mNodes[
offset].getValue();
1449 template<
typename ChildT, Index Log2Dim>
1450 inline const ChildT*
1454 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1455 value = mNodes[
offset].getValue();
1464 template<
typename ChildT, Index Log2Dim>
1465 inline typename ChildT::LeafNodeType*
1468 return this->
template probeNode<LeafNodeType>(xyz);
1472 template<
typename ChildT, Index Log2Dim>
1473 template<
typename AccessorT>
1474 inline typename ChildT::LeafNodeType*
1477 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
1481 template<
typename ChildT, Index Log2Dim>
1482 template<
typename AccessorT>
1483 inline const typename ChildT::LeafNodeType*
1486 return this->probeConstLeafAndCache(xyz, acc);
1490 template<
typename ChildT, Index Log2Dim>
1491 inline const typename ChildT::LeafNodeType*
1494 return this->
template probeConstNode<LeafNodeType>(xyz);
1498 template<
typename ChildT, Index Log2Dim>
1499 template<
typename AccessorT>
1500 inline const typename ChildT::LeafNodeType*
1503 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
1510 template<
typename ChildT, Index Log2Dim>
1515 const Coord& xyz = leaf->origin();
1516 const Index n = this->coordToOffset(xyz);
1517 ChildT* child =
nullptr;
1518 if (mChildMask.isOff(n)) {
1519 if (ChildT::LEVEL>0) {
1522 child =
reinterpret_cast<ChildT*
>(leaf);
1524 this->setChildNode(n, child);
1526 if (ChildT::LEVEL>0) {
1527 child = mNodes[
n].getChild();
1529 delete mNodes[
n].getChild();
1530 child =
reinterpret_cast<ChildT*
>(leaf);
1531 mNodes[
n].setChild(child);
1534 child->addLeaf(leaf);
1538 template<
typename ChildT, Index Log2Dim>
1539 template<
typename AccessorT>
1544 const Coord& xyz = leaf->origin();
1545 const Index n = this->coordToOffset(xyz);
1546 ChildT* child =
nullptr;
1547 if (mChildMask.isOff(n)) {
1548 if (ChildT::LEVEL>0) {
1550 acc.insert(xyz, child);
1552 child =
reinterpret_cast<ChildT*
>(leaf);
1554 this->setChildNode(n, child);
1556 if (ChildT::LEVEL>0) {
1557 child = mNodes[
n].getChild();
1558 acc.insert(xyz, child);
1560 delete mNodes[
n].getChild();
1561 child =
reinterpret_cast<ChildT*
>(leaf);
1562 mNodes[
n].setChild(child);
1565 child->addLeafAndCache(leaf, acc);
1572 template<
typename ChildT, Index Log2Dim>
1577 const Coord& xyz = child->origin();
1579 if (Coord((xyz & ~(DIM-1))) != this->origin())
return false;
1581 const Index n = this->coordToOffset(xyz);
1583 this->resetChildNode(n, child);
1588 template<
typename ChildT, Index Log2Dim>
1593 this->makeChildNodeEmpty(n, value);
1598 template<
typename ChildT, Index Log2Dim>
1603 if (LEVEL >= level) {
1604 const Index n = this->coordToOffset(xyz);
1605 if (mChildMask.isOff(n)) {
1606 if (LEVEL > level) {
1608 this->setChildNode(n, child);
1609 child->addTile(level, xyz, value, state);
1612 mNodes[
n].setValue(value);
1615 ChildT* child = mNodes[
n].getChild();
1616 if (LEVEL > level) {
1617 child->addTile(level, xyz, value, state);
1620 mChildMask.setOff(n);
1622 mNodes[
n].setValue(value);
1629 template<
typename ChildT, Index Log2Dim>
1630 template<
typename AccessorT>
1635 if (LEVEL >= level) {
1636 const Index n = this->coordToOffset(xyz);
1637 if (mChildMask.isOff(n)) {
1638 if (LEVEL > level) {
1640 this->setChildNode(n, child);
1641 acc.insert(xyz, child);
1642 child->addTileAndCache(level, xyz, value, state, acc);
1645 mNodes[
n].setValue(value);
1648 ChildT* child = mNodes[
n].getChild();
1649 if (LEVEL > level) {
1650 acc.insert(xyz, child);
1651 child->addTileAndCache(level, xyz, value, state, acc);
1654 mChildMask.setOff(n);
1656 mNodes[
n].setValue(value);
1666 template<
typename ChildT, Index Log2Dim>
1667 inline typename ChildT::LeafNodeType*
1670 const Index n = this->coordToOffset(xyz);
1671 ChildT* child =
nullptr;
1672 if (mChildMask.isOff(n)) {
1674 this->setChildNode(n, child);
1676 child = mNodes[
n].getChild();
1678 return child->touchLeaf(xyz);
1682 template<
typename ChildT, Index Log2Dim>
1683 template<
typename AccessorT>
1684 inline typename ChildT::LeafNodeType*
1687 const Index
n = this->coordToOffset(xyz);
1688 if (mChildMask.isOff(n)) {
1691 acc.insert(xyz, mNodes[n].getChild());
1692 return mNodes[
n].getChild()->touchLeafAndCache(xyz, acc);
1699 template<
typename ChildT, Index Log2Dim>
1704 if (!mChildMask.isOff() || !
mValueMask.isConstant(state))
return false;
1706 firstValue = mNodes[0].getValue();
1707 for (
Index i = 1; i < NUM_VALUES; ++i) {
1719 template<
typename ChildT, Index Log2Dim>
1727 if (!mChildMask.isOff() || !
mValueMask.isConstant(state))
return false;
1728 minValue = maxValue = mNodes[0].getValue();
1729 for (
Index i = 1; i < NUM_VALUES; ++i) {
1732 if ((maxValue - v) > tolerance)
return false;
1734 }
else if (v > maxValue) {
1735 if ((v - minValue) > tolerance)
return false;
1746 template<
typename ChildT, Index Log2Dim>
1753 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1754 if (iter->hasActiveTiles())
return true;
1761 template<
typename ChildT, Index Log2Dim>
1765 const Index n = this->coordToOffset(xyz);
1766 return this->isChildMaskOff(n) ? this->isValueMaskOn(n)
1767 : mNodes[
n].getChild()->isValueOn(xyz);
1770 template<
typename ChildT, Index Log2Dim>
1774 const Index n = this->coordToOffset(xyz);
1775 return this->isChildMaskOff(n) ? this->isValueMaskOn(n)
1776 : mNodes[
n].getChild()->isValueOff(xyz);
1779 template<
typename ChildT, Index Log2Dim>
1780 template<
typename AccessorT>
1784 const Index n = this->coordToOffset(xyz);
1785 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1786 acc.insert(xyz, mNodes[n].getChild());
1787 return mNodes[
n].getChild()->isValueOnAndCache(xyz, acc);
1791 template<
typename ChildT, Index Log2Dim>
1795 const Index n = this->coordToOffset(xyz);
1796 return this->isChildMaskOff(n) ? mNodes[
n].getValue()
1797 : mNodes[
n].getChild()->getValue(xyz);
1800 template<
typename ChildT, Index Log2Dim>
1801 template<
typename AccessorT>
1805 const Index
n = this->coordToOffset(xyz);
1806 if (this->isChildMaskOn(n)) {
1807 acc.insert(xyz, mNodes[n].getChild());
1808 return mNodes[
n].getChild()->getValueAndCache(xyz, acc);
1810 return mNodes[
n].getValue();
1814 template<
typename ChildT, Index Log2Dim>
1818 const Index n = this->coordToOffset(xyz);
1819 return this->isChildMaskOff(n) ? LEVEL : mNodes[
n].getChild()->getValueLevel(xyz);
1822 template<
typename ChildT, Index Log2Dim>
1823 template<
typename AccessorT>
1827 const Index n = this->coordToOffset(xyz);
1828 if (this->isChildMaskOn(n)) {
1829 acc.insert(xyz, mNodes[n].getChild());
1830 return mNodes[
n].getChild()->getValueLevelAndCache(xyz, acc);
1836 template<
typename ChildT, Index Log2Dim>
1840 const Index n = this->coordToOffset(xyz);
1841 if (this->isChildMaskOff(n)) {
1842 value = mNodes[
n].getValue();
1843 return this->isValueMaskOn(n);
1845 return mNodes[
n].getChild()->probeValue(xyz, value);
1848 template<
typename ChildT, Index Log2Dim>
1849 template<
typename AccessorT>
1854 const Index n = this->coordToOffset(xyz);
1855 if (this->isChildMaskOn(n)) {
1856 acc.insert(xyz, mNodes[n].getChild());
1857 return mNodes[
n].getChild()->probeValueAndCache(xyz, value, acc);
1859 value = mNodes[
n].getValue();
1860 return this->isValueMaskOn(n);
1864 template<
typename ChildT, Index Log2Dim>
1868 const Index n = this->coordToOffset(xyz);
1869 bool hasChild = this->isChildMaskOn(n);
1870 if (!hasChild && this->isValueMaskOn(n)) {
1876 if (hasChild) mNodes[
n].getChild()->setValueOff(xyz);
1880 template<
typename ChildT, Index Log2Dim>
1884 const Index n = this->coordToOffset(xyz);
1885 bool hasChild = this->isChildMaskOn(n);
1886 if (!hasChild && !this->isValueMaskOn(n)) {
1892 if (hasChild) mNodes[
n].getChild()->setValueOn(xyz);
1896 template<
typename ChildT, Index Log2Dim>
1901 bool hasChild = this->isChildMaskOn(n);
1903 const bool active = this->isValueMaskOn(n);
1912 if (hasChild) mNodes[
n].getChild()->setValueOff(xyz, value);
1915 template<
typename ChildT, Index Log2Dim>
1916 template<
typename AccessorT>
1922 bool hasChild = this->isChildMaskOn(n);
1924 const bool active = this->isValueMaskOn(n);
1934 ChildT* child = mNodes[
n].getChild();
1935 acc.insert(xyz, child);
1936 child->setValueOffAndCache(xyz, value, acc);
1941 template<
typename ChildT, Index Log2Dim>
1945 const Index n = this->coordToOffset(xyz);
1946 bool hasChild = this->isChildMaskOn(n);
1948 const bool active = this->isValueMaskOn(n);
1957 if (hasChild) mNodes[
n].getChild()->setValueOn(xyz, value);
1960 template<
typename ChildT, Index Log2Dim>
1961 template<
typename AccessorT>
1966 const Index n = this->coordToOffset(xyz);
1967 bool hasChild = this->isChildMaskOn(n);
1969 const bool active = this->isValueMaskOn(n);
1979 acc.insert(xyz, mNodes[n].getChild());
1980 mNodes[
n].getChild()->setValueAndCache(xyz, value, acc);
1985 template<
typename ChildT, Index Log2Dim>
1989 const Index n = this->coordToOffset(xyz);
1990 bool hasChild = this->isChildMaskOn(n);
1994 const bool active = this->isValueMaskOn(n);
1998 if (hasChild) mNodes[
n].getChild()->setValueOnly(xyz, value);
2001 template<
typename ChildT, Index Log2Dim>
2002 template<
typename AccessorT>
2007 const Index n = this->coordToOffset(xyz);
2008 bool hasChild = this->isChildMaskOn(n);
2012 const bool active = this->isValueMaskOn(n);
2017 acc.insert(xyz, mNodes[n].getChild());
2018 mNodes[
n].getChild()->setValueOnlyAndCache(xyz, value, acc);
2023 template<
typename ChildT, Index Log2Dim>
2027 const Index n = this->coordToOffset(xyz);
2028 bool hasChild = this->isChildMaskOn(n);
2030 if (on != this->isValueMaskOn(n)) {
2038 if (hasChild) mNodes[
n].getChild()->setActiveState(xyz, on);
2041 template<
typename ChildT, Index Log2Dim>
2042 template<
typename AccessorT>
2046 const Index n = this->coordToOffset(xyz);
2047 bool hasChild = this->isChildMaskOn(n);
2049 if (on != this->isValueMaskOn(n)) {
2058 ChildT* child = mNodes[
n].getChild();
2059 acc.insert(xyz, child);
2060 child->setActiveStateAndCache(xyz, on, acc);
2065 template<
typename ChildT, Index Log2Dim>
2070 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2071 mNodes[iter.pos()].getChild()->setValuesOn();
2076 template<
typename ChildT, Index Log2Dim>
2077 template<
typename ModifyOp>
2082 bool hasChild = this->isChildMaskOn(n);
2086 const bool active = this->isValueMaskOn(n);
2087 bool createChild = !
active;
2091 const ValueType& tileVal = mNodes[
n].getValue();
2101 if (hasChild) mNodes[
n].getChild()->modifyValue(xyz, op);
2104 template<
typename ChildT, Index Log2Dim>
2105 template<
typename ModifyOp,
typename AccessorT>
2111 bool hasChild = this->isChildMaskOn(n);
2115 const bool active = this->isValueMaskOn(n);
2116 bool createChild = !
active;
2120 const ValueType& tileVal = mNodes[
n].getValue();
2132 acc.insert(xyz, child);
2133 child->modifyValueAndCache(xyz, op, acc);
2138 template<
typename ChildT, Index Log2Dim>
2139 template<
typename ModifyOp>
2144 bool hasChild = this->isChildMaskOn(n);
2146 const bool tileState = this->isValueMaskOn(n);
2147 const ValueType& tileVal = mNodes[
n].getValue();
2148 bool modifiedState = !tileState;
2150 op(modifiedVal, modifiedState);
2155 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
2158 if (hasChild) mNodes[
n].getChild()->modifyValueAndActiveState(xyz, op);
2161 template<
typename ChildT, Index Log2Dim>
2162 template<
typename ModifyOp,
typename AccessorT>
2165 const Coord& xyz,
const ModifyOp&
op, AccessorT& acc)
2168 bool hasChild = this->isChildMaskOn(n);
2170 const bool tileState = this->isValueMaskOn(n);
2171 const ValueType& tileVal = mNodes[
n].getValue();
2172 bool modifiedState = !tileState;
2174 op(modifiedVal, modifiedState);
2179 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
2184 acc.insert(xyz, child);
2185 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
2193 template<
typename ChildT, Index Log2Dim>
2197 CoordBBox nodeBBox = this->getNodeBoundingBox();
2198 if (!clipBBox.hasOverlap(nodeBBox)) {
2200 this->
fill(nodeBBox, background,
false);
2201 }
else if (clipBBox.isInside(nodeBBox)) {
2210 for (
Index pos = 0; pos < NUM_VALUES; ++pos) {
2211 const Coord xyz = this->offsetToGlobalCoord(pos);
2212 CoordBBox tileBBox(xyz, xyz.offsetBy(ChildT::DIM - 1));
2213 if (!clipBBox.hasOverlap(tileBBox)) {
2216 this->makeChildNodeEmpty(pos, background);
2218 }
else if (!clipBBox.isInside(tileBBox)) {
2221 if (this->isChildMaskOn(pos)) {
2222 mNodes[pos].getChild()->clip(clipBBox, background);
2226 tileBBox.intersect(clipBBox);
2228 const bool on = this->isValueMaskOn(pos);
2229 mNodes[pos].setValue(background);
2231 this->
fill(tileBBox, val, on);
2243 template<
typename ChildT, Index Log2Dim>
2247 auto clippedBBox = this->getNodeBoundingBox();
2248 clippedBBox.intersect(bbox);
2249 if (!clippedBBox)
return;
2253 Coord xyz, tileMin, tileMax;
2254 for (
int x = clippedBBox.min().x();
x <= clippedBBox.max().x();
x = tileMax.x() + 1) {
2256 for (
int y = clippedBBox.min().y();
y <= clippedBBox.max().y();
y = tileMax.y() + 1) {
2258 for (
int z = clippedBBox.min().z();
z <= clippedBBox.max().z();
z = tileMax.z() + 1) {
2262 const Index n = this->coordToOffset(xyz);
2263 tileMin = this->offsetToGlobalCoord(n);
2264 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2266 if (xyz != tileMin || Coord::lessThan(clippedBBox.max(), tileMax)) {
2270 ChildT* child =
nullptr;
2271 if (this->isChildMaskOff(n)) {
2274 child =
new ChildT{xyz, mNodes[
n].getValue(), this->isValueMaskOn(n)};
2275 this->setChildNode(n, child);
2277 child = mNodes[
n].getChild();
2283 child->fill(
CoordBBox(xyz, tmp), value, active);
2290 this->makeChildNodeEmpty(n, value);
2299 template<
typename ChildT, Index Log2Dim>
2303 auto clippedBBox = this->getNodeBoundingBox();
2304 clippedBBox.intersect(bbox);
2305 if (!clippedBBox)
return;
2309 Coord xyz, tileMin, tileMax;
2310 for (
int x = clippedBBox.min().x();
x <= clippedBBox.max().x();
x = tileMax.x() + 1) {
2312 for (
int y = clippedBBox.min().y();
y <= clippedBBox.max().y();
y = tileMax.y() + 1) {
2314 for (
int z = clippedBBox.min().z();
z <= clippedBBox.max().z();
z = tileMax.z() + 1) {
2318 const auto n = this->coordToOffset(xyz);
2321 ChildT* child =
nullptr;
2322 if (this->isChildMaskOn(
n)) {
2323 child = mNodes[
n].getChild();
2327 child =
new ChildT{xyz, mNodes[
n].getValue(), this->isValueMaskOn(
n)};
2328 this->setChildNode(
n, child);
2332 tileMin = this->offsetToGlobalCoord(
n);
2333 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2346 template<
typename ChildT, Index Log2Dim>
2347 template<
typename DenseT>
2353 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2354 const Coord&
min = dense.bbox().min();
2355 for (Coord xyz = bbox.min(),
max; xyz[0] <= bbox.max()[0]; xyz[0] =
max[0] + 1) {
2356 for (xyz[1] = bbox.min()[1]; xyz[1] <= bbox.max()[1]; xyz[1] =
max[1] + 1) {
2357 for (xyz[2] = bbox.min()[2]; xyz[2] <= bbox.max()[2]; xyz[2] =
max[2] + 1) {
2358 const Index n = this->coordToOffset(xyz);
2360 max = this->offsetToGlobalCoord(n).offsetBy(ChildT::DIM-1);
2365 if (this->isChildMaskOn(n)) {
2366 mNodes[
n].getChild()->copyToDense(sub, dense);
2369 sub.translate(-min);
2370 DenseValueType* a0 = dense.data() + zStride*sub.min()[2];
2371 for (
Int32 x=sub.min()[0], ex=sub.max()[0]+1;
x<ex; ++
x) {
2372 DenseValueType* a1 = a0 +
x*xStride;
2373 for (
Int32 y=sub.min()[1], ey=sub.max()[1]+1;
y<ey; ++
y) {
2374 DenseValueType* a2 = a1 +
y*yStride;
2375 for (
Int32 z = sub.min()[2], ez = sub.max()[2]+1;
2376 z < ez; ++
z, a2 += zStride)
2378 *a2 = DenseValueType(value);
2392 template<
typename ChildT, Index Log2Dim>
2396 mChildMask.save(os);
2401 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[NUM_VALUES]);
2403 const ValueType zero = zeroVal<ValueType>();
2404 for (
Index i = 0; i < NUM_VALUES; ++i) {
2405 values[i] = (mChildMask.isOff(i) ? mNodes[i].getValue() : zero);
2411 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2412 iter->writeTopology(os, toHalf);
2417 template<
typename ChildT, Index Log2Dim>
2426 mChildMask.load(is);
2429 const bool oldVersion =
2431 const Index numValues = (oldVersion ? mChildMask.countOff() : NUM_VALUES);
2435 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[numValues]);
2442 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2443 mNodes[iter.pos()].setValue(values[n++]);
2447 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2448 mNodes[iter.pos()].setValue(values[iter.pos()]);
2454 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2456 mNodes[iter.pos()].setChild(child);
2457 child->readTopology(is, fromHalf);
2465 template<
typename ChildT, Index Log2Dim>
2469 return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].
getValue());
2473 template<
typename ChildT, Index Log2Dim>
2477 const Index n = NUM_VALUES - 1;
2478 return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].
getValue());
2485 template<
typename ChildT, Index Log2Dim>
2491 return mNodes[
n].getValue();
2494 template<
typename ChildT, Index Log2Dim>
2500 value = mNodes[
n].getValue();
2504 template<
typename ChildT, Index Log2Dim>
2510 return mNodes[
n].getChild();
2513 template<
typename ChildT, Index Log2Dim>
2514 inline const ChildT*
2519 return mNodes[
n].getChild();
2522 template<
typename ChildT, Index Log2Dim>
2523 inline const ChildT*
2526 return this->getConstChildUnsafe(n);
2529 template<
typename ChildT, Index Log2Dim>
2538 template<
typename ChildT, Index Log2Dim>
2544 mNodes[
n].setValue(value);
2547 template<
typename ChildT, Index Log2Dim>
2556 template<
typename ChildT, Index Log2Dim>
2562 mNodes[
n].setValue(value);
2566 template<
typename ChildT, Index Log2Dim>
2575 template<
typename ChildT, Index Log2Dim>
2581 mNodes[
n].setValue(value);
2585 template<
typename ChildT, Index Log2Dim>
2593 template<
typename ChildT, Index Log2Dim>
2600 mNodes[
n].setChild(child);
2601 mChildMask.setOn(n);
2605 template<
typename ChildT, Index Log2Dim>
2613 delete mNodes[
n].getChild();
2614 mNodes[
n].setChild(child);
2617 template<
typename ChildT, Index Log2Dim>
2624 auto* child = mNodes[
n].getChild();
2625 mChildMask.setOff(n);
2627 mNodes[
n].setValue(value);
2631 template<
typename ChildT, Index Log2Dim>
2636 delete this->stealChildUnsafe(n, value, active);
2643 template<
typename ChildT, Index Log2Dim>
2647 for (
Index i = 0; i < NUM_VALUES; ++i) {
2648 if (this->isChildMaskOn(i)) {
2649 mNodes[i].getChild()->negate();
2661 template<
typename ChildT, Index Log2Dim>
2673 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
2674 if (mNode->mChildMask.isOn(i)) {
2675 mNode->mNodes[i].getChild()->voxelizeActiveTiles(
true);
2676 }
else if (mNode->mValueMask.isOn(i)) {
2677 const Coord &ijk = mNode->offsetToGlobalCoord(i);
2679 child->voxelizeActiveTiles(
true);
2680 mNode->mNodes[i].setChild(child);
2687 template<
typename ChildT, Index Log2Dim>
2694 for (
ValueOnIter iter = this->beginValueOn(); iter; ++iter) {
2695 this->setChildNode(iter.pos(),
2698 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter)
2699 iter->voxelizeActiveTiles(
false);
2707 template<
typename ChildT, Index Log2Dim>
2708 template<MergePolicy Policy>
2721 const Index n = iter.pos();
2722 if (mChildMask.isOn(n)) {
2724 mNodes[
n].getChild()->template merge<MERGE_ACTIVE_STATES>(*iter,
2725 background, otherBackground);
2733 child->resetBackground(otherBackground, background);
2734 this->setChildNode(n, child);
2740 const Index n = iter.pos();
2743 this->makeChildNodeEmpty(n, iter.getValue());
2753 const Index n = iter.pos();
2754 if (mChildMask.isOn(n)) {
2756 mNodes[
n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2764 child->resetBackground(otherBackground, background);
2765 this->setChildNode(n, child);
2775 const Index n = iter.pos();
2776 if (mChildMask.isOn(n)) {
2778 mNodes[
n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2785 child->resetBackground(otherBackground, background);
2788 child->template merge<Policy>(mNodes[
n].getValue(),
true);
2791 mChildMask.setOn(n);
2792 mNodes[
n].setChild(child);
2798 const Index n = iter.pos();
2799 if (mChildMask.isOn(n)) {
2801 mNodes[
n].getChild()->template merge<Policy>(iter.getValue(),
true);
2804 mNodes[
n].setValue(iter.getValue());
2816 template<
typename ChildT, Index Log2Dim>
2817 template<MergePolicy Policy>
2826 if (!tileActive)
return;
2829 for (
ValueOffIter iter = this->beginValueOff(); iter; ++iter) {
2830 const Index n = iter.pos();
2831 if (mChildMask.isOn(n)) {
2833 mNodes[
n].getChild()->template merge<Policy>(tileValue,
true);
2836 iter.setValue(tileValue);
2847 template<
typename ChildT, Index Log2Dim>
2848 template<
typename OtherInternalNode>
2853 { tV = (tV | sV) & ~tC; }
2856 :
s(source),
t(target), mPreserveTiles(preserveTiles) {
2861 if (!mPreserveTiles)
t->mChildMask |=
s->mChildMask;
2862 else t->mChildMask |= (
s->mChildMask & !
t->mValueMask);
2865 t->mValueMask.foreach(
s->mValueMask,
t->mChildMask, op);
2869 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
2870 if (
s->mChildMask.isOn(i)) {
2871 const typename OtherInternalNode::ChildNodeType& other = *(
s->mNodes[i].getChild());
2872 if (
t->mChildMask.isOn(i)) {
2873 t->mNodes[i].getChild()->topologyUnion(other, mPreserveTiles);
2875 if (!mPreserveTiles ||
t->mValueMask.isOff(i)) {
2876 ChildT* child =
new ChildT(other,
t->mNodes[i].getValue(),
TopologyCopy());
2877 if (
t->mValueMask.isOn(i)) child->setValuesOn();
2878 t->mNodes[i].setChild(child);
2881 }
else if (
s->mValueMask.isOn(i) &&
t->mChildMask.isOn(i)) {
2882 t->mNodes[i].getChild()->setValuesOn();
2886 const OtherInternalNode*
s;
2891 template<
typename ChildT, Index Log2Dim>
2892 template<
typename OtherChildT>
2899 template<
typename ChildT, Index Log2Dim>
2900 template<
typename OtherInternalNode>
2901 struct InternalNode<ChildT, Log2Dim>::TopologyIntersection
2905 { tC = (tC & (sC | sV)) | (tV & sC); }
2908 const ValueType& background) :
s(source),
t(target),
b(background) {
2914 t->mChildMask.foreach(
s->mChildMask,
s->mValueMask,
t->mValueMask, op);
2916 t->mValueMask &=
s->mValueMask;
2920 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
2921 if (
t->mChildMask.isOn(i)) {
2922 ChildT* child =
t->mNodes[i].getChild();
2923 if (
s->mChildMask.isOn(i)) {
2924 child->topologyIntersection(*(
s->mNodes[i].getChild()),
b);
2925 }
else if (
s->mValueMask.isOff(i)) {
2927 t->mNodes[i].setValue(
b);
2929 }
else if (
t->mValueMask.isOn(i) &&
s->mChildMask.isOn(i)) {
2930 t->mNodes[i].setChild(
new ChildT(*(
s->mNodes[i].getChild()),
2935 const OtherInternalNode*
s;
2940 template<
typename ChildT, Index Log2Dim>
2941 template<
typename OtherChildT>
2949 template<
typename ChildT, Index Log2Dim>
2950 template<
typename OtherInternalNode>
2951 struct InternalNode<ChildT, Log2Dim>::TopologyDifference
2955 { tC = (tC & (sC | ~sV)) | (tV & sC); }
2958 { tV &= ~((tC & sV) | (sC | sV)); }
2961 const ValueType& background) :
s(source),
t(target),
b(background) {
2968 t->mChildMask.foreach(
s->mChildMask,
s->mValueMask,
t->mValueMask, op1);
2971 t->mValueMask.foreach(
t->mChildMask,
s->mValueMask, oldChildMask, op2);
2975 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
2976 if (
t->mChildMask.isOn(i)) {
2977 ChildT* child =
t->mNodes[i].getChild();
2978 if (
s->mChildMask.isOn(i)) {
2979 child->topologyDifference(*(
s->mNodes[i].getChild()),
b);
2980 }
else if (
s->mValueMask.isOn(i)) {
2982 t->mNodes[i].setValue(
b);
2984 }
else if (
t->mValueMask.isOn(i)) {
2985 if (
s->mChildMask.isOn(i)) {
2986 const typename OtherInternalNode::ChildNodeType& other =
2987 *(
s->mNodes[i].getChild());
2988 ChildT* child =
new ChildT(other.origin(),
t->mNodes[i].getValue(),
true);
2989 child->topologyDifference(other,
b);
2990 t->mNodes[i].setChild(child);
2995 const OtherInternalNode*
s;
3000 template<
typename ChildT, Index Log2Dim>
3001 template<
typename OtherChildT>
3013 template<
typename ChildT, Index Log2Dim>
3014 template<
typename CombineOp>
3018 const ValueType zero = zeroVal<ValueType>();
3022 for (
Index i = 0; i < NUM_VALUES; ++i) {
3026 op(args.setARef(mNodes[i].getValue())
3027 .setAIsActive(isValueMaskOn(i))
3030 mNodes[i].setValue(args.result());
3039 }
else if (this->isChildMaskOff(i) && other.
isChildMaskOn(i)) {
3048 child->combine(mNodes[i].
getValue(), isValueMaskOn(i), swappedOp);
3053 this->setChildNode(i, child);
3059 *child = mNodes[i].getChild(),
3063 if (child && otherChild) {
3064 child->combine(*otherChild, op);
3071 template<
typename ChildT, Index Log2Dim>
3072 template<
typename CombineOp>
3078 for (
Index i = 0; i < NUM_VALUES; ++i) {
3079 if (this->isChildMaskOff(i)) {
3082 .setAIsActive(isValueMaskOn(i))
3084 .setBIsActive(valueIsActive));
3085 mNodes[i].setValue(args.
result());
3091 if (child) child->combine(value, valueIsActive, op);
3100 template<
typename ChildT, Index Log2Dim>
3101 template<
typename CombineOp,
typename OtherNodeType>
3108 for (
Index i = 0; i < NUM_VALUES; ++i) {
3112 .setBRef(other1.mNodes[i].getValue())
3113 .setBIsActive(other1.isValueMaskOn(i)));
3115 this->makeChildNodeEmpty(i, args.
result());
3118 if (this->isChildMaskOff(i)) {
3122 : other1.mNodes[i].getChild()->origin();
3131 }
else if (other1.isChildMaskOff(i)) {
3135 other1.mNodes[i].getValue(), other1.isValueMaskOn(i),
op);
3140 *other1.mNodes[i].getChild(),
op);
3147 template<
typename ChildT, Index Log2Dim>
3148 template<
typename CombineOp,
typename OtherNodeType>
3151 bool valueIsActive, CombineOp&
op)
3155 for (
Index i = 0; i < NUM_VALUES; ++i) {
3156 if (other.isChildMaskOff(i)) {
3158 .setAIsActive(valueIsActive)
3159 .setBRef(other.mNodes[i].getValue())
3160 .setBIsActive(other.isValueMaskOn(i)));
3162 this->makeChildNodeEmpty(i, args.
result());
3165 typename OtherNodeType::ChildNodeType* otherChild = other.mNodes[i].getChild();
3167 if (this->isChildMaskOff(i)) {
3174 mNodes[i].getChild()->combine2(value, *otherChild, valueIsActive, op);
3180 template<
typename ChildT, Index Log2Dim>
3181 template<
typename CombineOp,
typename OtherValueType>
3184 bool valueIsActive, CombineOp&
op)
3188 for (
Index i = 0; i < NUM_VALUES; ++i) {
3193 .setBIsActive(valueIsActive));
3195 this->makeChildNodeEmpty(i, args.
result());
3200 if (this->isChildMaskOff(i)) {
3202 this->setChildNode(i,
3203 new ChildNodeType(otherChild->origin(), mNodes[i].getValue()));
3207 mNodes[i].getChild()->combine2(*otherChild, value, valueIsActive, op);
3216 template<
typename ChildT, Index Log2Dim>
3220 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3221 iter->writeBuffers(os, toHalf);
3226 template<
typename ChildT, Index Log2Dim>
3230 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3231 iter->readBuffers(is, fromHalf);
3236 template<
typename ChildT, Index Log2Dim>
3239 const CoordBBox& clipBBox,
bool fromHalf)
3241 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3246 iter->readBuffers(is, clipBBox, fromHalf);
3250 ValueType background = zeroVal<ValueType>();
3252 background = *
static_cast<const ValueType*
>(bgPtr);
3254 this->
clip(clipBBox, background);
3261 template<
typename ChildT, Index Log2Dim>
3265 dims.push_back(Log2Dim);
3266 ChildNodeType::getNodeLog2Dims(dims);
3270 template<
typename ChildT, Index Log2Dim>
3275 xyz.setX(n >> 2*Log2Dim);
3276 n &= ((1<<2*Log2Dim)-1);
3277 xyz.setY(n >> Log2Dim);
3278 xyz.setZ(n & ((1<<Log2Dim)-1));
3282 template<
typename ChildT, Index Log2Dim>
3286 return (((xyz[0] & (DIM-1u)) >> ChildNodeType::TOTAL) << 2*Log2Dim)
3287 + (((xyz[1] & (DIM-1u)) >> ChildNodeType::TOTAL) << Log2Dim)
3288 + ((xyz[2] & (DIM-1u)) >> ChildNodeType::TOTAL);
3292 template<
typename ChildT, Index Log2Dim>
3297 this->offsetToLocalCoord(n, local);
3298 local <<= ChildT::TOTAL;
3299 return local + this->origin();
3306 template<
typename ChildT, Index Log2Dim>
3307 template<
typename ArrayT>
3313 using ArrayChildT =
typename std::conditional<
3315 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3318 array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild()));
3320 iter->getNodes(array);
3326 template<
typename ChildT, Index Log2Dim>
3327 template<
typename ArrayT>
3334 "argument to getNodes() must be an array of const node pointers");
3335 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3338 array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild()));
3340 iter->getNodes(array);
3350 template<
typename ChildT, Index Log2Dim>
3351 template<
typename ArrayT>
3357 using ArrayChildT =
typename std::conditional<
3360 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3361 const Index n = iter.pos();
3363 array.push_back(reinterpret_cast<T>(mNodes[n].getChild()));
3365 mNodes[
n].setValue(value);
3367 iter->stealNodes(array, value, state);
3378 template<
typename ChildT, Index Log2Dim>
3384 for (
Index i = 0; i < NUM_VALUES; ++i) {
3385 if (this->isChildMaskOn(i)) {
3386 mNodes[i].getChild()->resetBackground(oldBackground, newBackground);
3387 }
else if (this->isValueMaskOff(i)) {
3389 mNodes[i].setValue(newBackground);
3397 template<
typename ChildT, Index Log2Dim>
3398 template<
typename OtherChildNodeType, Index OtherLog2Dim>
3403 if (Log2Dim != OtherLog2Dim || mChildMask != other->
mChildMask ||
3405 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3406 if (!iter->hasSameTopology(other->
mNodes[iter.pos()].getChild()))
return false;
3412 template<
typename ChildT, Index Log2Dim>
3417 if (this->isChildMaskOn(i)) {
3418 delete mNodes[i].getChild();
3420 mChildMask.setOn(i);
3423 mNodes[i].setChild(child);
3426 template<
typename ChildT, Index Log2Dim>
3432 mChildMask.setOn(i);
3434 mNodes[i].setChild(child);
3438 template<
typename ChildT, Index Log2Dim>
3442 if (this->isChildMaskOff(i)) {
3443 mNodes[i].setValue(value);
3447 mChildMask.setOff(i);
3448 mNodes[i].setValue(value);
3453 template<
typename ChildT, Index Log2Dim>
3457 delete this->unsetChildNode(n, value);
3460 template<
typename ChildT, Index Log2Dim>
3465 return mNodes[
n].getChild();
3469 template<
typename ChildT, Index Log2Dim>
3470 inline const ChildT*
3474 return mNodes[
n].getChild();
3481 #endif // OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
bool probeValue(const Coord &xyz, ValueType &value) const
const AValueType & result() const
Get the output value.
void setItem(Index pos, ChildT *child) const
Vec2< T > minComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise minimum of the two vectors.
void negate()
Change the sign of all the values represented in this node and its child nodes.
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
void combine(InternalNode &other, CombineOp &)
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
ValueIter< InternalNode, const ValueType, MaskOffIterator, ValueAll > ValueAllIter
void operator()(const tbb::blocked_range< Index > &r) const
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 setItem(Index pos, const ValueT &v) const
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
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...
const OtherInternalNode * s
NodeType * probeNodeAndCache(const Coord &xyz, AccessorT &)
Same as probeNode() except, if necessary, update the accessor with pointers to the nodes along the pa...
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
ChildIter< InternalNode, ChildNodeType, MaskOnIterator, ChildOn > ChildOnIter
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
ChildOnCIter cbeginChildOn() const
Index64 onVoxelCount() const
TopologyDifference(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
ChildT * getChild() const
static const Index NUM_VALUES
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
ValueOnIter beginValueOn()
Index64 offLeafVoxelCount() const
T negative(const T &val)
Return the unary negation of the given value.
typename NodeMaskType::Word W
const ChildNodeType * probeChild(const Coord &xyz, ValueType &value, bool &active) const
Return a pointer to the 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 child node that contains voxel (x, y, z). If no such node exists...
void clip(const CoordBBox &, const ValueType &background)
Set all voxels that lie outside the given axis-aligned box to the background.
const OtherInternalNode * s
ValueIter< InternalNode, const ValueType, MaskOffIterator, ValueOff > ValueOffIter
ChildOffIter beginChildOff()
GLsizei const GLfloat * value
const NodeMaskType & getChildMask() const
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...
bool isValueMaskOff(Index n) const
void setOff(Index32 n)
Set the nth bit off.
GLdouble GLdouble GLdouble z
Index pos() const
Identical to offset.
ValueOffIter beginValueOff()
void nodeCount(std::vector< Index64 > &vec) const
const ChildNodeType * probeConstChild(const Coord &xyz) const
Return a pointer to the child node that contains voxel (x, y, z). If no such node exists...
const NodeType * probeConstNode(const Coord &xyz) const
Return a pointer to the node that contains voxel (x, y, z). If no such node exists, return nullptr.
TopologyUnion(const OtherInternalNode *source, InternalNode *target, const bool preserveTiles)
void setChildNode(Index i, ChildNodeType *child)
void setValueOffUnsafe(Index offset)
Mark the tile inactive at offset but don't change its value.
#define OPENVDB_USE_VERSION_NAMESPACE
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
typename NodeMaskType::OnIterator MaskOnIterator
void toggle(Index32 n)
Toggle the state of the nth bit.
Base class for iterators over internal and leaf nodes.
const ChildNodeType * getConstChildUnsafe(Index offset) const
Return the child node at offset.
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...
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...
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
ValueConverter<T>::Type is the type of an InternalNode having the same child hierarchy and dimensions...
**But if you need a or simply need to know when the task has note that the like this
void writeTopology(std::ostream &, bool toHalf=false) const
UnionType mNodes[NUM_VALUES]
bool hasActiveTiles() const
Return true if this node or any of its child nodes have any active tiles.
DenseIterator beginDense() const
void operator()(W &tV, const W &sC, const W &sV, const W &tC) const
typename ChildNodeType::LeafNodeType LeafNodeType
const ChildNodeType * probeConstChildUnsafe(Index offset) const
Return a pointer to the child node for a specific offset. If no such node exists, return nullptr...
typename NodeMaskType::Word W
Index64 nonLeafCount() const
typename NodeMaskType::Word W
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...
bool isValueOff(Index offset) const
Return true if the voxel at the given offset is inactive.
Index64 onTileCount() const
typename BaseT::NonConstValueType NonConstValueT
NodeT & parent() const
Return a reference to the node over which this iterator is iterating.
const OtherInternalNode * s
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
typename ChildNodeType::BuildType BuildType
bool isConstant(ValueType &firstValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) 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.
bool getItem(Index pos, ChildT *&child, NonConstValueT &value) const
DenseIter(const MaskDenseIterator &iter, NodeT *parent)
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
void operator()(const tbb::blocked_range< Index > &r) const
NodeMaskType getValueOffMask() const
Tag dispatch class that distinguishes constructors during file input.
typename NodeMaskType::DenseIterator MaskDenseIterator
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
const ValueType & getFirstValue() const
If the first entry in this node's table is a tile, return the tile's value. Otherwise, return the result of calling getFirstValue() on the child.
OPENVDB_API void checkFormatVersion(std::ios_base &)
Throws an IoError if the file format version number is not supported.
static const Index64 NUM_VOXELS
const ValueType & getValueUnsafe(Index offset) const
Return the tile value at offset.
ChildNodeType * probeChildUnsafe(Index offset)
Return a pointer to the child node for a specific offset. If no such node exists, return nullptr...
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
typename NodeMaskType::OffIterator MaskOffIterator
__hostdev__ float getValue(uint32_t i) const
ChildNodeType * getChildNode(Index n)
Returns a pointer to the child node at the linear offset n.
ChildIter< const InternalNode, const ChildNodeType, MaskOnIterator, ChildOn > ChildOnCIter
DeepCopy(const OtherInternalNode *source, InternalNode *target)
bool isInactive() const
Return true if this node has no children and only contains inactive values.
void operator()(const tbb::blocked_range< Index > &r) const
#define OPENVDB_ASSERT(X)
void readCompressedValues(std::istream &is, ValueT *destBuf, Index destCount, const MaskT &valueMask, bool fromHalf)
void setValueMask(Index n, bool on)
void writeCompressedValues(std::ostream &os, const ValueT *srcBuf, Index srcCount, const MaskT &valueMask, const MaskT &childMask, bool toHalf)
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
ChildT & getItem(Index pos) const
void setValuesOn()
Mark all values (both tiles and voxels) as active.
ValueAllIter beginValueAll()
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 setValue(const ValueT &val)
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
typename ChildNodeType::ValueType ValueType
ChildAllCIter beginChildAll() const
OffMaskIterator< NodeMask > OffIterator
void setValueOnlyUnsafe(Index offset, const ValueType &value)
Set the tile value at offset but don't change its value.
const ChildNodeType * probeChildUnsafe(Index offset) const
Return a pointer to the child node for a specific offset. If no such node exists, return nullptr...
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...
Index32 mTransientData
Transient data (not serialized)
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.
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
void setValueMaskUnsafe(const NodeMaskType &mask)
Set the active/inactive value mask.
void operator()(const tbb::blocked_range< Index > &r) const
ValueAllCIter cbeginValueAll() const
bool isChildMaskOff() const
bool isValueMaskOn(Index n) const
bool isChildMaskOn(Index n) const
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.
Index64 offVoxelCount() const
const LeafNodeType * probeConstLeafAndCache(const Coord &xyz, AccessorT &acc) const
Same as probeLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
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, whose ValueType may be different.
bool isOn(Index32 n) const
Return true if the nth bit is on.
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
void makeChildNodeEmpty(Index n, const ValueType &value)
ChildNodeType * probeChild(const Coord &xyz)
Return a pointer to the child node that contains voxel (x, y, z). If no such node exists...
const NodeType * probeNode(const Coord &xyz) const
Return a pointer to the node that contains voxel (x, y, z). If no such node exists, return nullptr.
bool resultIsActive() const
void fill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
const NodeMaskType & getValueMask() const
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
ValueIter< const InternalNode, const ValueType, MaskOffIterator, ValueAll > ValueAllCIter
GLsizei GLsizei GLchar * source
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
void deleteChildUnsafe(Index offset, const ValueType &value, bool active)
Delete a child node at offset and replace with the given value and active state.
OIIO_UTIL_API void parallel_for(int32_t begin, int32_t end, function_view< void(int32_t)> task, paropt opt=0)
void setTransientData(Index32 transientData)
Set the transient data value.
void resetChildNode(Index i, ChildNodeType *child)
_ChildNodeType ChildNodeType
void unsetItem(Index pos, const ValueT &value) const
void operator()(const tbb::blocked_range< Index > &r) const
ChildNodeType * unsetChildNode(Index i, const ValueType &value)
void operator()(const tbb::blocked_range< Index > &r) const
LeafNodeType * touchLeaf(const Coord &xyz)
Return the leaf node that contains voxel (x, y, z). If no such node exists, create one...
const ValueT & getItem(Index pos) const
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
bool isValueMaskOff() const
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 ...
void set(Index32 n, bool On)
Set the nth bit to the specified state.
OnIterator beginOn() const
typename std::remove_const< UnsetItemT >::type NonConstValueType
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
void setOn(Index32 n)
Set the nth bit on.
ValueAllCIter beginValueAll() const
Index getValueLevelAndCache(const Coord &xyz, AccessorT &) const
Return the level of the tree (0 = leaf) at which the value at the given coordinates resides...
ValueIter< const InternalNode, const ValueType, MaskOnIterator, ValueOn > ValueOnCIter
void writeBuffers(std::ostream &, bool toHalf=false) const
const ChildNodeType * probeChildUnsafe(Index offset, ValueType &value, bool &active) const
Return a pointer to the child node for a specific offset. If no such node exists, return nullptr...
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
void modifyItem(Index pos, const ModifyOp &op) const
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...
void setActiveStateUnsafe(Index offset, bool on)
Set the tile active state at offset but don't change its value.
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...
void resetChildUnsafe(Index offset, ChildNodeType *child)
Replace a child node at offset with the given child node.
GLboolean GLboolean GLboolean b
Index32 childCount() const
ChildNodeType * stealChildUnsafe(Index offset, const ValueType &value, bool active)
Replace a child node at offset with the given value and active state.
ValueIter< const InternalNode, const ValueType, MaskOffIterator, ChildOff > ChildOffCIter
Index64 onLeafVoxelCount() const
OffIterator beginOff() const
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by the node regardless of it...
that also have some descendant prim *whose name begins with which in turn has a child named baz where *the predicate active
MaskT< LOG2DIM > mValueMask
TopologyCopy1(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
DenseIter< InternalNode, ChildNodeType, ValueType, ChildAll > ChildAllIter
Index32 transientData() const
Return the transient data value.
ValueOnCIter cbeginValueOn() const
Base class for sparse iterators over internal and leaf nodes.
void merge(InternalNode &other, const ValueType &background, const ValueType &otherBackground)
Efficiently merge another tree into this tree using one of several schemes.
const NodeType * probeConstNodeAndCache(const Coord &xyz, AccessorT &) const
Same as probeNode() except, if necessary, update the accessor with pointers to the nodes along the pa...
static Index getChildDim()
ChildNodeType * getChildUnsafe(Index offset)
Return the child node at offset.
ChildOnCIter beginChildOn() const
const ValueType & getLastValue() const
If the last entry in this node's table is a tile, return the tile's value. Otherwise, return the result of calling getLastValue() on the child.
Base class for dense iterators over internal and leaf nodes.
bool isValueOff(const Coord &xyz) const
Return true if the voxel at the given coordinates is inactive.
InternalNode< typename ChildNodeType::template ValueConverter< OtherValueType >::Type, Log2Dim > Type
ValueOffCIter beginValueOff() const
void operator()(W &tV, const W &sV, const W &tC) const
DenseMaskIterator< NodeMask > DenseIterator
Library and file format version numbers.
void setValueOnUnsafe(Index offset)
Mark the tile active at offset but don't change its value.
ChildOffCIter cbeginChildOff() const
GLenum GLsizei GLsizei GLint * values
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don't change its value.
ValueIter< InternalNode, const ValueType, MaskOffIterator, ChildOff > ChildOffIter
static const Index LOG2DIM
void readTopology(std::istream &, bool fromHalf=false)
ChildOnIter beginChildOn()
void addLeaf(LeafNodeType *leaf)
Add the specified leaf to this node, possibly creating a child branch in the process. If the leaf node already exists, replace it.
VoxelizeActiveTiles(InternalNode &node)
void resetBackground(const ValueType &oldBackground, const ValueType &newBackground)
Change inactive tiles or voxels with value oldBackground to newBackground or -oldBackground to -newBa...
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
void setItem(Index pos, const ChildT &c) const
OnMaskIterator< NodeMask > OnIterator
void operator()(const tbb::blocked_range< Index > &r) const
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
Index64 leafCount() const
const ValueType & getValue(const Coord &xyz) const
const OtherInternalNode * s
**If you just want to fire and args
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
void setChildUnsafe(Index offset, ChildNodeType *child)
Replace a tile at offset with the given child node.
static void offsetToLocalCoord(Index n, Coord &xyz)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0...
util::NodeMask< Log2Dim > NodeMaskType
ChildOffCIter beginChildOff() const
TopologyCopy2(const OtherInternalNode *source, InternalNode *target, const ValueType &offValue, const ValueType &onValue)
void combine2(const InternalNode &other0, const OtherNodeType &other1, CombineOp &)
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of an Internal...
Index getValueLevel(const Coord &xyz) const
Return the level of the tree (0 = leaf) at which the value at the given coordinates resides...
InternalNode()
Default constructor.
Tag dispatch class that distinguishes constructors that deep copy.
NodeType * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists, return nullptr.
void addLeafAndCache(LeafNodeType *leaf, AccessorT &)
Same as addLeaf() except, if necessary, update the accessor with pointers to the nodes along the path...
ChildAllCIter cbeginChildAll() const
ValueIter(const MaskIterT &iter, NodeT *parent)
ValueIter< InternalNode, const ValueType, MaskOnIterator, ValueOn > ValueOnIter
const bool mPreserveTiles
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.
const OtherInternalNode * s
ValueT & getValue() const
Return the item to which this iterator is pointing.
const ValueT & getValue() const
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.
ChildIter(const MaskIterT &iter, NodeT *parent)
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T clip(const T &p, const Box< T > &box) IMATH_NOEXCEPT
DenseIter< const InternalNode, const ChildNodeType, ValueType, ChildAll > ChildAllCIter
Coord mOrigin
Global grid index coordinates (x,y,z) of the local origin of this node.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
TopologyIntersection(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
ValueOnCIter beginValueOn() const
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
bool isChildMaskOff(Index n) const
void readBuffers(std::istream &, bool fromHalf=false)
const UnionType * getTable() const
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...
LeafNodeType * touchLeafAndCache(const Coord &xyz, AccessorT &)
Same as touchLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
const OtherInternalNode * s
ValueOffCIter cbeginValueOff() const
ValueIter< const InternalNode, const ValueType, MaskOffIterator, ValueOff > ValueOffCIter
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, whose ValueType may be different. So a resulting voxel will be active only if the original voxel is active in this node and inactive in the other node.
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...
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 ...
bool isOff(Index32 n) const
Return true if the nth bit is off.
ChildAllIter beginChildAll()
bool isValueMaskOn() const