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>
38 using ValueType =
typename ChildNodeType::ValueType;
39 using BuildType =
typename ChildNodeType::BuildType;
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);
271 #if OPENVDB_ABI_VERSION_NUMBER >= 9
273 Index32 transientData()
const {
return mTransientData; }
275 void setTransientData(
Index32 transientData) { mTransientData = transientData; }
279 void nodeCount(std::vector<Index32> &vec)
const;
310 const ValueType& tolerance = zeroVal<ValueType>())
const;
327 bool& state,
const ValueType& tolerance = zeroVal<ValueType>())
const;
369 template<
typename ModifyOp>
370 void modifyValue(
const Coord& xyz,
const ModifyOp& op);
372 template<
typename ModifyOp>
379 template<
typename AccessorT>
386 template<
typename AccessorT>
393 template<
typename AccessorT>
400 template<
typename AccessorT>
408 template<
typename ModifyOp,
typename AccessorT>
415 template<
typename ModifyOp,
typename AccessorT>
422 template<
typename AccessorT>
429 template<
typename AccessorT>
437 template<
typename AccessorT>
446 template<
typename AccessorT>
455 void writeTopology(std::ostream&,
bool toHalf =
false)
const;
456 void readTopology(std::istream&,
bool fromHalf =
false);
457 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
458 void readBuffers(std::istream&,
bool fromHalf =
false);
459 void readBuffers(std::istream&,
const CoordBBox&,
bool fromHalf =
false);
500 template<
typename DenseT>
501 void copyToDense(
const CoordBBox& bbox, DenseT& dense)
const;
505 template<MergePolicy Policy>
510 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive);
524 template<
typename OtherChildNodeType>
540 template<
typename OtherChildNodeType>
555 template<
typename OtherChildNodeType>
559 template<
typename CombineOp>
561 template<
typename CombineOp>
564 template<
typename CombineOp,
typename OtherNodeType >
566 template<
typename CombineOp,
typename OtherNodeType >
568 template<
typename CombineOp,
typename OtherValueType>
585 template<
typename AccessorT>
596 template<
typename NodeT>
616 template<
typename AccessorT>
622 template<
typename NodeType> NodeType*
probeNode(
const Coord& xyz);
623 template<
typename NodeType>
const NodeType*
probeConstNode(
const Coord& xyz)
const;
629 template<
typename NodeType,
typename AccessorT>
631 template<
typename NodeType,
typename AccessorT>
646 template<
typename AccessorT>
648 template<
typename AccessorT>
650 template<
typename AccessorT>
664 template<
typename AccessorT>
690 template<
typename ArrayT>
692 template<
typename ArrayT>
719 template<
typename ArrayT>
728 template<
typename OtherChildNodeType, Index OtherLog2Dim>
785 struct VoxelizeActiveTiles;
786 template<
typename OtherInternalNode>
struct DeepCopy;
798 #if OPENVDB_ABI_VERSION_NUMBER >= 9
811 template<
typename ChildT1, Index Dim1,
typename NodeT2>
816 template<
typename ChildT1, Index Dim1,
typename ChildT2>
826 template<
typename ChildT, Index Log2Dim>
830 for (
Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(background);
834 template<
typename ChildT, Index Log2Dim>
837 mOrigin(origin[0] & ~(DIM - 1),
838 origin[1] & ~(DIM - 1),
839 origin[2] & ~(DIM - 1))
848 template<
typename ChildT, Index Log2Dim>
852 : mOrigin(origin[0] & ~(DIM-1), origin[1] & ~(DIM-1), origin[2] & ~(DIM-1))
858 template<
typename ChildT, Index Log2Dim>
859 template<
typename OtherInternalNode>
867 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
868 if (
s->mChildMask.isOff(i)) {
869 t->mNodes[i].setValue(
ValueType(
s->mNodes[i].getValue()));
875 const OtherInternalNode*
s;
879 template<
typename ChildT, Index Log2Dim>
882 : mChildMask(other.mChildMask)
883 , mValueMask(other.mValueMask)
884 , mOrigin(other.mOrigin)
886 , mTransientData(other.mTransientData)
894 template<
typename ChildT, Index Log2Dim>
895 template<
typename OtherChildNodeType>
898 : mChildMask(other.mChildMask)
899 , mValueMask(other.mValueMask)
900 , mOrigin(other.mOrigin)
902 , mTransientData(other.mTransientData)
908 template<
typename ChildT, Index Log2Dim>
909 template<
typename OtherInternalNode>
913 const ValueType& background) :
s(source),
t(target),
b(background) {
918 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
919 if (
s->isChildMaskOn(i)) {
923 t->mNodes[i].setValue(
b);
927 const OtherInternalNode*
s;
932 template<
typename ChildT, Index Log2Dim>
933 template<
typename OtherChildNodeType>
937 : mChildMask(other.mChildMask)
938 , mValueMask(other.mValueMask)
939 , mOrigin(other.mOrigin)
941 , mTransientData(other.mTransientData)
947 template<
typename ChildT, Index Log2Dim>
948 template<
typename OtherInternalNode>
953 :
s(source),
t(target), offV(offValue), onV(onValue) {
957 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
958 if (
s->isChildMaskOn(i)) {
962 t->mNodes[i].setValue(
s->isValueMaskOn(i) ? onV : offV);
966 const OtherInternalNode*
s;
971 template<
typename ChildT, Index Log2Dim>
972 template<
typename OtherChildNodeType>
977 : mChildMask(other.mChildMask)
978 , mValueMask(other.mValueMask)
979 , mOrigin(other.mOrigin)
981 , mTransientData(other.mTransientData)
988 template<
typename ChildT, Index Log2Dim>
992 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
993 delete mNodes[iter.pos()].getChild();
1001 template<
typename ChildT, Index Log2Dim>
1007 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1008 sum += iter->leafCount();
1013 template<
typename ChildT, Index Log2Dim>
1017 assert(vec.size() > ChildNodeType::LEVEL);
1018 const auto count = mChildMask.countOn();
1019 if (ChildNodeType::LEVEL > 0 && count > 0) {
1020 for (
auto iter = this->cbeginChildOn(); iter; ++iter) iter->nodeCount(vec);
1022 vec[ChildNodeType::LEVEL] +=
count;
1026 template<
typename ChildT, Index Log2Dim>
1032 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1033 sum += iter->nonLeafCount();
1039 template<
typename ChildT, Index Log2Dim>
1043 return this->getChildMask().countOn();
1047 template<
typename ChildT, Index Log2Dim>
1051 Index64 sum = ChildT::NUM_VOXELS * mValueMask.countOn();
1052 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1053 sum += iter->onVoxelCount();
1059 template<
typename ChildT, Index Log2Dim>
1063 Index64 sum = ChildT::NUM_VOXELS * (NUM_VALUES-mValueMask.countOn()-mChildMask.countOn());
1064 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1065 sum += iter->offVoxelCount();
1071 template<
typename ChildT, Index Log2Dim>
1076 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1077 sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount();
1083 template<
typename ChildT, Index Log2Dim>
1088 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1089 sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount();
1094 template<
typename ChildT, Index Log2Dim>
1098 Index64 sum = mValueMask.countOn();
1099 for (
ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) {
1100 sum += iter->onTileCount();
1105 template<
typename ChildT, Index Log2Dim>
1110 + mValueMask.memUsage() +
sizeof(mOrigin);
1111 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1112 sum += iter->memUsage();
1118 template<
typename ChildT, Index Log2Dim>
1122 if (bbox.isInside(
this->getNodeBoundingBox()))
return;
1125 bbox.expand(i.getCoord(), ChildT::DIM);
1128 i->evalActiveBoundingBox(bbox, visitVoxels);
1136 template<
typename ChildT, Index Log2Dim>
1142 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1143 const Index i = iter.pos();
1144 ChildT* child = mNodes[i].getChild();
1145 child->prune(tolerance);
1146 if (child->isConstant(value, state, tolerance)) {
1148 mChildMask.setOff(i);
1149 mValueMask.set(i, state);
1150 mNodes[i].setValue(value);
1159 template<
typename ChildT, Index Log2Dim>
1160 template<
typename NodeT>
1165 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1167 const Index n = this->coordToOffset(xyz);
1168 if (mChildMask.isOff(n))
return nullptr;
1169 ChildT* child = mNodes[
n].getChild();
1171 mChildMask.setOff(n);
1172 mValueMask.set(n, state);
1173 mNodes[
n].setValue(value);
1176 ?
reinterpret_cast<NodeT*
>(child)
1177 : child->template stealNode<NodeT>(xyz, value, state);
1185 template<
typename ChildT, Index Log2Dim>
1186 template<
typename NodeT>
1191 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1193 const Index n = this->coordToOffset(xyz);
1194 if (mChildMask.isOff(n))
return nullptr;
1195 ChildT* child = mNodes[
n].getChild();
1197 ?
reinterpret_cast<NodeT*
>(child)
1198 : child->template probeNode<NodeT>(xyz);
1203 template<
typename ChildT, Index Log2Dim>
1204 template<
typename NodeT,
typename AccessorT>
1209 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1211 const Index n = this->coordToOffset(xyz);
1212 if (mChildMask.isOff(n))
return nullptr;
1213 ChildT* child = mNodes[
n].getChild();
1214 acc.insert(xyz, child);
1216 ?
reinterpret_cast<NodeT*
>(child)
1217 : child->template probeNodeAndCache<NodeT>(xyz, acc);
1222 template<
typename ChildT, Index Log2Dim>
1223 template<
typename NodeT>
1228 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1230 const Index n = this->coordToOffset(xyz);
1231 if (mChildMask.isOff(n))
return nullptr;
1232 const ChildT* child = mNodes[
n].getChild();
1234 ?
reinterpret_cast<const NodeT*
>(child)
1235 : child->template probeConstNode<NodeT>(xyz);
1240 template<
typename ChildT, Index Log2Dim>
1241 template<
typename NodeT,
typename AccessorT>
1246 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1248 const Index n = this->coordToOffset(xyz);
1249 if (mChildMask.isOff(n))
return nullptr;
1250 const ChildT* child = mNodes[
n].getChild();
1251 acc.insert(xyz, child);
1253 ?
reinterpret_cast<const NodeT*
>(child)
1254 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
1262 template<
typename ChildT, Index Log2Dim>
1263 inline typename ChildT::LeafNodeType*
1266 return this->
template probeNode<LeafNodeType>(xyz);
1270 template<
typename ChildT, Index Log2Dim>
1271 template<
typename AccessorT>
1272 inline typename ChildT::LeafNodeType*
1275 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
1279 template<
typename ChildT, Index Log2Dim>
1280 template<
typename AccessorT>
1281 inline const typename ChildT::LeafNodeType*
1284 return this->probeConstLeafAndCache(xyz, acc);
1288 template<
typename ChildT, Index Log2Dim>
1289 inline const typename ChildT::LeafNodeType*
1292 return this->
template probeConstNode<LeafNodeType>(xyz);
1296 template<
typename ChildT, Index Log2Dim>
1297 template<
typename AccessorT>
1298 inline const typename ChildT::LeafNodeType*
1301 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
1308 template<
typename ChildT, Index Log2Dim>
1312 assert(leaf !=
nullptr);
1313 const Coord& xyz = leaf->origin();
1314 const Index n = this->coordToOffset(xyz);
1315 ChildT* child =
nullptr;
1316 if (mChildMask.isOff(n)) {
1317 if (ChildT::LEVEL>0) {
1318 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1320 child =
reinterpret_cast<ChildT*
>(leaf);
1322 this->setChildNode(n, child);
1324 if (ChildT::LEVEL>0) {
1325 child = mNodes[
n].getChild();
1327 delete mNodes[
n].getChild();
1328 child =
reinterpret_cast<ChildT*
>(leaf);
1329 mNodes[
n].setChild(child);
1332 child->addLeaf(leaf);
1336 template<
typename ChildT, Index Log2Dim>
1337 template<
typename AccessorT>
1341 assert(leaf !=
nullptr);
1342 const Coord& xyz = leaf->origin();
1343 const Index n = this->coordToOffset(xyz);
1344 ChildT* child =
nullptr;
1345 if (mChildMask.isOff(n)) {
1346 if (ChildT::LEVEL>0) {
1347 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1348 acc.insert(xyz, child);
1350 child =
reinterpret_cast<ChildT*
>(leaf);
1352 this->setChildNode(n, child);
1354 if (ChildT::LEVEL>0) {
1355 child = mNodes[
n].getChild();
1356 acc.insert(xyz, child);
1358 delete mNodes[
n].getChild();
1359 child =
reinterpret_cast<ChildT*
>(leaf);
1360 mNodes[
n].setChild(child);
1363 child->addLeafAndCache(leaf, acc);
1370 template<
typename ChildT, Index Log2Dim>
1375 const Coord& xyz = child->origin();
1377 if (Coord((xyz & ~(DIM-1))) != this->origin())
return false;
1379 const Index n = this->coordToOffset(xyz);
1381 this->resetChildNode(n, child);
1386 template<
typename ChildT, Index Log2Dim>
1390 assert(n < NUM_VALUES);
1391 this->makeChildNodeEmpty(n, value);
1392 mValueMask.set(n, state);
1396 template<
typename ChildT, Index Log2Dim>
1401 if (LEVEL >= level) {
1402 const Index n = this->coordToOffset(xyz);
1403 if (mChildMask.isOff(n)) {
1404 if (LEVEL > level) {
1405 ChildT* child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1406 this->setChildNode(n, child);
1407 child->addTile(level, xyz, value, state);
1409 mValueMask.set(n, state);
1410 mNodes[
n].setValue(value);
1413 ChildT* child = mNodes[
n].getChild();
1414 if (LEVEL > level) {
1415 child->addTile(level, xyz, value, state);
1418 mChildMask.setOff(n);
1419 mValueMask.set(n, state);
1420 mNodes[
n].setValue(value);
1427 template<
typename ChildT, Index Log2Dim>
1428 template<
typename AccessorT>
1433 if (LEVEL >= level) {
1434 const Index n = this->coordToOffset(xyz);
1435 if (mChildMask.isOff(n)) {
1436 if (LEVEL > level) {
1437 ChildT* child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1438 this->setChildNode(n, child);
1439 acc.insert(xyz, child);
1440 child->addTileAndCache(level, xyz, value, state, acc);
1442 mValueMask.set(n, state);
1443 mNodes[
n].setValue(value);
1446 ChildT* child = mNodes[
n].getChild();
1447 if (LEVEL > level) {
1448 acc.insert(xyz, child);
1449 child->addTileAndCache(level, xyz, value, state, acc);
1452 mChildMask.setOff(n);
1453 mValueMask.set(n, state);
1454 mNodes[
n].setValue(value);
1464 template<
typename ChildT, Index Log2Dim>
1465 inline typename ChildT::LeafNodeType*
1468 const Index n = this->coordToOffset(xyz);
1469 ChildT* child =
nullptr;
1470 if (mChildMask.isOff(n)) {
1471 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1472 this->setChildNode(n, child);
1474 child = mNodes[
n].getChild();
1476 return child->touchLeaf(xyz);
1480 template<
typename ChildT, Index Log2Dim>
1481 template<
typename AccessorT>
1482 inline typename ChildT::LeafNodeType*
1485 const Index n = this->coordToOffset(xyz);
1486 if (mChildMask.isOff(n)) {
1487 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), mValueMask.isOn(n)));
1489 acc.insert(xyz, mNodes[n].getChild());
1490 return mNodes[
n].getChild()->touchLeafAndCache(xyz, acc);
1497 template<
typename ChildT, Index Log2Dim>
1502 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1504 firstValue = mNodes[0].getValue();
1505 for (
Index i = 1; i < NUM_VALUES; ++i) {
1517 template<
typename ChildT, Index Log2Dim>
1525 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1526 minValue = maxValue = mNodes[0].getValue();
1527 for (
Index i = 1; i < NUM_VALUES; ++i) {
1530 if ((maxValue - v) > tolerance)
return false;
1532 }
else if (v > maxValue) {
1533 if ((v - minValue) > tolerance)
return false;
1544 template<
typename ChildT, Index Log2Dim>
1551 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1552 if (iter->hasActiveTiles())
return true;
1559 template<
typename ChildT, Index Log2Dim>
1563 const Index n = this->coordToOffset(xyz);
1564 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1565 return mNodes[
n].getChild()->isValueOn(xyz);
1568 template<
typename ChildT, Index Log2Dim>
1569 template<
typename AccessorT>
1573 const Index n = this->coordToOffset(xyz);
1574 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1575 acc.insert(xyz, mNodes[n].getChild());
1576 return mNodes[
n].getChild()->isValueOnAndCache(xyz, acc);
1580 template<
typename ChildT, Index Log2Dim>
1581 inline const typename ChildT::ValueType&
1584 const Index n = this->coordToOffset(xyz);
1585 return this->isChildMaskOff(n) ? mNodes[
n].getValue()
1586 : mNodes[
n].getChild()->getValue(xyz);
1589 template<
typename ChildT, Index Log2Dim>
1590 template<
typename AccessorT>
1591 inline const typename ChildT::ValueType&
1594 const Index n = this->coordToOffset(xyz);
1595 if (this->isChildMaskOn(n)) {
1596 acc.insert(xyz, mNodes[n].getChild());
1597 return mNodes[
n].getChild()->getValueAndCache(xyz, acc);
1599 return mNodes[
n].getValue();
1603 template<
typename ChildT, Index Log2Dim>
1607 const Index n = this->coordToOffset(xyz);
1608 return this->isChildMaskOff(n) ? LEVEL : mNodes[
n].getChild()->getValueLevel(xyz);
1611 template<
typename ChildT, Index Log2Dim>
1612 template<
typename AccessorT>
1616 const Index n = this->coordToOffset(xyz);
1617 if (this->isChildMaskOn(n)) {
1618 acc.insert(xyz, mNodes[n].getChild());
1619 return mNodes[
n].getChild()->getValueLevelAndCache(xyz, acc);
1625 template<
typename ChildT, Index Log2Dim>
1629 const Index n = this->coordToOffset(xyz);
1630 if (this->isChildMaskOff(n)) {
1631 value = mNodes[
n].getValue();
1632 return this->isValueMaskOn(n);
1634 return mNodes[
n].getChild()->probeValue(xyz, value);
1637 template<
typename ChildT, Index Log2Dim>
1638 template<
typename AccessorT>
1643 const Index n = this->coordToOffset(xyz);
1644 if (this->isChildMaskOn(n)) {
1645 acc.insert(xyz, mNodes[n].getChild());
1646 return mNodes[
n].getChild()->probeValueAndCache(xyz, value, acc);
1648 value = mNodes[
n].getValue();
1649 return this->isValueMaskOn(n);
1653 template<
typename ChildT, Index Log2Dim>
1657 const Index n = this->coordToOffset(xyz);
1658 bool hasChild = this->isChildMaskOn(n);
1659 if (!hasChild && this->isValueMaskOn(n)) {
1663 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
true));
1665 if (hasChild) mNodes[
n].getChild()->setValueOff(xyz);
1669 template<
typename ChildT, Index Log2Dim>
1673 const Index n = this->coordToOffset(xyz);
1674 bool hasChild = this->isChildMaskOn(n);
1675 if (!hasChild && !this->isValueMaskOn(n)) {
1679 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
false));
1681 if (hasChild) mNodes[
n].getChild()->setValueOn(xyz);
1685 template<
typename ChildT, Index Log2Dim>
1690 bool hasChild = this->isChildMaskOn(n);
1692 const bool active = this->isValueMaskOn(n);
1698 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1701 if (hasChild) mNodes[
n].getChild()->setValueOff(xyz, value);
1704 template<
typename ChildT, Index Log2Dim>
1705 template<
typename AccessorT>
1711 bool hasChild = this->isChildMaskOn(n);
1713 const bool active = this->isValueMaskOn(n);
1719 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1723 ChildT* child = mNodes[
n].getChild();
1724 acc.insert(xyz, child);
1725 child->setValueOffAndCache(xyz, value, acc);
1730 template<
typename ChildT, Index Log2Dim>
1734 const Index n = this->coordToOffset(xyz);
1735 bool hasChild = this->isChildMaskOn(n);
1737 const bool active = this->isValueMaskOn(n);
1743 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1746 if (hasChild) mNodes[
n].getChild()->setValueOn(xyz, value);
1749 template<
typename ChildT, Index Log2Dim>
1750 template<
typename AccessorT>
1755 const Index n = this->coordToOffset(xyz);
1756 bool hasChild = this->isChildMaskOn(n);
1758 const bool active = this->isValueMaskOn(n);
1764 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1768 acc.insert(xyz, mNodes[n].getChild());
1769 mNodes[
n].getChild()->setValueAndCache(xyz, value, acc);
1774 template<
typename ChildT, Index Log2Dim>
1778 const Index n = this->coordToOffset(xyz);
1779 bool hasChild = this->isChildMaskOn(n);
1783 const bool active = this->isValueMaskOn(n);
1785 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1787 if (hasChild) mNodes[
n].getChild()->setValueOnly(xyz, value);
1790 template<
typename ChildT, Index Log2Dim>
1791 template<
typename AccessorT>
1796 const Index n = this->coordToOffset(xyz);
1797 bool hasChild = this->isChildMaskOn(n);
1801 const bool active = this->isValueMaskOn(n);
1803 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1806 acc.insert(xyz, mNodes[n].getChild());
1807 mNodes[
n].getChild()->setValueOnlyAndCache(xyz, value, acc);
1812 template<
typename ChildT, Index Log2Dim>
1816 const Index n = this->coordToOffset(xyz);
1817 bool hasChild = this->isChildMaskOn(n);
1819 if (on != this->isValueMaskOn(n)) {
1824 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1827 if (hasChild) mNodes[
n].getChild()->setActiveState(xyz, on);
1830 template<
typename ChildT, Index Log2Dim>
1831 template<
typename AccessorT>
1835 const Index n = this->coordToOffset(xyz);
1836 bool hasChild = this->isChildMaskOn(n);
1838 if (on != this->isValueMaskOn(n)) {
1843 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1847 ChildT* child = mNodes[
n].getChild();
1848 acc.insert(xyz, child);
1849 child->setActiveStateAndCache(xyz, on, acc);
1854 template<
typename ChildT, Index Log2Dim>
1858 mValueMask = !mChildMask;
1859 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1860 mNodes[iter.pos()].getChild()->setValuesOn();
1865 template<
typename ChildT, Index Log2Dim>
1866 template<
typename ModifyOp>
1871 bool hasChild = this->isChildMaskOn(n);
1875 const bool active = this->isValueMaskOn(n);
1876 bool createChild = !active;
1880 const ValueType& tileVal = mNodes[
n].getValue();
1887 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1890 if (hasChild) mNodes[
n].getChild()->modifyValue(xyz, op);
1893 template<
typename ChildT, Index Log2Dim>
1894 template<
typename ModifyOp,
typename AccessorT>
1900 bool hasChild = this->isChildMaskOn(n);
1904 const bool active = this->isValueMaskOn(n);
1905 bool createChild = !active;
1909 const ValueType& tileVal = mNodes[
n].getValue();
1916 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1921 acc.insert(xyz, child);
1922 child->modifyValueAndCache(xyz, op, acc);
1927 template<
typename ChildT, Index Log2Dim>
1928 template<
typename ModifyOp>
1933 bool hasChild = this->isChildMaskOn(n);
1935 const bool tileState = this->isValueMaskOn(n);
1936 const ValueType& tileVal = mNodes[
n].getValue();
1937 bool modifiedState = !tileState;
1939 op(modifiedVal, modifiedState);
1944 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
1947 if (hasChild) mNodes[
n].getChild()->modifyValueAndActiveState(xyz, op);
1950 template<
typename ChildT, Index Log2Dim>
1951 template<
typename ModifyOp,
typename AccessorT>
1954 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
1957 bool hasChild = this->isChildMaskOn(n);
1959 const bool tileState = this->isValueMaskOn(n);
1960 const ValueType& tileVal = mNodes[
n].getValue();
1961 bool modifiedState = !tileState;
1963 op(modifiedVal, modifiedState);
1968 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
1973 acc.insert(xyz, child);
1974 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
1982 template<
typename ChildT, Index Log2Dim>
1986 CoordBBox nodeBBox = this->getNodeBoundingBox();
1987 if (!clipBBox.hasOverlap(nodeBBox)) {
1989 this->
fill(nodeBBox, background,
false);
1990 }
else if (clipBBox.isInside(nodeBBox)) {
1999 for (
Index pos = 0; pos < NUM_VALUES; ++pos) {
2000 const Coord xyz = this->offsetToGlobalCoord(pos);
2001 CoordBBox tileBBox(xyz, xyz.offsetBy(ChildT::DIM - 1));
2002 if (!clipBBox.hasOverlap(tileBBox)) {
2005 this->makeChildNodeEmpty(pos, background);
2006 mValueMask.setOff(pos);
2007 }
else if (!clipBBox.isInside(tileBBox)) {
2010 if (this->isChildMaskOn(pos)) {
2011 mNodes[pos].getChild()->clip(clipBBox, background);
2015 tileBBox.intersect(clipBBox);
2017 const bool on = this->isValueMaskOn(pos);
2018 mNodes[pos].setValue(background);
2019 mValueMask.setOff(pos);
2020 this->
fill(tileBBox, val, on);
2032 template<
typename ChildT, Index Log2Dim>
2036 auto clippedBBox = this->getNodeBoundingBox();
2037 clippedBBox.intersect(bbox);
2038 if (!clippedBBox)
return;
2042 Coord xyz, tileMin, tileMax;
2043 for (
int x = clippedBBox.min().x();
x <= clippedBBox.max().x();
x = tileMax.x() + 1) {
2045 for (
int y = clippedBBox.min().y();
y <= clippedBBox.max().y();
y = tileMax.y() + 1) {
2047 for (
int z = clippedBBox.min().z();
z <= clippedBBox.max().z();
z = tileMax.z() + 1) {
2051 const Index n = this->coordToOffset(xyz);
2052 tileMin = this->offsetToGlobalCoord(n);
2053 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2055 if (xyz != tileMin || Coord::lessThan(clippedBBox.max(), tileMax)) {
2059 ChildT* child =
nullptr;
2060 if (this->isChildMaskOff(n)) {
2063 child =
new ChildT{xyz, mNodes[
n].getValue(), this->isValueMaskOn(n)};
2064 this->setChildNode(n, child);
2066 child = mNodes[
n].getChild();
2072 child->fill(CoordBBox(xyz, tmp), value, active);
2079 this->makeChildNodeEmpty(n, value);
2080 mValueMask.set(n, active);
2088 template<
typename ChildT, Index Log2Dim>
2092 auto clippedBBox = this->getNodeBoundingBox();
2093 clippedBBox.intersect(bbox);
2094 if (!clippedBBox)
return;
2098 Coord xyz, tileMin, tileMax;
2099 for (
int x = clippedBBox.min().x();
x <= clippedBBox.max().x();
x = tileMax.x() + 1) {
2101 for (
int y = clippedBBox.min().y();
y <= clippedBBox.max().y();
y = tileMax.y() + 1) {
2103 for (
int z = clippedBBox.min().z();
z <= clippedBBox.max().z();
z = tileMax.z() + 1) {
2107 const auto n = this->coordToOffset(xyz);
2110 ChildT* child =
nullptr;
2111 if (this->isChildMaskOn(
n)) {
2112 child = mNodes[
n].getChild();
2116 child =
new ChildT{xyz, mNodes[
n].getValue(), this->isValueMaskOn(
n)};
2117 this->setChildNode(
n, child);
2121 tileMin = this->offsetToGlobalCoord(
n);
2122 tileMax = tileMin.offsetBy(ChildT::DIM - 1);
2125 child->denseFill(CoordBBox{xyz, clippedBBox.max()},
value, active);
2135 template<
typename ChildT, Index Log2Dim>
2136 template<
typename DenseT>
2140 using DenseValueType =
typename DenseT::ValueType;
2142 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2143 const Coord&
min = dense.bbox().min();
2144 for (Coord xyz = bbox.min(),
max; xyz[0] <= bbox.max()[0]; xyz[0] =
max[0] + 1) {
2145 for (xyz[1] = bbox.min()[1]; xyz[1] <= bbox.max()[1]; xyz[1] =
max[1] + 1) {
2146 for (xyz[2] = bbox.min()[2]; xyz[2] <= bbox.max()[2]; xyz[2] =
max[2] + 1) {
2147 const Index n = this->coordToOffset(xyz);
2149 max = this->offsetToGlobalCoord(n).offsetBy(ChildT::DIM-1);
2154 if (this->isChildMaskOn(n)) {
2155 mNodes[
n].getChild()->copyToDense(sub, dense);
2158 sub.translate(-min);
2159 DenseValueType* a0 = dense.data() + zStride*sub.min()[2];
2160 for (
Int32 x=sub.min()[0], ex=sub.max()[0]+1;
x<ex; ++
x) {
2161 DenseValueType* a1 = a0 +
x*xStride;
2162 for (
Int32 y=sub.min()[1], ey=sub.max()[1]+1;
y<ey; ++
y) {
2163 DenseValueType* a2 = a1 +
y*yStride;
2164 for (
Int32 z = sub.min()[2], ez = sub.max()[2]+1;
2165 z < ez; ++
z, a2 += zStride)
2167 *a2 = DenseValueType(value);
2181 template<
typename ChildT, Index Log2Dim>
2185 mChildMask.save(os);
2186 mValueMask.save(os);
2190 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[NUM_VALUES]);
2193 for (
Index i = 0; i < NUM_VALUES; ++i) {
2194 values[i] = (mChildMask.isOff(i) ? mNodes[i].getValue() :
zero);
2200 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2201 iter->writeTopology(os, toHalf);
2206 template<
typename ChildT, Index Log2Dim>
2213 mChildMask.load(is);
2214 mValueMask.load(is);
2217 for (
Index i = 0; i < NUM_VALUES; ++i) {
2218 if (this->isChildMaskOn(i)) {
2221 mNodes[i].setChild(child);
2222 child->readTopology(is);
2225 is.read(reinterpret_cast<char*>(&value),
sizeof(
ValueType));
2226 mNodes[i].setValue(value);
2230 const bool oldVersion =
2232 const Index numValues = (oldVersion ? mChildMask.countOff() : NUM_VALUES);
2236 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[numValues]);
2243 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2244 mNodes[iter.pos()].setValue(values[n++]);
2246 assert(n == numValues);
2248 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2249 mNodes[iter.pos()].setValue(values[iter.pos()]);
2254 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2256 mNodes[iter.pos()].setChild(child);
2257 child->readTopology(is, fromHalf);
2266 template<
typename ChildT, Index Log2Dim>
2267 inline const typename ChildT::ValueType&
2270 return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].getValue());
2274 template<
typename ChildT, Index Log2Dim>
2275 inline const typename ChildT::ValueType&
2278 const Index n = NUM_VALUES - 1;
2279 return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].getValue());
2286 template<
typename ChildT, Index Log2Dim>
2290 for (
Index i = 0; i < NUM_VALUES; ++i) {
2291 if (this->isChildMaskOn(i)) {
2292 mNodes[i].getChild()->negate();
2304 template<
typename ChildT, Index Log2Dim>
2316 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
2317 if (mNode->mChildMask.isOn(i)) {
2318 mNode->mNodes[i].getChild()->voxelizeActiveTiles(
true);
2319 }
else if (mNode->mValueMask.isOn(i)) {
2320 const Coord &ijk = mNode->offsetToGlobalCoord(i);
2322 child->voxelizeActiveTiles(
true);
2323 mNode->mNodes[i].setChild(child);
2330 template<
typename ChildT, Index Log2Dim>
2337 for (
ValueOnIter iter = this->beginValueOn(); iter; ++iter) {
2338 this->setChildNode(iter.pos(),
2341 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter)
2342 iter->voxelizeActiveTiles(
false);
2350 template<
typename ChildT, Index Log2Dim>
2351 template<MergePolicy Policy>
2364 const Index n = iter.pos();
2365 if (mChildMask.isOn(n)) {
2367 mNodes[
n].getChild()->template merge<MERGE_ACTIVE_STATES>(*iter,
2368 background, otherBackground);
2369 }
else if (mValueMask.isOff(n)) {
2376 child->resetBackground(otherBackground, background);
2377 this->setChildNode(n, child);
2383 const Index n = iter.pos();
2384 if (mValueMask.isOff(n)) {
2386 this->makeChildNodeEmpty(n, iter.getValue());
2387 mValueMask.setOn(n);
2396 const Index n = iter.pos();
2397 if (mChildMask.isOn(n)) {
2399 mNodes[
n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2407 child->resetBackground(otherBackground, background);
2408 this->setChildNode(n, child);
2418 const Index n = iter.pos();
2419 if (mChildMask.isOn(n)) {
2421 mNodes[
n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2428 child->resetBackground(otherBackground, background);
2429 if (mValueMask.isOn(n)) {
2431 child->template merge<Policy>(mNodes[
n].getValue(),
true);
2432 mValueMask.setOff(n);
2434 mChildMask.setOn(n);
2435 mNodes[
n].setChild(child);
2441 const Index n = iter.pos();
2442 if (mChildMask.isOn(n)) {
2444 mNodes[
n].getChild()->template merge<Policy>(iter.getValue(),
true);
2445 }
else if (mValueMask.isOff(n)) {
2447 mNodes[
n].setValue(iter.getValue());
2448 mValueMask.setOn(n);
2459 template<
typename ChildT, Index Log2Dim>
2460 template<MergePolicy Policy>
2469 if (!tileActive)
return;
2472 for (
ValueOffIter iter = this->beginValueOff(); iter; ++iter) {
2473 const Index n = iter.pos();
2474 if (mChildMask.isOn(n)) {
2476 mNodes[
n].getChild()->template merge<Policy>(tileValue,
true);
2479 iter.setValue(tileValue);
2480 mValueMask.setOn(n);
2490 template<
typename ChildT, Index Log2Dim>
2491 template<
typename OtherInternalNode>
2496 { tV = (tV | sV) & ~tC; }
2499 :
s(source),
t(target), mPreserveTiles(preserveTiles) {
2504 if (!mPreserveTiles)
t->mChildMask |=
s->mChildMask;
2505 else t->mChildMask |= (
s->mChildMask & !
t->mValueMask);
2508 t->mValueMask.foreach(
s->mValueMask,
t->mChildMask, op);
2509 assert((
t->mValueMask &
t->mChildMask).isOff());
2512 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
2513 if (
s->mChildMask.isOn(i)) {
2514 const typename OtherInternalNode::ChildNodeType& other = *(
s->mNodes[i].getChild());
2515 if (
t->mChildMask.isOn(i)) {
2516 t->mNodes[i].getChild()->topologyUnion(other, mPreserveTiles);
2518 if (!mPreserveTiles ||
t->mValueMask.isOff(i)) {
2519 ChildT* child =
new ChildT(other,
t->mNodes[i].getValue(),
TopologyCopy());
2520 if (
t->mValueMask.isOn(i)) child->setValuesOn();
2521 t->mNodes[i].setChild(child);
2524 }
else if (
s->mValueMask.isOn(i) &&
t->mChildMask.isOn(i)) {
2525 t->mNodes[i].getChild()->setValuesOn();
2529 const OtherInternalNode*
s;
2534 template<
typename ChildT, Index Log2Dim>
2535 template<
typename OtherChildT>
2542 template<
typename ChildT, Index Log2Dim>
2543 template<
typename OtherInternalNode>
2544 struct InternalNode<ChildT, Log2Dim>::TopologyIntersection
2548 { tC = (tC & (sC | sV)) | (tV & sC); }
2551 const ValueType& background) :
s(source),
t(target),
b(background) {
2557 t->mChildMask.foreach(
s->mChildMask,
s->mValueMask,
t->mValueMask, op);
2559 t->mValueMask &=
s->mValueMask;
2560 assert((
t->mValueMask &
t->mChildMask).isOff());
2563 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
2564 if (
t->mChildMask.isOn(i)) {
2565 ChildT* child =
t->mNodes[i].getChild();
2566 if (
s->mChildMask.isOn(i)) {
2567 child->topologyIntersection(*(
s->mNodes[i].getChild()),
b);
2568 }
else if (
s->mValueMask.isOff(i)) {
2570 t->mNodes[i].setValue(
b);
2572 }
else if (
t->mValueMask.isOn(i) &&
s->mChildMask.isOn(i)) {
2573 t->mNodes[i].setChild(
new ChildT(*(
s->mNodes[i].getChild()),
2578 const OtherInternalNode*
s;
2583 template<
typename ChildT, Index Log2Dim>
2584 template<
typename OtherChildT>
2592 template<
typename ChildT, Index Log2Dim>
2593 template<
typename OtherInternalNode>
2594 struct InternalNode<ChildT, Log2Dim>::TopologyDifference
2598 { tC = (tC & (sC | ~sV)) | (tV & sC); }
2601 { tV &= ~((tC & sV) | (sC | sV)); }
2604 const ValueType& background) :
s(source),
t(target),
b(background) {
2611 t->mChildMask.foreach(
s->mChildMask,
s->mValueMask,
t->mValueMask, op1);
2614 t->mValueMask.foreach(
t->mChildMask,
s->mValueMask, oldChildMask, op2);
2615 assert((
t->mValueMask &
t->mChildMask).isOff());
2618 for (
Index i = r.begin(),
end=r.end(); i!=
end; ++i) {
2619 if (
t->mChildMask.isOn(i)) {
2620 ChildT* child =
t->mNodes[i].getChild();
2621 if (
s->mChildMask.isOn(i)) {
2622 child->topologyDifference(*(
s->mNodes[i].getChild()),
b);
2623 }
else if (
s->mValueMask.isOn(i)) {
2625 t->mNodes[i].setValue(
b);
2627 }
else if (
t->mValueMask.isOn(i)) {
2628 if (
s->mChildMask.isOn(i)) {
2629 const typename OtherInternalNode::ChildNodeType& other =
2630 *(
s->mNodes[i].getChild());
2631 ChildT* child =
new ChildT(other.origin(),
t->mNodes[i].getValue(),
true);
2632 child->topologyDifference(other,
b);
2633 t->mNodes[i].setChild(child);
2638 const OtherInternalNode*
s;
2643 template<
typename ChildT, Index Log2Dim>
2644 template<
typename OtherChildT>
2656 template<
typename ChildT, Index Log2Dim>
2657 template<
typename CombineOp>
2665 for (
Index i = 0; i < NUM_VALUES; ++i) {
2669 op(args.setARef(mNodes[i].getValue())
2670 .setAIsActive(isValueMaskOn(i))
2673 mNodes[i].setValue(args.result());
2674 mValueMask.set(i, args.resultIsActive());
2682 }
else if (this->isChildMaskOff(i) && other.
isChildMaskOn(i)) {
2691 child->combine(mNodes[i].getValue(), isValueMaskOn(i), swappedOp);
2696 this->setChildNode(i, child);
2702 *child = mNodes[i].getChild(),
2706 if (child && otherChild) {
2707 child->combine(*otherChild, op);
2714 template<
typename ChildT, Index Log2Dim>
2715 template<
typename CombineOp>
2721 for (
Index i = 0; i < NUM_VALUES; ++i) {
2722 if (this->isChildMaskOff(i)) {
2724 op(args.
setARef(mNodes[i].getValue())
2725 .setAIsActive(isValueMaskOn(i))
2727 .setBIsActive(valueIsActive));
2728 mNodes[i].setValue(args.
result());
2734 if (child) child->combine(value, valueIsActive, op);
2743 template<
typename ChildT, Index Log2Dim>
2744 template<
typename CombineOp,
typename OtherNodeType>
2751 for (
Index i = 0; i < NUM_VALUES; ++i) {
2755 .setBRef(other1.mNodes[i].getValue())
2756 .setBIsActive(other1.isValueMaskOn(i)));
2758 this->makeChildNodeEmpty(i, args.
result());
2761 if (this->isChildMaskOff(i)) {
2765 : other1.mNodes[i].getChild()->origin();
2766 this->setChildNode(i,
new ChildNodeType(childOrigin, mNodes[i].getValue()));
2774 }
else if (other1.isChildMaskOff(i)) {
2778 other1.mNodes[i].getValue(), other1.isValueMaskOn(i), op);
2783 *other1.mNodes[i].getChild(), op);
2790 template<
typename ChildT, Index Log2Dim>
2791 template<
typename CombineOp,
typename OtherNodeType>
2794 bool valueIsActive, CombineOp& op)
2798 for (
Index i = 0; i < NUM_VALUES; ++i) {
2799 if (other.isChildMaskOff(i)) {
2801 .setAIsActive(valueIsActive)
2802 .setBRef(other.mNodes[i].getValue())
2803 .setBIsActive(other.isValueMaskOn(i)));
2805 this->makeChildNodeEmpty(i, args.
result());
2808 typename OtherNodeType::ChildNodeType* otherChild = other.mNodes[i].getChild();
2810 if (this->isChildMaskOff(i)) {
2817 mNodes[i].getChild()->combine2(value, *otherChild, valueIsActive, op);
2823 template<
typename ChildT, Index Log2Dim>
2824 template<
typename CombineOp,
typename OtherValueType>
2827 bool valueIsActive, CombineOp& op)
2831 for (
Index i = 0; i < NUM_VALUES; ++i) {
2836 .setBIsActive(valueIsActive));
2838 this->makeChildNodeEmpty(i, args.
result());
2843 if (this->isChildMaskOff(i)) {
2845 this->setChildNode(i,
2846 new ChildNodeType(otherChild->origin(), mNodes[i].getValue()));
2850 mNodes[i].getChild()->combine2(*otherChild, value, valueIsActive, op);
2859 template<
typename ChildT, Index Log2Dim>
2863 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2864 iter->writeBuffers(os, toHalf);
2869 template<
typename ChildT, Index Log2Dim>
2873 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2874 iter->readBuffers(is, fromHalf);
2879 template<
typename ChildT, Index Log2Dim>
2882 const CoordBBox& clipBBox,
bool fromHalf)
2884 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2889 iter->readBuffers(is, clipBBox, fromHalf);
2893 ValueType background = zeroVal<ValueType>();
2895 background = *
static_cast<const ValueType*
>(bgPtr);
2897 this->
clip(clipBBox, background);
2904 template<
typename ChildT, Index Log2Dim>
2908 dims.push_back(Log2Dim);
2909 ChildNodeType::getNodeLog2Dims(dims);
2913 template<
typename ChildT, Index Log2Dim>
2917 assert(n<(1<<3*Log2Dim));
2918 xyz.setX(n >> 2*Log2Dim);
2919 n &= ((1<<2*Log2Dim)-1);
2920 xyz.setY(n >> Log2Dim);
2921 xyz.setZ(n & ((1<<Log2Dim)-1));
2925 template<
typename ChildT, Index Log2Dim>
2929 return (((xyz[0] & (DIM-1u)) >> ChildNodeType::TOTAL) << 2*Log2Dim)
2930 + (((xyz[1] & (DIM-1u)) >> ChildNodeType::TOTAL) << Log2Dim)
2931 + ((xyz[2] & (DIM-1u)) >> ChildNodeType::TOTAL);
2935 template<
typename ChildT, Index Log2Dim>
2940 this->offsetToLocalCoord(n, local);
2941 local <<= ChildT::TOTAL;
2942 return local + this->origin();
2949 template<
typename ChildT, Index Log2Dim>
2950 template<
typename ArrayT>
2956 using ArrayChildT =
typename std::conditional<
2958 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2961 array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild()));
2963 iter->getNodes(array);
2969 template<
typename ChildT, Index Log2Dim>
2970 template<
typename ArrayT>
2977 "argument to getNodes() must be an array of const node pointers");
2978 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2981 array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild()));
2983 iter->getNodes(array);
2993 template<
typename ChildT, Index Log2Dim>
2994 template<
typename ArrayT>
3000 using ArrayChildT =
typename std::conditional<
3003 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3004 const Index n = iter.pos();
3006 array.push_back(reinterpret_cast<T>(mNodes[n].getChild()));
3007 mValueMask.set(n, state);
3008 mNodes[
n].setValue(value);
3010 iter->stealNodes(array, value, state);
3021 template<
typename ChildT, Index Log2Dim>
3027 for (
Index i = 0; i < NUM_VALUES; ++i) {
3028 if (this->isChildMaskOn(i)) {
3029 mNodes[i].getChild()->resetBackground(oldBackground, newBackground);
3030 }
else if (this->isValueMaskOff(i)) {
3032 mNodes[i].setValue(newBackground);
3040 template<
typename ChildT, Index Log2Dim>
3041 template<
typename OtherChildNodeType, Index OtherLog2Dim>
3046 if (Log2Dim != OtherLog2Dim || mChildMask != other->
mChildMask ||
3047 mValueMask != other->
mValueMask)
return false;
3048 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3049 if (!iter->hasSameTopology(other->
mNodes[iter.pos()].getChild()))
return false;
3055 template<
typename ChildT, Index Log2Dim>
3060 if (this->isChildMaskOn(i)) {
3061 delete mNodes[i].getChild();
3063 mChildMask.setOn(i);
3064 mValueMask.setOff(i);
3066 mNodes[i].setChild(child);
3069 template<
typename ChildT, Index Log2Dim>
3074 assert(mChildMask.isOff(i));
3075 mChildMask.setOn(i);
3076 mValueMask.setOff(i);
3077 mNodes[i].setChild(child);
3081 template<
typename ChildT, Index Log2Dim>
3085 if (this->isChildMaskOff(i)) {
3086 mNodes[i].setValue(value);
3090 mChildMask.setOff(i);
3091 mNodes[i].setValue(value);
3096 template<
typename ChildT, Index Log2Dim>
3100 delete this->unsetChildNode(n, value);
3103 template<
typename ChildT, Index Log2Dim>
3107 assert(this->isChildMaskOn(n));
3108 return mNodes[
n].getChild();
3112 template<
typename ChildT, Index Log2Dim>
3113 inline const ChildT*
3116 assert(this->isChildMaskOn(n));
3117 return mNodes[
n].getChild();
3124 #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
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
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...
#define OPENVDB_ABI_VERSION_NUMBER
The ABI version that OpenVDB was built with.
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
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...
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 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
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...
TopologyCopy1(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
DenseIter< InternalNode, ChildNodeType, ValueType, ChildAll > ChildAllIter
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 addChild(ChildNodeType *child)
Add the given child node at this level deducing the offset from it's origin. If a child node with thi...
bool isValueMaskOn() const