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);
578 template<
typename DenseT>
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>
642 template<
typename CombineOp,
typename OtherNodeType >
644 template<
typename CombineOp,
typename OtherNodeType >
646 template<
typename CombineOp,
typename OtherValueType>
663 template<
typename AccessorT>
674 template<
typename NodeT>
694 template<
typename AccessorT>
700 template<
typename NodeType> NodeType*
probeNode(
const Coord& xyz);
701 template<
typename NodeType>
const NodeType*
probeConstNode(
const Coord& xyz)
const;
702 template<
typename NodeType>
const NodeType*
probeNode(
const Coord& xyz)
const {
return this->probeConstNode<NodeType>(xyz); }
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>
807 template<
typename ArrayT>
834 template<
typename ArrayT>
843 template<
typename OtherChildNodeType, Index OtherLog2Dim>
900 struct VoxelizeActiveTiles;
901 template<
typename OtherInternalNode>
struct DeepCopy;
924 template<
typename ChildT1, Index Dim1,
typename NodeT2>
929 template<
typename ChildT1, Index Dim1,
typename ChildT2>
939 template<
typename ChildT, Index Log2Dim>
943 for (
Index i = 0; i < NUM_VALUES; ++i) mNodes[i].
setValue(background);
947 template<
typename ChildT, Index Log2Dim>
950 mOrigin(origin[0] & ~(DIM - 1),
951 origin[1] & ~(DIM - 1),
952 origin[2] & ~(DIM - 1))
961 template<
typename ChildT, Index Log2Dim>
965 : mOrigin(origin[0] & ~(DIM-1), origin[1] & ~(DIM-1), origin[2] & ~(DIM-1))
971 template<
typename ChildT, Index Log2Dim>
972 template<
typename OtherInternalNode>
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()));
988 const OtherInternalNode*
s;
992 template<
typename ChildT, Index Log2Dim>
995 : mChildMask(other.mChildMask)
997 , mOrigin(other.mOrigin)
998 , mTransientData(other.mTransientData)
1005 template<
typename ChildT, Index Log2Dim>
1006 template<
typename OtherChildNodeType>
1009 : mChildMask(other.mChildMask)
1011 , mOrigin(other.mOrigin)
1012 , mTransientData(other.mTransientData)
1017 template<
typename ChildT, Index Log2Dim>
1018 template<
typename OtherInternalNode>
1022 const ValueType& background) :
s(source),
t(target),
b(background) {
1027 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
1028 if (
s->isChildMaskOn(i)) {
1032 t->mNodes[i].setValue(
b);
1036 const OtherInternalNode*
s;
1041 template<
typename ChildT, Index Log2Dim>
1042 template<
typename OtherChildNodeType>
1046 : mChildMask(other.mChildMask)
1048 , mOrigin(other.mOrigin)
1049 , mTransientData(other.mTransientData)
1054 template<
typename ChildT, Index Log2Dim>
1055 template<
typename OtherInternalNode>
1060 :
s(source),
t(target), offV(offValue), onV(onValue) {
1064 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
1065 if (
s->isChildMaskOn(i)) {
1069 t->mNodes[i].setValue(
s->isValueMaskOn(i) ? onV : offV);
1073 const OtherInternalNode*
s;
1078 template<
typename ChildT, Index Log2Dim>
1079 template<
typename OtherChildNodeType>
1084 : mChildMask(other.mChildMask)
1086 , mOrigin(other.mOrigin)
1087 , mTransientData(other.mTransientData)
1093 template<
typename ChildT, Index Log2Dim>
1097 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1098 delete mNodes[iter.pos()].getChild();
1106 template<
typename ChildT, Index Log2Dim>
1112 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1113 sum += iter->leafCount();
1118 template<
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;
1130 template<
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;
1147 template<
typename ChildT, Index Log2Dim>
1153 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1154 sum += iter->nonLeafCount();
1160 template<
typename ChildT, Index Log2Dim>
1164 return this->getChildMask().countOn();
1168 template<
typename ChildT, Index Log2Dim>
1173 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1174 sum += iter->onVoxelCount();
1180 template<
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();
1192 template<
typename ChildT, Index Log2Dim>
1197 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1198 sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount();
1204 template<
typename ChildT, Index Log2Dim>
1209 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1210 sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount();
1215 template<
typename ChildT, Index Log2Dim>
1220 for (
ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) {
1221 sum += iter->onTileCount();
1226 template<
typename ChildT, Index Log2Dim>
1232 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1233 sum += iter->memUsage();
1239 template<
typename ChildT, Index Log2Dim>
1243 if (bbox.isInside(
this->getNodeBoundingBox()))
return;
1246 bbox.expand(i.getCoord(), ChildT::DIM);
1249 i->evalActiveBoundingBox(bbox, visitVoxels);
1257 template<
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);
1271 mNodes[i].setValue(value);
1280 template<
typename ChildT, Index Log2Dim>
1281 template<
typename NodeT>
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();
1292 mChildMask.setOff(n);
1294 mNodes[
n].setValue(value);
1297 ?
reinterpret_cast<NodeT*
>(child)
1298 : child->template stealNode<NodeT>(xyz, value, state);
1306 template<
typename ChildT, Index Log2Dim>
1307 template<
typename NodeT>
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();
1318 ?
reinterpret_cast<NodeT*
>(child)
1319 : child->template probeNode<NodeT>(xyz);
1324 template<
typename ChildT, Index Log2Dim>
1325 template<
typename NodeT,
typename AccessorT>
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);
1337 ?
reinterpret_cast<NodeT*
>(child)
1338 : child->template probeNodeAndCache<NodeT>(xyz, acc);
1343 template<
typename ChildT, Index Log2Dim>
1344 template<
typename NodeT>
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();
1355 ?
reinterpret_cast<const NodeT*
>(child)
1356 : child->template probeConstNode<NodeT>(xyz);
1361 template<
typename ChildT, Index Log2Dim>
1362 template<
typename NodeT,
typename AccessorT>
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);
1374 ?
reinterpret_cast<const NodeT*
>(child)
1375 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
1383 template<
typename ChildT, Index Log2Dim>
1387 const Index n = this->coordToOffset(xyz);
1388 return this->probeChildUnsafe(n);
1391 template<
typename ChildT, Index Log2Dim>
1392 inline const ChildT*
1395 const Index n = this->coordToOffset(xyz);
1396 return this->probeConstChildUnsafe(n);
1399 template<
typename ChildT, Index Log2Dim>
1403 const Index n = this->coordToOffset(xyz);
1404 return this->probeChildUnsafe(n, value, active);
1407 template<
typename ChildT, Index Log2Dim>
1408 inline const ChildT*
1411 const Index n = this->coordToOffset(xyz);
1412 return this->probeConstChildUnsafe(n, value, active);
1415 template<
typename ChildT, Index Log2Dim>
1420 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1424 template<
typename ChildT, Index Log2Dim>
1425 inline const ChildT*
1429 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1433 template<
typename ChildT, Index Log2Dim>
1438 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1439 value = mNodes[
offset].getValue();
1444 template<
typename ChildT, Index Log2Dim>
1445 inline const ChildT*
1449 if (mChildMask.isOn(offset))
return mNodes[offset].getChild();
1450 value = mNodes[
offset].getValue();
1459 template<
typename ChildT, Index Log2Dim>
1460 inline typename ChildT::LeafNodeType*
1463 return this->
template probeNode<LeafNodeType>(xyz);
1467 template<
typename ChildT, Index Log2Dim>
1468 template<
typename AccessorT>
1469 inline typename ChildT::LeafNodeType*
1472 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
1476 template<
typename ChildT, Index Log2Dim>
1477 template<
typename AccessorT>
1478 inline const typename ChildT::LeafNodeType*
1481 return this->probeConstLeafAndCache(xyz, acc);
1485 template<
typename ChildT, Index Log2Dim>
1486 inline const typename ChildT::LeafNodeType*
1489 return this->
template probeConstNode<LeafNodeType>(xyz);
1493 template<
typename ChildT, Index Log2Dim>
1494 template<
typename AccessorT>
1495 inline const typename ChildT::LeafNodeType*
1498 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
1505 template<
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) {
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);
1533 template<
typename ChildT, Index Log2Dim>
1534 template<
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) {
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);
1567 template<
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);
1583 template<
typename ChildT, Index Log2Dim>
1588 this->makeChildNodeEmpty(n, value);
1593 template<
typename ChildT, Index Log2Dim>
1598 if (LEVEL >= level) {
1599 const Index n = this->coordToOffset(xyz);
1600 if (mChildMask.isOff(n)) {
1601 if (LEVEL > level) {
1603 this->setChildNode(n, child);
1604 child->addTile(level, xyz, value, 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);
1617 mNodes[
n].setValue(value);
1624 template<
typename ChildT, Index Log2Dim>
1625 template<
typename AccessorT>
1630 if (LEVEL >= level) {
1631 const Index n = this->coordToOffset(xyz);
1632 if (mChildMask.isOff(n)) {
1633 if (LEVEL > level) {
1635 this->setChildNode(n, child);
1636 acc.insert(xyz, child);
1637 child->addTileAndCache(level, xyz, value, state, acc);
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);
1651 mNodes[
n].setValue(value);
1661 template<
typename ChildT, Index Log2Dim>
1662 inline typename ChildT::LeafNodeType*
1665 const Index n = this->coordToOffset(xyz);
1666 ChildT* child =
nullptr;
1667 if (mChildMask.isOff(n)) {
1669 this->setChildNode(n, child);
1671 child = mNodes[
n].getChild();
1673 return child->touchLeaf(xyz);
1677 template<
typename ChildT, Index Log2Dim>
1678 template<
typename AccessorT>
1679 inline typename ChildT::LeafNodeType*
1682 const Index
n = this->coordToOffset(xyz);
1683 if (mChildMask.isOff(n)) {
1686 acc.insert(xyz, mNodes[n].getChild());
1687 return mNodes[
n].getChild()->touchLeafAndCache(xyz, acc);
1694 template<
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) {
1714 template<
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) {
1727 if ((maxValue - v) > tolerance)
return false;
1729 }
else if (v > maxValue) {
1730 if ((v - minValue) > tolerance)
return false;
1741 template<
typename ChildT, Index Log2Dim>
1748 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1749 if (iter->hasActiveTiles())
return true;
1756 template<
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);
1765 template<
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);
1774 template<
typename ChildT, Index Log2Dim>
1775 template<
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);
1786 template<
typename ChildT, Index Log2Dim>
1790 const Index n = this->coordToOffset(xyz);
1791 return this->isChildMaskOff(n) ? mNodes[
n].getValue()
1792 : mNodes[
n].getChild()->getValue(xyz);
1795 template<
typename ChildT, Index Log2Dim>
1796 template<
typename AccessorT>
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();
1809 template<
typename ChildT, Index Log2Dim>
1813 const Index n = this->coordToOffset(xyz);
1814 return this->isChildMaskOff(n) ? LEVEL : mNodes[
n].getChild()->getValueLevel(xyz);
1817 template<
typename ChildT, Index Log2Dim>
1818 template<
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);
1831 template<
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);
1843 template<
typename ChildT, Index Log2Dim>
1844 template<
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);
1859 template<
typename ChildT, Index Log2Dim>
1863 const Index n = this->coordToOffset(xyz);
1864 bool hasChild = this->isChildMaskOn(n);
1865 if (!hasChild && this->isValueMaskOn(n)) {
1871 if (hasChild) mNodes[
n].getChild()->setValueOff(xyz);
1875 template<
typename ChildT, Index Log2Dim>
1879 const Index n = this->coordToOffset(xyz);
1880 bool hasChild = this->isChildMaskOn(n);
1881 if (!hasChild && !this->isValueMaskOn(n)) {
1887 if (hasChild) mNodes[
n].getChild()->setValueOn(xyz);
1891 template<
typename ChildT, Index Log2Dim>
1896 bool hasChild = this->isChildMaskOn(n);
1898 const bool active = this->isValueMaskOn(n);
1907 if (hasChild) mNodes[
n].getChild()->setValueOff(xyz, value);
1910 template<
typename ChildT, Index Log2Dim>
1911 template<
typename AccessorT>
1917 bool hasChild = this->isChildMaskOn(n);
1919 const bool active = this->isValueMaskOn(n);
1929 ChildT* child = mNodes[
n].getChild();
1930 acc.insert(xyz, child);
1931 child->setValueOffAndCache(xyz, value, acc);
1936 template<
typename ChildT, Index Log2Dim>
1940 const Index n = this->coordToOffset(xyz);
1941 bool hasChild = this->isChildMaskOn(n);
1943 const bool active = this->isValueMaskOn(n);
1952 if (hasChild) mNodes[
n].getChild()->setValueOn(xyz, value);
1955 template<
typename ChildT, Index Log2Dim>
1956 template<
typename AccessorT>
1961 const Index n = this->coordToOffset(xyz);
1962 bool hasChild = this->isChildMaskOn(n);
1964 const bool active = this->isValueMaskOn(n);
1974 acc.insert(xyz, mNodes[n].getChild());
1975 mNodes[
n].getChild()->setValueAndCache(xyz, value, acc);
1980 template<
typename ChildT, Index Log2Dim>
1984 const Index n = this->coordToOffset(xyz);
1985 bool hasChild = this->isChildMaskOn(n);
1989 const bool active = this->isValueMaskOn(n);
1993 if (hasChild) mNodes[
n].getChild()->setValueOnly(xyz, value);
1996 template<
typename ChildT, Index Log2Dim>
1997 template<
typename AccessorT>
2002 const Index n = this->coordToOffset(xyz);
2003 bool hasChild = this->isChildMaskOn(n);
2007 const bool active = this->isValueMaskOn(n);
2012 acc.insert(xyz, mNodes[n].getChild());
2013 mNodes[
n].getChild()->setValueOnlyAndCache(xyz, value, acc);
2018 template<
typename ChildT, Index Log2Dim>
2022 const Index n = this->coordToOffset(xyz);
2023 bool hasChild = this->isChildMaskOn(n);
2025 if (on != this->isValueMaskOn(n)) {
2033 if (hasChild) mNodes[
n].getChild()->setActiveState(xyz, on);
2036 template<
typename ChildT, Index Log2Dim>
2037 template<
typename AccessorT>
2041 const Index n = this->coordToOffset(xyz);
2042 bool hasChild = this->isChildMaskOn(n);
2044 if (on != this->isValueMaskOn(n)) {
2053 ChildT* child = mNodes[
n].getChild();
2054 acc.insert(xyz, child);
2055 child->setActiveStateAndCache(xyz, on, acc);
2060 template<
typename ChildT, Index Log2Dim>
2065 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2066 mNodes[iter.pos()].getChild()->setValuesOn();
2071 template<
typename ChildT, Index Log2Dim>
2072 template<
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();
2096 if (hasChild) mNodes[
n].getChild()->modifyValue(xyz, op);
2099 template<
typename ChildT, Index Log2Dim>
2100 template<
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();
2127 acc.insert(xyz, child);
2128 child->modifyValueAndCache(xyz, op, acc);
2133 template<
typename ChildT, Index Log2Dim>
2134 template<
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);
2156 template<
typename ChildT, Index Log2Dim>
2157 template<
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);
2188 template<
typename ChildT, Index Log2Dim>
2192 CoordBBox nodeBBox = this->getNodeBoundingBox();
2193 if (!clipBBox.hasOverlap(nodeBBox)) {
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);
2207 CoordBBox tileBBox(xyz, xyz.offsetBy(ChildT::DIM - 1));
2208 if (!clipBBox.hasOverlap(tileBBox)) {
2211 this->makeChildNodeEmpty(pos, background);
2213 }
else if (!clipBBox.isInside(tileBBox)) {
2216 if (this->isChildMaskOn(pos)) {
2217 mNodes[pos].getChild()->clip(clipBBox, background);
2221 tileBBox.intersect(clipBBox);
2223 const bool on = this->isValueMaskOn(pos);
2224 mNodes[pos].setValue(background);
2226 this->
fill(tileBBox, val, on);
2238 template<
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);
2261 if (xyz != tileMin || Coord::lessThan(clippedBBox.max(), tileMax)) {
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);
2294 template<
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);
2341 template<
typename ChildT, Index Log2Dim>
2342 template<
typename DenseT>
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);
2364 sub.translate(-min);
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;
2370 for (
Int32 z = sub.min()[2], ez = sub.max()[2]+1;
2371 z < ez; ++
z, a2 += zStride)
2373 *a2 = DenseValueType(value);
2387 template<
typename ChildT, Index Log2Dim>
2391 mChildMask.save(os);
2396 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[NUM_VALUES]);
2398 const ValueType zero = zeroVal<ValueType>();
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);
2412 template<
typename ChildT, Index Log2Dim>
2419 mChildMask.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);
2472 template<
typename ChildT, Index Log2Dim>
2476 return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].
getValue());
2480 template<
typename ChildT, Index Log2Dim>
2484 const Index n = NUM_VALUES - 1;
2485 return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].
getValue());
2492 template<
typename ChildT, Index Log2Dim>
2498 return mNodes[
n].getValue();
2501 template<
typename ChildT, Index Log2Dim>
2507 value = mNodes[
n].getValue();
2511 template<
typename ChildT, Index Log2Dim>
2517 return mNodes[
n].getChild();
2520 template<
typename ChildT, Index Log2Dim>
2521 inline const ChildT*
2526 return mNodes[
n].getChild();
2529 template<
typename ChildT, Index Log2Dim>
2530 inline const ChildT*
2533 return this->getConstChildUnsafe(n);
2536 template<
typename ChildT, Index Log2Dim>
2545 template<
typename ChildT, Index Log2Dim>
2551 mNodes[
n].setValue(value);
2554 template<
typename ChildT, Index Log2Dim>
2563 template<
typename ChildT, Index Log2Dim>
2569 mNodes[
n].setValue(value);
2573 template<
typename ChildT, Index Log2Dim>
2582 template<
typename ChildT, Index Log2Dim>
2588 mNodes[
n].setValue(value);
2592 template<
typename ChildT, Index Log2Dim>
2599 mNodes[
n].setChild(child);
2600 mChildMask.setOn(n);
2604 template<
typename ChildT, Index Log2Dim>
2612 delete mNodes[
n].getChild();
2613 mNodes[
n].setChild(child);
2616 template<
typename ChildT, Index Log2Dim>
2623 auto* child = mNodes[
n].getChild();
2624 mChildMask.setOff(n);
2626 mNodes[
n].setValue(value);
2630 template<
typename ChildT, Index Log2Dim>
2635 delete this->stealChildUnsafe(n, value, active);
2642 template<
typename ChildT, Index Log2Dim>
2646 for (
Index i = 0; i < NUM_VALUES; ++i) {
2647 if (this->isChildMaskOn(i)) {
2648 mNodes[i].getChild()->negate();
2660 template<
typename ChildT, Index Log2Dim>
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);
2686 template<
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);
2706 template<
typename ChildT, Index Log2Dim>
2707 template<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);
2732 child->resetBackground(otherBackground, background);
2733 this->setChildNode(n, child);
2739 const Index n = iter.pos();
2742 this->makeChildNodeEmpty(n, iter.getValue());
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);
2787 child->template merge<Policy>(mNodes[
n].getValue(),
true);
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);
2803 mNodes[
n].setValue(iter.getValue());
2815 template<
typename ChildT, Index Log2Dim>
2816 template<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);
2846 template<
typename ChildT, Index Log2Dim>
2847 template<
typename OtherInternalNode>
2852 { tV = (tV | sV) & ~tC; }
2855 :
s(source),
t(target), mPreserveTiles(preserveTiles) {
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;
2890 template<
typename ChildT, Index Log2Dim>
2891 template<
typename OtherChildT>
2898 template<
typename ChildT, Index Log2Dim>
2899 template<
typename OtherInternalNode>
2900 struct InternalNode<ChildT, Log2Dim>::TopologyIntersection
2904 { tC = (tC & (sC | sV)) | (tV & sC); }
2907 const ValueType& background) :
s(source),
t(target),
b(background) {
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;
2939 template<
typename ChildT, Index Log2Dim>
2940 template<
typename OtherChildT>
2948 template<
typename ChildT, Index Log2Dim>
2949 template<
typename OtherInternalNode>
2950 struct InternalNode<ChildT, Log2Dim>::TopologyDifference
2954 { tC = (tC & (sC | ~sV)) | (tV & sC); }
2957 { tV &= ~((tC & sV) | (sC | sV)); }
2960 const ValueType& background) :
s(source),
t(target),
b(background) {
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;
2999 template<
typename ChildT, Index Log2Dim>
3000 template<
typename OtherChildT>
3012 template<
typename ChildT, Index Log2Dim>
3013 template<
typename CombineOp>
3017 const ValueType zero = zeroVal<ValueType>();
3021 for (
Index i = 0; i < NUM_VALUES; ++i) {
3025 op(args.setARef(mNodes[i].getValue())
3026 .setAIsActive(isValueMaskOn(i))
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);
3070 template<
typename ChildT, Index Log2Dim>
3071 template<
typename CombineOp>
3077 for (
Index i = 0; i < NUM_VALUES; ++i) {
3078 if (this->isChildMaskOff(i)) {
3081 .setAIsActive(isValueMaskOn(i))
3083 .setBIsActive(valueIsActive));
3084 mNodes[i].setValue(args.
result());
3090 if (child) child->combine(value, valueIsActive, op);
3099 template<
typename ChildT, Index Log2Dim>
3100 template<
typename CombineOp,
typename OtherNodeType>
3107 for (
Index i = 0; i < NUM_VALUES; ++i) {
3111 .setBRef(other1.mNodes[i].getValue())
3112 .setBIsActive(other1.isValueMaskOn(i)));
3114 this->makeChildNodeEmpty(i, args.
result());
3117 if (this->isChildMaskOff(i)) {
3121 : other1.mNodes[i].getChild()->origin();
3130 }
else if (other1.isChildMaskOff(i)) {
3134 other1.mNodes[i].getValue(), other1.isValueMaskOn(i),
op);
3139 *other1.mNodes[i].getChild(),
op);
3146 template<
typename ChildT, Index Log2Dim>
3147 template<
typename CombineOp,
typename OtherNodeType>
3150 bool valueIsActive, CombineOp&
op)
3154 for (
Index i = 0; i < NUM_VALUES; ++i) {
3155 if (other.isChildMaskOff(i)) {
3157 .setAIsActive(valueIsActive)
3158 .setBRef(other.mNodes[i].getValue())
3159 .setBIsActive(other.isValueMaskOn(i)));
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);
3179 template<
typename ChildT, Index Log2Dim>
3180 template<
typename CombineOp,
typename OtherValueType>
3183 bool valueIsActive, CombineOp&
op)
3187 for (
Index i = 0; i < NUM_VALUES; ++i) {
3192 .setBIsActive(valueIsActive));
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);
3215 template<
typename ChildT, Index Log2Dim>
3219 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3220 iter->writeBuffers(os, toHalf);
3225 template<
typename ChildT, Index Log2Dim>
3229 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3230 iter->readBuffers(is, fromHalf);
3235 template<
typename ChildT, Index Log2Dim>
3238 const CoordBBox& clipBBox,
bool fromHalf)
3240 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3245 iter->readBuffers(is, clipBBox, fromHalf);
3249 ValueType background = zeroVal<ValueType>();
3251 background = *
static_cast<const ValueType*
>(bgPtr);
3253 this->
clip(clipBBox, background);
3260 template<
typename ChildT, Index Log2Dim>
3264 dims.push_back(Log2Dim);
3265 ChildNodeType::getNodeLog2Dims(dims);
3269 template<
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));
3281 template<
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);
3291 template<
typename ChildT, Index Log2Dim>
3296 this->offsetToLocalCoord(n, local);
3297 local <<= ChildT::TOTAL;
3298 return local + this->origin();
3305 template<
typename ChildT, Index Log2Dim>
3306 template<
typename ArrayT>
3312 using ArrayChildT =
typename std::conditional<
3314 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3317 array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild()));
3319 iter->getNodes(array);
3325 template<
typename ChildT, Index Log2Dim>
3326 template<
typename ArrayT>
3333 "argument to getNodes() must be an array of const node pointers");
3334 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3337 array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild()));
3339 iter->getNodes(array);
3349 template<
typename ChildT, Index Log2Dim>
3350 template<
typename ArrayT>
3356 using ArrayChildT =
typename std::conditional<
3359 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3360 const Index n = iter.pos();
3362 array.push_back(reinterpret_cast<T>(mNodes[n].getChild()));
3364 mNodes[
n].setValue(value);
3366 iter->stealNodes(array, value, state);
3377 template<
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);
3396 template<
typename ChildT, Index Log2Dim>
3397 template<
typename OtherChildNodeType, Index OtherLog2Dim>
3402 if (Log2Dim != OtherLog2Dim || mChildMask != other->
mChildMask ||
3404 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3405 if (!iter->hasSameTopology(other->
mNodes[iter.pos()].getChild()))
return false;
3411 template<
typename ChildT, Index Log2Dim>
3416 if (this->isChildMaskOn(i)) {
3417 delete mNodes[i].getChild();
3419 mChildMask.setOn(i);
3422 mNodes[i].setChild(child);
3425 template<
typename ChildT, Index Log2Dim>
3431 mChildMask.setOn(i);
3433 mNodes[i].setChild(child);
3437 template<
typename ChildT, Index Log2Dim>
3441 if (this->isChildMaskOff(i)) {
3442 mNodes[i].setValue(value);
3446 mChildMask.setOff(i);
3447 mNodes[i].setValue(value);
3452 template<
typename ChildT, Index Log2Dim>
3456 delete this->unsetChildNode(n, value);
3459 template<
typename ChildT, Index Log2Dim>
3464 return mNodes[
n].getChild();
3468 template<
typename ChildT, Index Log2Dim>
3469 inline const ChildT*
3473 return mNodes[
n].getChild();
3480 #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
void writeCompressedValues(std::ostream &os, ValueT *srcBuf, Index srcCount, const MaskT &valueMask, const MaskT &childMask, bool toHalf)
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...
__hostdev__ void setValue(uint32_t offset, bool v)
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.
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 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 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...
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