8 #ifndef OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
9 #define OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
19 #include <tbb/parallel_for.h>
21 #include <type_traits>
32 template<
typename _ChildNodeType, Index Log2Dim>
45 TOTAL = Log2Dim + ChildNodeType::TOTAL,
48 LEVEL = 1 + ChildNodeType::LEVEL;
54 template<
typename OtherValueType>
63 template<
typename OtherNodeType>
94 template<
typename OtherChildNodeType>
100 template<
typename OtherChildNodeType>
107 template<
typename OtherChildNodeType>
126 template<
typename NodeT,
typename ChildT,
typename MaskIterT,
typename TagT>
128 MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>
132 MaskIterT,
ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>(iter, parent) {}
137 return *(this->
parent().getChildNode(pos));
147 template<
typename NodeT,
typename ValueT,
typename MaskIterT,
typename TagT>
149 MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>
153 MaskIterT,
ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>(iter, parent) {}
161 template<
typename ModifyOp>
169 template<
typename NodeT,
typename ChildT,
typename ValueT,
typename TagT>
171 MaskDenseIterator, DenseIter<NodeT, ChildT, ValueT, TagT>, NodeT, ChildT, ValueT>
183 child = this->
parent().getChildNode(pos);
187 value = this->
parent().mNodes[
pos].getValue();
194 this->
parent().resetChildNode(pos, child);
200 this->
parent().unsetChildNode(pos, value);
277 void nodeCount(std::vector<Index32> &vec)
const;
308 const ValueType& tolerance = zeroVal<ValueType>())
const;
325 bool& state,
const ValueType& tolerance = zeroVal<ValueType>())
const;
367 template<
typename ModifyOp>
368 void modifyValue(
const Coord& xyz,
const ModifyOp& op);
370 template<
typename ModifyOp>
377 template<
typename AccessorT>
384 template<
typename AccessorT>
391 template<
typename AccessorT>
398 template<
typename AccessorT>
406 template<
typename ModifyOp,
typename AccessorT>
413 template<
typename ModifyOp,
typename AccessorT>
420 template<
typename AccessorT>
427 template<
typename AccessorT>
435 template<
typename AccessorT>
444 template<
typename AccessorT>
453 void writeTopology(std::ostream&,
bool toHalf =
false)
const;
454 void readTopology(std::istream&,
bool fromHalf =
false);
455 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
456 void readBuffers(std::istream&,
bool fromHalf =
false);
498 template<
typename DenseT>
503 template<MergePolicy Policy>
508 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive);
522 template<
typename OtherChildNodeType>
538 template<
typename OtherChildNodeType>
553 template<
typename OtherChildNodeType>
557 template<
typename CombineOp>
559 template<
typename CombineOp>
562 template<
typename CombineOp,
typename OtherNodeType >
564 template<
typename CombineOp,
typename OtherNodeType >
566 template<
typename CombineOp,
typename OtherValueType>
583 template<
typename AccessorT>
594 template<
typename NodeT>
614 template<
typename AccessorT>
620 template<
typename NodeType> NodeType*
probeNode(
const Coord& xyz);
621 template<
typename NodeType>
const NodeType*
probeConstNode(
const Coord& xyz)
const;
627 template<
typename NodeType,
typename AccessorT>
629 template<
typename NodeType,
typename AccessorT>
644 template<
typename AccessorT>
646 template<
typename AccessorT>
648 template<
typename AccessorT>
662 template<
typename AccessorT>
688 template<
typename ArrayT>
690 template<
typename ArrayT>
717 template<
typename ArrayT>
726 template<
typename OtherChildNodeType, Index OtherLog2Dim>
783 struct VoxelizeActiveTiles;
784 template<
typename OtherInternalNode>
struct DeepCopy;
807 template<
typename ChildT1, Index Dim1,
typename NodeT2>
812 template<
typename ChildT1, Index Dim1,
typename ChildT2>
822 template<
typename ChildT, Index Log2Dim>
826 for (
Index i = 0; i < NUM_VALUES; ++i) mNodes[i].
setValue(background);
830 template<
typename ChildT, Index Log2Dim>
833 mOrigin(origin[0] & ~(DIM - 1),
834 origin[1] & ~(DIM - 1),
835 origin[2] & ~(DIM - 1))
844 template<
typename ChildT, Index Log2Dim>
848 : mOrigin(origin[0] & ~(DIM-1), origin[1] & ~(DIM-1), origin[2] & ~(DIM-1))
854 template<
typename ChildT, Index Log2Dim>
855 template<
typename OtherInternalNode>
863 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
864 if (
s->mChildMask.isOff(i)) {
865 t->mNodes[i].setValue(
ValueType(
s->mNodes[i].getValue()));
871 const OtherInternalNode*
s;
875 template<
typename ChildT, Index Log2Dim>
878 : mChildMask(other.mChildMask)
880 , mOrigin(other.mOrigin)
881 , mTransientData(other.mTransientData)
888 template<
typename ChildT, Index Log2Dim>
889 template<
typename OtherChildNodeType>
892 : mChildMask(other.mChildMask)
894 , mOrigin(other.mOrigin)
895 , mTransientData(other.mTransientData)
900 template<
typename ChildT, Index Log2Dim>
901 template<
typename OtherInternalNode>
905 const ValueType& background) :
s(source),
t(target),
b(background) {
910 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
911 if (
s->isChildMaskOn(i)) {
915 t->mNodes[i].setValue(
b);
919 const OtherInternalNode*
s;
924 template<
typename ChildT, Index Log2Dim>
925 template<
typename OtherChildNodeType>
929 : mChildMask(other.mChildMask)
931 , mOrigin(other.mOrigin)
932 , mTransientData(other.mTransientData)
937 template<
typename ChildT, Index Log2Dim>
938 template<
typename OtherInternalNode>
943 :
s(source),
t(target), offV(offValue), onV(onValue) {
947 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
948 if (
s->isChildMaskOn(i)) {
952 t->mNodes[i].setValue(
s->isValueMaskOn(i) ? onV : offV);
956 const OtherInternalNode*
s;
961 template<
typename ChildT, Index Log2Dim>
962 template<
typename OtherChildNodeType>
967 : mChildMask(other.mChildMask)
969 , mOrigin(other.mOrigin)
970 , mTransientData(other.mTransientData)
976 template<
typename ChildT, Index Log2Dim>
980 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
981 delete mNodes[iter.pos()].getChild();
989 template<
typename ChildT, Index Log2Dim>
995 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
996 sum += iter->leafCount();
1001 template<
typename ChildT, Index Log2Dim>
1005 assert(vec.size() > ChildNodeType::LEVEL);
1006 const auto count = mChildMask.countOn();
1007 if (ChildNodeType::LEVEL > 0 && count > 0) {
1008 for (
auto iter = this->cbeginChildOn(); iter; ++iter) iter->nodeCount(vec);
1010 vec[ChildNodeType::LEVEL] += count;
1014 template<
typename ChildT, Index Log2Dim>
1020 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1021 sum += iter->nonLeafCount();
1027 template<
typename ChildT, Index Log2Dim>
1031 return this->getChildMask().countOn();
1035 template<
typename ChildT, Index Log2Dim>
1040 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1041 sum += iter->onVoxelCount();
1047 template<
typename ChildT, Index Log2Dim>
1051 Index64 sum = ChildT::NUM_VOXELS * (NUM_VALUES-
mValueMask.countOn()-mChildMask.countOn());
1052 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1053 sum += iter->offVoxelCount();
1059 template<
typename ChildT, Index Log2Dim>
1064 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1065 sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount();
1071 template<
typename ChildT, Index Log2Dim>
1076 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1077 sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount();
1082 template<
typename ChildT, Index Log2Dim>
1087 for (
ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) {
1088 sum += iter->onTileCount();
1093 template<
typename ChildT, Index Log2Dim>
1099 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1100 sum += iter->memUsage();
1106 template<
typename ChildT, Index Log2Dim>
1110 if (bbox.isInside(
this->getNodeBoundingBox()))
return;
1113 bbox.expand(i.getCoord(), ChildT::DIM);
1116 i->evalActiveBoundingBox(bbox, visitVoxels);
1124 template<
typename ChildT, Index Log2Dim>
1130 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1131 const Index i = iter.pos();
1132 ChildT* child = mNodes[i].getChild();
1133 child->prune(tolerance);
1134 if (child->isConstant(value, state, tolerance)) {
1136 mChildMask.setOff(i);
1138 mNodes[i].setValue(value);
1147 template<
typename ChildT, Index Log2Dim>
1148 template<
typename NodeT>
1153 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1155 const Index n = this->coordToOffset(xyz);
1156 if (mChildMask.isOff(n))
return nullptr;
1157 ChildT* child = mNodes[
n].getChild();
1159 mChildMask.setOff(n);
1161 mNodes[
n].setValue(value);
1164 ?
reinterpret_cast<NodeT*
>(child)
1165 : child->template stealNode<NodeT>(xyz, value, state);
1173 template<
typename ChildT, Index Log2Dim>
1174 template<
typename NodeT>
1179 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1181 const Index n = this->coordToOffset(xyz);
1182 if (mChildMask.isOff(n))
return nullptr;
1183 ChildT* child = mNodes[
n].getChild();
1185 ?
reinterpret_cast<NodeT*
>(child)
1186 : child->template probeNode<NodeT>(xyz);
1191 template<
typename ChildT, Index Log2Dim>
1192 template<
typename NodeT,
typename AccessorT>
1197 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1199 const Index n = this->coordToOffset(xyz);
1200 if (mChildMask.isOff(n))
return nullptr;
1201 ChildT* child = mNodes[
n].getChild();
1202 acc.insert(xyz, child);
1204 ?
reinterpret_cast<NodeT*
>(child)
1205 : child->template probeNodeAndCache<NodeT>(xyz, acc);
1210 template<
typename ChildT, Index Log2Dim>
1211 template<
typename NodeT>
1216 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1218 const Index n = this->coordToOffset(xyz);
1219 if (mChildMask.isOff(n))
return nullptr;
1220 const ChildT* child = mNodes[
n].getChild();
1222 ?
reinterpret_cast<const NodeT*
>(child)
1223 : child->template probeConstNode<NodeT>(xyz);
1228 template<
typename ChildT, Index Log2Dim>
1229 template<
typename NodeT,
typename AccessorT>
1234 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1236 const Index n = this->coordToOffset(xyz);
1237 if (mChildMask.isOff(n))
return nullptr;
1238 const ChildT* child = mNodes[
n].getChild();
1239 acc.insert(xyz, child);
1241 ?
reinterpret_cast<const NodeT*
>(child)
1242 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
1250 template<
typename ChildT, Index Log2Dim>
1251 inline typename ChildT::LeafNodeType*
1254 return this->
template probeNode<LeafNodeType>(xyz);
1258 template<
typename ChildT, Index Log2Dim>
1259 template<
typename AccessorT>
1260 inline typename ChildT::LeafNodeType*
1263 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
1267 template<
typename ChildT, Index Log2Dim>
1268 template<
typename AccessorT>
1269 inline const typename ChildT::LeafNodeType*
1272 return this->probeConstLeafAndCache(xyz, acc);
1276 template<
typename ChildT, Index Log2Dim>
1277 inline const typename ChildT::LeafNodeType*
1280 return this->
template probeConstNode<LeafNodeType>(xyz);
1284 template<
typename ChildT, Index Log2Dim>
1285 template<
typename AccessorT>
1286 inline const typename ChildT::LeafNodeType*
1289 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
1296 template<
typename ChildT, Index Log2Dim>
1300 assert(leaf !=
nullptr);
1301 const Coord& xyz = leaf->origin();
1302 const Index n = this->coordToOffset(xyz);
1303 ChildT* child =
nullptr;
1304 if (mChildMask.isOff(n)) {
1305 if (ChildT::LEVEL>0) {
1308 child =
reinterpret_cast<ChildT*
>(leaf);
1310 this->setChildNode(n, child);
1312 if (ChildT::LEVEL>0) {
1313 child = mNodes[
n].getChild();
1315 delete mNodes[
n].getChild();
1316 child =
reinterpret_cast<ChildT*
>(leaf);
1317 mNodes[
n].setChild(child);
1320 child->addLeaf(leaf);
1324 template<
typename ChildT, Index Log2Dim>
1325 template<
typename AccessorT>
1329 assert(leaf !=
nullptr);
1330 const Coord& xyz = leaf->origin();
1331 const Index n = this->coordToOffset(xyz);
1332 ChildT* child =
nullptr;
1333 if (mChildMask.isOff(n)) {
1334 if (ChildT::LEVEL>0) {
1336 acc.insert(xyz, child);
1338 child =
reinterpret_cast<ChildT*
>(leaf);
1340 this->setChildNode(n, child);
1342 if (ChildT::LEVEL>0) {
1343 child = mNodes[
n].getChild();
1344 acc.insert(xyz, child);
1346 delete mNodes[
n].getChild();
1347 child =
reinterpret_cast<ChildT*
>(leaf);
1348 mNodes[
n].setChild(child);
1351 child->addLeafAndCache(leaf, acc);
1358 template<
typename ChildT, Index Log2Dim>
1363 const Coord& xyz = child->origin();
1365 if (Coord((xyz & ~(DIM-1))) != this->origin())
return false;
1367 const Index n = this->coordToOffset(xyz);
1369 this->resetChildNode(n, child);
1374 template<
typename ChildT, Index Log2Dim>
1378 assert(n < NUM_VALUES);
1379 this->makeChildNodeEmpty(n, value);
1384 template<
typename ChildT, Index Log2Dim>
1389 if (LEVEL >= level) {
1390 const Index n = this->coordToOffset(xyz);
1391 if (mChildMask.isOff(n)) {
1392 if (LEVEL > level) {
1394 this->setChildNode(n, child);
1395 child->addTile(level, xyz, value, state);
1398 mNodes[
n].setValue(value);
1401 ChildT* child = mNodes[
n].getChild();
1402 if (LEVEL > level) {
1403 child->addTile(level, xyz, value, state);
1406 mChildMask.setOff(n);
1408 mNodes[
n].setValue(value);
1415 template<
typename ChildT, Index Log2Dim>
1416 template<
typename AccessorT>
1421 if (LEVEL >= level) {
1422 const Index n = this->coordToOffset(xyz);
1423 if (mChildMask.isOff(n)) {
1424 if (LEVEL > level) {
1426 this->setChildNode(n, child);
1427 acc.insert(xyz, child);
1428 child->addTileAndCache(level, xyz, value, state, acc);
1431 mNodes[
n].setValue(value);
1434 ChildT* child = mNodes[
n].getChild();
1435 if (LEVEL > level) {
1436 acc.insert(xyz, child);
1437 child->addTileAndCache(level, xyz, value, state, acc);
1440 mChildMask.setOff(n);
1442 mNodes[
n].setValue(value);
1452 template<
typename ChildT, Index Log2Dim>
1453 inline typename ChildT::LeafNodeType*
1456 const Index n = this->coordToOffset(xyz);
1457 ChildT* child =
nullptr;
1458 if (mChildMask.isOff(n)) {
1460 this->setChildNode(n, child);
1462 child = mNodes[
n].getChild();
1464 return child->touchLeaf(xyz);
1468 template<
typename ChildT, Index Log2Dim>
1469 template<
typename AccessorT>
1470 inline typename ChildT::LeafNodeType*
1473 const Index
n = this->coordToOffset(xyz);
1474 if (mChildMask.isOff(n)) {
1477 acc.insert(xyz, mNodes[n].getChild());
1478 return mNodes[
n].getChild()->touchLeafAndCache(xyz, acc);
1485 template<
typename ChildT, Index Log2Dim>
1490 if (!mChildMask.isOff() || !
mValueMask.isConstant(state))
return false;
1492 firstValue = mNodes[0].getValue();
1493 for (
Index i = 1; i < NUM_VALUES; ++i) {
1505 template<
typename ChildT, Index Log2Dim>
1513 if (!mChildMask.isOff() || !
mValueMask.isConstant(state))
return false;
1514 minValue = maxValue = mNodes[0].getValue();
1515 for (
Index i = 1; i < NUM_VALUES; ++i) {
1518 if ((maxValue - v) > tolerance)
return false;
1520 }
else if (v > maxValue) {
1521 if ((v - minValue) > tolerance)
return false;
1532 template<
typename ChildT, Index Log2Dim>
1539 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1540 if (iter->hasActiveTiles())
return true;
1547 template<
typename ChildT, Index Log2Dim>
1551 const Index n = this->coordToOffset(xyz);
1552 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1553 return mNodes[
n].getChild()->isValueOn(xyz);
1556 template<
typename ChildT, Index Log2Dim>
1557 template<
typename AccessorT>
1561 const Index n = this->coordToOffset(xyz);
1562 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1563 acc.insert(xyz, mNodes[n].getChild());
1564 return mNodes[
n].getChild()->isValueOnAndCache(xyz, acc);
1568 template<
typename ChildT, Index Log2Dim>
1572 const Index n = this->coordToOffset(xyz);
1573 return this->isChildMaskOff(n) ? mNodes[
n].getValue()
1574 : mNodes[
n].getChild()->getValue(xyz);
1577 template<
typename ChildT, Index Log2Dim>
1578 template<
typename AccessorT>
1582 const Index
n = this->coordToOffset(xyz);
1583 if (this->isChildMaskOn(n)) {
1584 acc.insert(xyz, mNodes[n].getChild());
1585 return mNodes[
n].getChild()->getValueAndCache(xyz, acc);
1587 return mNodes[
n].getValue();
1591 template<
typename ChildT, Index Log2Dim>
1595 const Index n = this->coordToOffset(xyz);
1596 return this->isChildMaskOff(n) ? LEVEL : mNodes[
n].getChild()->getValueLevel(xyz);
1599 template<
typename ChildT, Index Log2Dim>
1600 template<
typename AccessorT>
1604 const Index n = this->coordToOffset(xyz);
1605 if (this->isChildMaskOn(n)) {
1606 acc.insert(xyz, mNodes[n].getChild());
1607 return mNodes[
n].getChild()->getValueLevelAndCache(xyz, acc);
1613 template<
typename ChildT, Index Log2Dim>
1617 const Index n = this->coordToOffset(xyz);
1618 if (this->isChildMaskOff(n)) {
1619 value = mNodes[
n].getValue();
1620 return this->isValueMaskOn(n);
1622 return mNodes[
n].getChild()->probeValue(xyz, value);
1625 template<
typename ChildT, Index Log2Dim>
1626 template<
typename AccessorT>
1631 const Index n = this->coordToOffset(xyz);
1632 if (this->isChildMaskOn(n)) {
1633 acc.insert(xyz, mNodes[n].getChild());
1634 return mNodes[
n].getChild()->probeValueAndCache(xyz, value, acc);
1636 value = mNodes[
n].getValue();
1637 return this->isValueMaskOn(n);
1641 template<
typename ChildT, Index Log2Dim>
1645 const Index n = this->coordToOffset(xyz);
1646 bool hasChild = this->isChildMaskOn(n);
1647 if (!hasChild && this->isValueMaskOn(n)) {
1653 if (hasChild) mNodes[
n].getChild()->setValueOff(xyz);
1657 template<
typename ChildT, Index Log2Dim>
1661 const Index n = this->coordToOffset(xyz);
1662 bool hasChild = this->isChildMaskOn(n);
1663 if (!hasChild && !this->isValueMaskOn(n)) {
1669 if (hasChild) mNodes[
n].getChild()->setValueOn(xyz);
1673 template<
typename ChildT, Index Log2Dim>
1678 bool hasChild = this->isChildMaskOn(n);
1680 const bool active = this->isValueMaskOn(n);
1689 if (hasChild) mNodes[
n].getChild()->setValueOff(xyz, value);
1692 template<
typename ChildT, Index Log2Dim>
1693 template<
typename AccessorT>
1699 bool hasChild = this->isChildMaskOn(n);
1701 const bool active = this->isValueMaskOn(n);
1711 ChildT* child = mNodes[
n].getChild();
1712 acc.insert(xyz, child);
1713 child->setValueOffAndCache(xyz, value, acc);
1718 template<
typename ChildT, Index Log2Dim>
1722 const Index n = this->coordToOffset(xyz);
1723 bool hasChild = this->isChildMaskOn(n);
1725 const bool active = this->isValueMaskOn(n);
1734 if (hasChild) mNodes[
n].getChild()->setValueOn(xyz, value);
1737 template<
typename ChildT, Index Log2Dim>
1738 template<
typename AccessorT>
1743 const Index n = this->coordToOffset(xyz);
1744 bool hasChild = this->isChildMaskOn(n);
1746 const bool active = this->isValueMaskOn(n);
1756 acc.insert(xyz, mNodes[n].getChild());
1757 mNodes[
n].getChild()->setValueAndCache(xyz, value, acc);
1762 template<
typename ChildT, Index Log2Dim>
1766 const Index n = this->coordToOffset(xyz);
1767 bool hasChild = this->isChildMaskOn(n);
1771 const bool active = this->isValueMaskOn(n);
1775 if (hasChild) mNodes[
n].getChild()->setValueOnly(xyz, value);
1778 template<
typename ChildT, Index Log2Dim>
1779 template<
typename AccessorT>
1784 const Index n = this->coordToOffset(xyz);
1785 bool hasChild = this->isChildMaskOn(n);
1789 const bool active = this->isValueMaskOn(n);
1794 acc.insert(xyz, mNodes[n].getChild());
1795 mNodes[
n].getChild()->setValueOnlyAndCache(xyz, value, acc);
1800 template<
typename ChildT, Index Log2Dim>
1804 const Index n = this->coordToOffset(xyz);
1805 bool hasChild = this->isChildMaskOn(n);
1807 if (on != this->isValueMaskOn(n)) {
1815 if (hasChild) mNodes[
n].getChild()->setActiveState(xyz, on);
1818 template<
typename ChildT, Index Log2Dim>
1819 template<
typename AccessorT>
1823 const Index n = this->coordToOffset(xyz);
1824 bool hasChild = this->isChildMaskOn(n);
1826 if (on != this->isValueMaskOn(n)) {
1835 ChildT* child = mNodes[
n].getChild();
1836 acc.insert(xyz, child);
1837 child->setActiveStateAndCache(xyz, on, acc);
1842 template<
typename ChildT, Index Log2Dim>
1847 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1848 mNodes[iter.pos()].getChild()->setValuesOn();
1853 template<
typename ChildT, Index Log2Dim>
1854 template<
typename ModifyOp>
1859 bool hasChild = this->isChildMaskOn(n);
1863 const bool active = this->isValueMaskOn(n);
1864 bool createChild = !
active;
1868 const ValueType& tileVal = mNodes[
n].getValue();
1878 if (hasChild) mNodes[
n].getChild()->modifyValue(xyz, op);
1881 template<
typename ChildT, Index Log2Dim>
1882 template<
typename ModifyOp,
typename AccessorT>
1888 bool hasChild = this->isChildMaskOn(n);
1892 const bool active = this->isValueMaskOn(n);
1893 bool createChild = !
active;
1897 const ValueType& tileVal = mNodes[
n].getValue();
1909 acc.insert(xyz, child);
1910 child->modifyValueAndCache(xyz, op, acc);
1915 template<
typename ChildT, Index Log2Dim>
1916 template<
typename ModifyOp>
1921 bool hasChild = this->isChildMaskOn(n);
1923 const bool tileState = this->isValueMaskOn(n);
1924 const ValueType& tileVal = mNodes[
n].getValue();
1925 bool modifiedState = !tileState;
1927 op(modifiedVal, modifiedState);
1932 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
1935 if (hasChild) mNodes[
n].getChild()->modifyValueAndActiveState(xyz, op);
1938 template<
typename ChildT, Index Log2Dim>
1939 template<
typename ModifyOp,
typename AccessorT>
1942 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
1945 bool hasChild = this->isChildMaskOn(n);
1947 const bool tileState = this->isValueMaskOn(n);
1948 const ValueType& tileVal = mNodes[
n].getValue();
1949 bool modifiedState = !tileState;
1951 op(modifiedVal, modifiedState);
1956 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
1961 acc.insert(xyz, child);
1962 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
1970 template<
typename ChildT, Index Log2Dim>
1974 CoordBBox nodeBBox = this->getNodeBoundingBox();
1975 if (!clipBBox.hasOverlap(nodeBBox)) {
1977 this->
fill(nodeBBox, background,
false);
1978 }
else if (clipBBox.isInside(nodeBBox)) {
1987 for (
Index pos = 0; pos < NUM_VALUES; ++pos) {
1988 const Coord xyz = this->offsetToGlobalCoord(pos);
1989 CoordBBox tileBBox(xyz, xyz.offsetBy(ChildT::DIM - 1));
1990 if (!clipBBox.hasOverlap(tileBBox)) {
1993 this->makeChildNodeEmpty(pos, background);
1995 }
else if (!clipBBox.isInside(tileBBox)) {
1998 if (this->isChildMaskOn(pos)) {
1999 mNodes[pos].getChild()->clip(clipBBox, background);
2003 tileBBox.intersect(clipBBox);
2005 const bool on = this->isValueMaskOn(pos);
2006 mNodes[pos].setValue(background);
2008 this->
fill(tileBBox, val, on);
2020 template<
typename ChildT, Index Log2Dim>
2024 auto clippedBBox = this->getNodeBoundingBox();
2025 clippedBBox.intersect(bbox);
2026 if (!clippedBBox)
return;
2030 Coord xyz, tileMin, tileMax;
2031 for (
int x = clippedBBox.min().x();
x <= clippedBBox.max().x();
x = tileMax.x() + 1) {
2033 for (
int y = clippedBBox.min().y();
y <= clippedBBox.max().y();
y = tileMax.y() + 1) {
2035 for (
int z = clippedBBox.min().z();
z <= clippedBBox.max().z();
z = tileMax.z() + 1) {
2039 const Index n = this->coordToOffset(xyz);
2040 tileMin = this->offsetToGlobalCoord(n);
2041 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2043 if (xyz != tileMin || Coord::lessThan(clippedBBox.max(), tileMax)) {
2047 ChildT* child =
nullptr;
2048 if (this->isChildMaskOff(n)) {
2051 child =
new ChildT{xyz, mNodes[
n].getValue(), this->isValueMaskOn(n)};
2052 this->setChildNode(n, child);
2054 child = mNodes[
n].getChild();
2060 child->fill(
CoordBBox(xyz, tmp), value, active);
2067 this->makeChildNodeEmpty(n, value);
2076 template<
typename ChildT, Index Log2Dim>
2080 auto clippedBBox = this->getNodeBoundingBox();
2081 clippedBBox.intersect(bbox);
2082 if (!clippedBBox)
return;
2086 Coord xyz, tileMin, tileMax;
2087 for (
int x = clippedBBox.min().x();
x <= clippedBBox.max().x();
x = tileMax.x() + 1) {
2089 for (
int y = clippedBBox.min().y();
y <= clippedBBox.max().y();
y = tileMax.y() + 1) {
2091 for (
int z = clippedBBox.min().z();
z <= clippedBBox.max().z();
z = tileMax.z() + 1) {
2095 const auto n = this->coordToOffset(xyz);
2098 ChildT* child =
nullptr;
2099 if (this->isChildMaskOn(
n)) {
2100 child = mNodes[
n].getChild();
2104 child =
new ChildT{xyz, mNodes[
n].getValue(), this->isValueMaskOn(
n)};
2105 this->setChildNode(
n, child);
2109 tileMin = this->offsetToGlobalCoord(
n);
2110 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2123 template<
typename ChildT, Index Log2Dim>
2124 template<
typename DenseT>
2130 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2131 const Coord&
min = dense.bbox().min();
2132 for (Coord xyz = bbox.min(),
max; xyz[0] <= bbox.max()[0]; xyz[0] =
max[0] + 1) {
2133 for (xyz[1] = bbox.min()[1]; xyz[1] <= bbox.max()[1]; xyz[1] =
max[1] + 1) {
2134 for (xyz[2] = bbox.min()[2]; xyz[2] <= bbox.max()[2]; xyz[2] =
max[2] + 1) {
2135 const Index n = this->coordToOffset(xyz);
2137 max = this->offsetToGlobalCoord(n).offsetBy(ChildT::DIM-1);
2142 if (this->isChildMaskOn(n)) {
2143 mNodes[
n].getChild()->copyToDense(sub, dense);
2146 sub.translate(-min);
2147 DenseValueType* a0 = dense.data() + zStride*sub.min()[2];
2148 for (
Int32 x=sub.min()[0], ex=sub.max()[0]+1;
x<ex; ++
x) {
2149 DenseValueType* a1 = a0 +
x*xStride;
2150 for (
Int32 y=sub.min()[1], ey=sub.max()[1]+1;
y<ey; ++
y) {
2151 DenseValueType* a2 = a1 +
y*yStride;
2152 for (
Int32 z = sub.min()[2], ez = sub.max()[2]+1;
2153 z < ez; ++
z, a2 += zStride)
2155 *a2 = DenseValueType(value);
2169 template<
typename ChildT, Index Log2Dim>
2173 mChildMask.save(os);
2178 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[NUM_VALUES]);
2181 for (
Index i = 0; i < NUM_VALUES; ++i) {
2182 values[i] = (mChildMask.isOff(i) ? mNodes[i].getValue() :
zero);
2188 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2189 iter->writeTopology(os, toHalf);
2194 template<
typename ChildT, Index Log2Dim>
2201 mChildMask.load(is);
2205 for (
Index i = 0; i < NUM_VALUES; ++i) {
2206 if (this->isChildMaskOn(i)) {
2209 mNodes[i].setChild(child);
2210 child->readTopology(is);
2213 is.read(reinterpret_cast<char*>(&value),
sizeof(
ValueType));
2214 mNodes[i].setValue(value);
2218 const bool oldVersion =
2220 const Index numValues = (oldVersion ? mChildMask.countOff() : NUM_VALUES);
2224 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[numValues]);
2231 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2232 mNodes[iter.pos()].setValue(values[n++]);
2234 assert(n == numValues);
2236 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2237 mNodes[iter.pos()].setValue(values[iter.pos()]);
2242 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2244 mNodes[iter.pos()].setChild(child);
2245 child->readTopology(is, fromHalf);
2254 template<
typename ChildT, Index Log2Dim>
2258 return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].
getValue());
2262 template<
typename ChildT, Index Log2Dim>
2266 const Index n = NUM_VALUES - 1;
2267 return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].
getValue());
2274 template<
typename ChildT, Index Log2Dim>
2278 for (
Index i = 0; i < NUM_VALUES; ++i) {
2279 if (this->isChildMaskOn(i)) {
2280 mNodes[i].getChild()->negate();
2292 template<
typename ChildT, Index Log2Dim>
2304 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
2305 if (mNode->mChildMask.isOn(i)) {
2306 mNode->mNodes[i].getChild()->voxelizeActiveTiles(
true);
2307 }
else if (mNode->mValueMask.isOn(i)) {
2308 const Coord &ijk = mNode->offsetToGlobalCoord(i);
2310 child->voxelizeActiveTiles(
true);
2311 mNode->mNodes[i].setChild(child);
2318 template<
typename ChildT, Index Log2Dim>
2325 for (
ValueOnIter iter = this->beginValueOn(); iter; ++iter) {
2326 this->setChildNode(iter.pos(),
2329 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter)
2330 iter->voxelizeActiveTiles(
false);
2338 template<
typename ChildT, Index Log2Dim>
2339 template<MergePolicy Policy>
2352 const Index n = iter.pos();
2353 if (mChildMask.isOn(n)) {
2355 mNodes[
n].getChild()->template merge<MERGE_ACTIVE_STATES>(*iter,
2356 background, otherBackground);
2364 child->resetBackground(otherBackground, background);
2365 this->setChildNode(n, child);
2371 const Index n = iter.pos();
2374 this->makeChildNodeEmpty(n, iter.getValue());
2384 const Index n = iter.pos();
2385 if (mChildMask.isOn(n)) {
2387 mNodes[
n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2395 child->resetBackground(otherBackground, background);
2396 this->setChildNode(n, child);
2406 const Index n = iter.pos();
2407 if (mChildMask.isOn(n)) {
2409 mNodes[
n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2416 child->resetBackground(otherBackground, background);
2419 child->template merge<Policy>(mNodes[
n].getValue(),
true);
2422 mChildMask.setOn(n);
2423 mNodes[
n].setChild(child);
2429 const Index n = iter.pos();
2430 if (mChildMask.isOn(n)) {
2432 mNodes[
n].getChild()->template merge<Policy>(iter.getValue(),
true);
2435 mNodes[
n].setValue(iter.getValue());
2447 template<
typename ChildT, Index Log2Dim>
2448 template<MergePolicy Policy>
2457 if (!tileActive)
return;
2460 for (
ValueOffIter iter = this->beginValueOff(); iter; ++iter) {
2461 const Index n = iter.pos();
2462 if (mChildMask.isOn(n)) {
2464 mNodes[
n].getChild()->template merge<Policy>(tileValue,
true);
2467 iter.setValue(tileValue);
2478 template<
typename ChildT, Index Log2Dim>
2479 template<
typename OtherInternalNode>
2484 { tV = (tV | sV) & ~tC; }
2487 :
s(source),
t(target), mPreserveTiles(preserveTiles) {
2492 if (!mPreserveTiles)
t->mChildMask |=
s->mChildMask;
2493 else t->mChildMask |= (
s->mChildMask & !
t->mValueMask);
2496 t->mValueMask.foreach(
s->mValueMask,
t->mChildMask, op);
2497 assert((
t->mValueMask &
t->mChildMask).isOff());
2500 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
2501 if (
s->mChildMask.isOn(i)) {
2502 const typename OtherInternalNode::ChildNodeType& other = *(
s->mNodes[i].getChild());
2503 if (
t->mChildMask.isOn(i)) {
2504 t->mNodes[i].getChild()->topologyUnion(other, mPreserveTiles);
2506 if (!mPreserveTiles ||
t->mValueMask.isOff(i)) {
2507 ChildT* child =
new ChildT(other,
t->mNodes[i].getValue(),
TopologyCopy());
2508 if (
t->mValueMask.isOn(i)) child->setValuesOn();
2509 t->mNodes[i].setChild(child);
2512 }
else if (
s->mValueMask.isOn(i) &&
t->mChildMask.isOn(i)) {
2513 t->mNodes[i].getChild()->setValuesOn();
2517 const OtherInternalNode*
s;
2522 template<
typename ChildT, Index Log2Dim>
2523 template<
typename OtherChildT>
2530 template<
typename ChildT, Index Log2Dim>
2531 template<
typename OtherInternalNode>
2532 struct InternalNode<ChildT, Log2Dim>::TopologyIntersection
2536 { tC = (tC & (sC | sV)) | (tV & sC); }
2539 const ValueType& background) :
s(source),
t(target),
b(background) {
2545 t->mChildMask.foreach(
s->mChildMask,
s->mValueMask,
t->mValueMask, op);
2547 t->mValueMask &=
s->mValueMask;
2548 assert((
t->mValueMask &
t->mChildMask).isOff());
2551 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
2552 if (
t->mChildMask.isOn(i)) {
2553 ChildT* child =
t->mNodes[i].getChild();
2554 if (
s->mChildMask.isOn(i)) {
2555 child->topologyIntersection(*(
s->mNodes[i].getChild()),
b);
2556 }
else if (
s->mValueMask.isOff(i)) {
2558 t->mNodes[i].setValue(
b);
2560 }
else if (
t->mValueMask.isOn(i) &&
s->mChildMask.isOn(i)) {
2561 t->mNodes[i].setChild(
new ChildT(*(
s->mNodes[i].getChild()),
2566 const OtherInternalNode*
s;
2571 template<
typename ChildT, Index Log2Dim>
2572 template<
typename OtherChildT>
2580 template<
typename ChildT, Index Log2Dim>
2581 template<
typename OtherInternalNode>
2582 struct InternalNode<ChildT, Log2Dim>::TopologyDifference
2586 { tC = (tC & (sC | ~sV)) | (tV & sC); }
2589 { tV &= ~((tC & sV) | (sC | sV)); }
2592 const ValueType& background) :
s(source),
t(target),
b(background) {
2599 t->mChildMask.foreach(
s->mChildMask,
s->mValueMask,
t->mValueMask, op1);
2602 t->mValueMask.foreach(
t->mChildMask,
s->mValueMask, oldChildMask, op2);
2603 assert((
t->mValueMask &
t->mChildMask).isOff());
2606 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
2607 if (
t->mChildMask.isOn(i)) {
2608 ChildT* child =
t->mNodes[i].getChild();
2609 if (
s->mChildMask.isOn(i)) {
2610 child->topologyDifference(*(
s->mNodes[i].getChild()),
b);
2611 }
else if (
s->mValueMask.isOn(i)) {
2613 t->mNodes[i].setValue(
b);
2615 }
else if (
t->mValueMask.isOn(i)) {
2616 if (
s->mChildMask.isOn(i)) {
2617 const typename OtherInternalNode::ChildNodeType& other =
2618 *(
s->mNodes[i].getChild());
2619 ChildT* child =
new ChildT(other.origin(),
t->mNodes[i].getValue(),
true);
2620 child->topologyDifference(other,
b);
2621 t->mNodes[i].setChild(child);
2626 const OtherInternalNode*
s;
2631 template<
typename ChildT, Index Log2Dim>
2632 template<
typename OtherChildT>
2644 template<
typename ChildT, Index Log2Dim>
2645 template<
typename CombineOp>
2653 for (
Index i = 0; i < NUM_VALUES; ++i) {
2657 op(args.setARef(mNodes[i].getValue())
2658 .setAIsActive(isValueMaskOn(i))
2661 mNodes[i].setValue(args.result());
2670 }
else if (this->isChildMaskOff(i) && other.
isChildMaskOn(i)) {
2679 child->combine(mNodes[i].
getValue(), isValueMaskOn(i), swappedOp);
2684 this->setChildNode(i, child);
2690 *child = mNodes[i].getChild(),
2694 if (child && otherChild) {
2695 child->combine(*otherChild, op);
2702 template<
typename ChildT, Index Log2Dim>
2703 template<
typename CombineOp>
2709 for (
Index i = 0; i < NUM_VALUES; ++i) {
2710 if (this->isChildMaskOff(i)) {
2712 op(args.
setARef(mNodes[i].getValue())
2713 .setAIsActive(isValueMaskOn(i))
2715 .setBIsActive(valueIsActive));
2716 mNodes[i].setValue(args.
result());
2722 if (child) child->combine(value, valueIsActive, op);
2731 template<
typename ChildT, Index Log2Dim>
2732 template<
typename CombineOp,
typename OtherNodeType>
2739 for (
Index i = 0; i < NUM_VALUES; ++i) {
2743 .setBRef(other1.mNodes[i].getValue())
2744 .setBIsActive(other1.isValueMaskOn(i)));
2746 this->makeChildNodeEmpty(i, args.
result());
2749 if (this->isChildMaskOff(i)) {
2753 : other1.mNodes[i].getChild()->origin();
2762 }
else if (other1.isChildMaskOff(i)) {
2766 other1.mNodes[i].getValue(), other1.isValueMaskOn(i), op);
2771 *other1.mNodes[i].getChild(), op);
2778 template<
typename ChildT, Index Log2Dim>
2779 template<
typename CombineOp,
typename OtherNodeType>
2782 bool valueIsActive, CombineOp& op)
2786 for (
Index i = 0; i < NUM_VALUES; ++i) {
2787 if (other.isChildMaskOff(i)) {
2789 .setAIsActive(valueIsActive)
2790 .setBRef(other.mNodes[i].getValue())
2791 .setBIsActive(other.isValueMaskOn(i)));
2793 this->makeChildNodeEmpty(i, args.
result());
2796 typename OtherNodeType::ChildNodeType* otherChild = other.mNodes[i].getChild();
2798 if (this->isChildMaskOff(i)) {
2805 mNodes[i].getChild()->combine2(value, *otherChild, valueIsActive, op);
2811 template<
typename ChildT, Index Log2Dim>
2812 template<
typename CombineOp,
typename OtherValueType>
2815 bool valueIsActive, CombineOp& op)
2819 for (
Index i = 0; i < NUM_VALUES; ++i) {
2824 .setBIsActive(valueIsActive));
2826 this->makeChildNodeEmpty(i, args.
result());
2831 if (this->isChildMaskOff(i)) {
2833 this->setChildNode(i,
2834 new ChildNodeType(otherChild->origin(), mNodes[i].getValue()));
2838 mNodes[i].getChild()->combine2(*otherChild, value, valueIsActive, op);
2847 template<
typename ChildT, Index Log2Dim>
2851 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2852 iter->writeBuffers(os, toHalf);
2857 template<
typename ChildT, Index Log2Dim>
2861 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2862 iter->readBuffers(is, fromHalf);
2867 template<
typename ChildT, Index Log2Dim>
2870 const CoordBBox& clipBBox,
bool fromHalf)
2872 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2877 iter->readBuffers(is, clipBBox, fromHalf);
2881 ValueType background = zeroVal<ValueType>();
2883 background = *
static_cast<const ValueType*
>(bgPtr);
2885 this->
clip(clipBBox, background);
2892 template<
typename ChildT, Index Log2Dim>
2896 dims.push_back(Log2Dim);
2897 ChildNodeType::getNodeLog2Dims(dims);
2901 template<
typename ChildT, Index Log2Dim>
2905 assert(n<(1<<3*Log2Dim));
2906 xyz.setX(n >> 2*Log2Dim);
2907 n &= ((1<<2*Log2Dim)-1);
2908 xyz.setY(n >> Log2Dim);
2909 xyz.setZ(n & ((1<<Log2Dim)-1));
2913 template<
typename ChildT, Index Log2Dim>
2917 return (((xyz[0] & (DIM-1u)) >> ChildNodeType::TOTAL) << 2*Log2Dim)
2918 + (((xyz[1] & (DIM-1u)) >> ChildNodeType::TOTAL) << Log2Dim)
2919 + ((xyz[2] & (DIM-1u)) >> ChildNodeType::TOTAL);
2923 template<
typename ChildT, Index Log2Dim>
2928 this->offsetToLocalCoord(n, local);
2929 local <<= ChildT::TOTAL;
2930 return local + this->origin();
2937 template<
typename ChildT, Index Log2Dim>
2938 template<
typename ArrayT>
2944 using ArrayChildT =
typename std::conditional<
2946 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2949 array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild()));
2951 iter->getNodes(array);
2957 template<
typename ChildT, Index Log2Dim>
2958 template<
typename ArrayT>
2965 "argument to getNodes() must be an array of const node pointers");
2966 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2969 array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild()));
2971 iter->getNodes(array);
2981 template<
typename ChildT, Index Log2Dim>
2982 template<
typename ArrayT>
2988 using ArrayChildT =
typename std::conditional<
2991 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2992 const Index n = iter.pos();
2994 array.push_back(reinterpret_cast<T>(mNodes[n].getChild()));
2996 mNodes[
n].setValue(value);
2998 iter->stealNodes(array, value, state);
3009 template<
typename ChildT, Index Log2Dim>
3015 for (
Index i = 0; i < NUM_VALUES; ++i) {
3016 if (this->isChildMaskOn(i)) {
3017 mNodes[i].getChild()->resetBackground(oldBackground, newBackground);
3018 }
else if (this->isValueMaskOff(i)) {
3020 mNodes[i].setValue(newBackground);
3028 template<
typename ChildT, Index Log2Dim>
3029 template<
typename OtherChildNodeType, Index OtherLog2Dim>
3034 if (Log2Dim != OtherLog2Dim || mChildMask != other->
mChildMask ||
3036 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3037 if (!iter->hasSameTopology(other->
mNodes[iter.pos()].getChild()))
return false;
3043 template<
typename ChildT, Index Log2Dim>
3048 if (this->isChildMaskOn(i)) {
3049 delete mNodes[i].getChild();
3051 mChildMask.setOn(i);
3054 mNodes[i].setChild(child);
3057 template<
typename ChildT, Index Log2Dim>
3062 assert(mChildMask.isOff(i));
3063 mChildMask.setOn(i);
3065 mNodes[i].setChild(child);
3069 template<
typename ChildT, Index Log2Dim>
3073 if (this->isChildMaskOff(i)) {
3074 mNodes[i].setValue(value);
3078 mChildMask.setOff(i);
3079 mNodes[i].setValue(value);
3084 template<
typename ChildT, Index Log2Dim>
3088 delete this->unsetChildNode(n, value);
3091 template<
typename ChildT, Index Log2Dim>
3095 assert(this->isChildMaskOn(n));
3096 return mNodes[
n].getChild();
3100 template<
typename ChildT, Index Log2Dim>
3101 inline const ChildT*
3104 assert(this->isChildMaskOn(n));
3105 return mNodes[
n].getChild();
3112 #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.
void parallel_for(int64_t start, int64_t end, std::function< void(int64_t index)> &&task, parallel_options opt=parallel_options(0, Split_Y, 1))
ValueIter< InternalNode, const ValueType, MaskOffIterator, ValueAll > ValueAllIter
Index32 nonLeafCount() const
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
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()
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)
#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.
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
__hostdev__ void setValue(uint32_t offset, bool v)
Index32 leafCount() const
typename NodeMaskType::Word W
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...
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
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
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 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
void nodeCount(std::vector< Index32 > &vec) 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)
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 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
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...
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...
GLboolean GLboolean GLboolean b
Index32 childCount() const
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()
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.
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.
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)
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.
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.
ImageBuf OIIO_API zero(ROI roi, int nthreads=0)
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