8#ifndef OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
9#define OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
15#include <openvdb/version.h>
19#include <tbb/parallel_for.h>
29template<
typename, Index,
typename>
struct SameInternalConfig;
32template<
typename _ChildNodeType, Index Log2Dim>
38 using ValueType =
typename ChildNodeType::ValueType;
39 using BuildType =
typename ChildNodeType::BuildType;
45 TOTAL = Log2Dim + ChildNodeType::TOTAL,
47 NUM_VALUES = 1 << (3 * Log2Dim),
48 LEVEL = 1 + ChildNodeType::LEVEL;
50 NUM_VOXELS = uint64_t(1) << (3 * TOTAL);
54 template<
typename OtherValueType>
57 OtherValueType>
::Type, Log2Dim>;
63 template<
typename OtherNodeType>
82 InternalNode(
const Coord& origin,
const ValueType& fillValue,
bool active =
false);
94 template<
typename OtherChildNodeType>
100 template<
typename OtherChildNodeType>
107 template<
typename OtherChildNodeType>
109 const ValueType& offValue,
const ValueType& onValue,
TopologyCopy);
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) {}
136 assert(this->parent().isChildMaskOn(pos));
137 return *(this->parent().getChildNode(pos));
141 void setItem(
Index pos,
const ChildT& c)
const { this->parent().resetChildNode(pos, &c); }
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) {}
155 const ValueT&
getItem(
Index pos)
const {
return this->parent().mNodes[pos].getValue(); }
158 void setItem(
Index pos,
const ValueT& v)
const { this->parent().mNodes[pos].setValue(v); }
161 template<
typename ModifyOp>
164 op(this->parent().mNodes[pos].getValue());
169 template<
typename NodeT,
typename ChildT,
typename ValueT,
typename TagT>
171 MaskDenseIterator, DenseIter<NodeT, ChildT, ValueT, TagT>, NodeT, ChildT, ValueT>
182 if (this->parent().isChildMaskOn(pos)) {
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);
252 static void getNodeLog2Dims(std::vector<Index>& dims);
262 static void offsetToLocalCoord(
Index n,
Coord& xyz);
271#if OPENVDB_ABI_VERSION_NUMBER >= 9
279 void nodeCount(std::vector<Index32> &vec)
const;
284 Index64 onLeafVoxelCount()
const;
285 Index64 offLeafVoxelCount()
const;
295 void evalActiveBoundingBox(
CoordBBox& bbox,
bool visitVoxels =
true)
const;
302 bool isEmpty()
const {
return mChildMask.isOff(); }
309 bool isConstant(ValueType& firstValue,
bool& state,
310 const ValueType& tolerance = zeroVal<ValueType>())
const;
326 bool isConstant(ValueType& minValue, ValueType& maxValue,
327 bool& state,
const ValueType& tolerance = zeroVal<ValueType>())
const;
330 bool isInactive()
const {
return this->isChildMaskOff() && this->isValueMaskOff(); }
333 bool isValueOn(
const Coord& xyz)
const;
338 bool hasActiveTiles()
const;
340 const ValueType& getValue(
const Coord& xyz)
const;
341 bool probeValue(
const Coord& xyz, ValueType&
value)
const;
349 const ValueType& getFirstValue()
const;
352 const ValueType& getLastValue()
const;
355 void setActiveState(
const Coord& xyz,
bool on);
357 void setValueOnly(
const Coord& xyz,
const ValueType&
value);
359 void setValueOn(
const Coord& xyz);
361 void setValueOn(
const Coord& xyz,
const ValueType&
value);
363 void setValueOff(
const Coord& xyz);
365 void setValueOff(
const Coord& xyz,
const ValueType&
value);
369 template<
typename ModifyOp>
370 void modifyValue(
const Coord& xyz,
const ModifyOp& op);
372 template<
typename ModifyOp>
373 void modifyValueAndActiveState(
const Coord& xyz,
const ModifyOp& op);
379 template<
typename AccessorT>
386 template<
typename AccessorT>
387 bool isValueOnAndCache(
const Coord& xyz, AccessorT&)
const;
393 template<
typename AccessorT>
400 template<
typename AccessorT>
408 template<
typename ModifyOp,
typename AccessorT>
409 void modifyValueAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
415 template<
typename ModifyOp,
typename AccessorT>
416 void modifyValueAndActiveStateAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
422 template<
typename AccessorT>
429 template<
typename AccessorT>
430 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&);
437 template<
typename AccessorT>
446 template<
typename AccessorT>
447 Index getValueLevelAndCache(
const Coord& xyz, AccessorT&)
const;
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);
491 void voxelizeActiveTiles(
bool threaded =
true);
500 template<
typename DenseT>
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 >
565 void combine2(
const InternalNode& other0,
const OtherNodeType& other1, CombineOp&);
566 template<
typename CombineOp,
typename OtherNodeType >
567 void combine2(
const ValueType&
value,
const OtherNodeType& other,
bool valIsActive, CombineOp&);
568 template<
typename CombineOp,
typename OtherValueType>
569 void combine2(
const InternalNode& other,
const OtherValueType&,
bool valIsActive, CombineOp&);
576 template<
typename BBoxOp>
void visitActiveBBox(BBoxOp&)
const;
578 template<
typename VisitorOp>
void visit(VisitorOp&);
579 template<
typename VisitorOp>
void visit(VisitorOp&)
const;
581 template<
typename OtherNodeType,
typename VisitorOp>
582 void visit2Node(OtherNodeType& other, VisitorOp&);
583 template<
typename OtherNodeType,
typename VisitorOp>
584 void visit2Node(OtherNodeType& other, VisitorOp&)
const;
585 template<
typename IterT,
typename VisitorOp>
586 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false);
587 template<
typename IterT,
typename VisitorOp>
588 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false)
const;
604 template<
typename AccessorT>
615 template<
typename NodeT>
635 template<
typename AccessorT>
636 void addTileAndCache(
Index level,
const Coord& xyz,
const ValueType&,
bool state, AccessorT&);
648 template<
typename NodeType,
typename AccessorT>
650 template<
typename NodeType,
typename AccessorT>
665 template<
typename AccessorT>
667 template<
typename AccessorT>
669 template<
typename AccessorT>
683 template<
typename AccessorT>
709 template<
typename ArrayT>
710 void getNodes(ArrayT& array);
711 template<
typename ArrayT>
712 void getNodes(ArrayT& array)
const;
738 template<
typename ArrayT>
739 void stealNodes(ArrayT& array,
const ValueType&
value,
bool state);
747 template<
typename OtherChildNodeType, Index OtherLog2Dim>
789 void makeChildNodeEmpty(
Index n,
const ValueType&
value);
790 void setChildNode(
Index i, ChildNodeType*
child);
791 void resetChildNode(
Index i, ChildNodeType*
child);
792 ChildNodeType* unsetChildNode(
Index i,
const ValueType&
value);
794 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
795 static inline void doVisit(NodeT&, VisitorOp&);
797 template<
typename NodeT,
typename OtherNodeT,
typename VisitorOp,
798 typename ChildAllIterT,
typename OtherChildAllIterT>
799 static inline void doVisit2Node(NodeT&, OtherNodeT&, VisitorOp&);
801 template<
typename NodeT,
typename VisitorOp,
802 typename ChildAllIterT,
typename OtherChildAllIterT>
803 static inline void doVisit2(NodeT&, OtherChildAllIterT&, VisitorOp&,
bool otherIsLHS);
809 ChildNodeType* getChildNode(
Index n);
810 const ChildNodeType* getChildNode(
Index n)
const;
815 struct VoxelizeActiveTiles;
816 template<
typename OtherInternalNode>
struct DeepCopy;
817 template<
typename OtherInternalNode>
struct TopologyCopy1;
818 template<
typename OtherInternalNode>
struct TopologyCopy2;
819 template<
typename OtherInternalNode>
struct TopologyUnion;
820 template<
typename OtherInternalNode>
struct TopologyDifference;
821 template<
typename OtherInternalNode>
struct TopologyIntersection;
828#if OPENVDB_ABI_VERSION_NUMBER >= 9
841template<
typename ChildT1, Index Dim1,
typename NodeT2>
846template<
typename ChildT1, Index Dim1,
typename ChildT2>
856template<
typename ChildT, Index Log2Dim>
860 for (
Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(background);
864template<
typename ChildT, Index Log2Dim>
867 mOrigin(origin[0] & ~(DIM - 1),
868 origin[1] & ~(DIM - 1),
869 origin[2] & ~(DIM - 1))
878template<
typename ChildT, Index Log2Dim>
882 : mOrigin(origin[0] & ~(DIM-1), origin[1] & ~(DIM-1), origin[2] & ~(DIM-1))
888template<
typename ChildT, Index Log2Dim>
889template<
typename OtherInternalNode>
893 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
897 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
898 if (s->mChildMask.isOff(i)) {
899 t->mNodes[i].setValue(
ValueType(s->mNodes[i].getValue()));
901 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild())));
905 const OtherInternalNode*
s;
909template<
typename ChildT, Index Log2Dim>
912 : mChildMask(other.mChildMask)
913 , mValueMask(other.mValueMask)
914 , mOrigin(other.mOrigin)
915#if OPENVDB_ABI_VERSION_NUMBER >= 9
916 , mTransientData(other.mTransientData)
924template<
typename ChildT, Index Log2Dim>
925template<
typename OtherChildNodeType>
928 : mChildMask(other.mChildMask)
929 , mValueMask(other.mValueMask)
930 , mOrigin(other.mOrigin)
931#if OPENVDB_ABI_VERSION_NUMBER >= 9
932 , mTransientData(other.mTransientData)
938template<
typename ChildT, Index Log2Dim>
939template<
typename OtherInternalNode>
943 const ValueType& background) : s(source), t(target), b(background) {
944 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
948 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
949 if (s->isChildMaskOn(i)) {
950 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild()),
953 t->mNodes[i].setValue(b);
957 const OtherInternalNode*
s;
962template<
typename ChildT, Index Log2Dim>
963template<
typename OtherChildNodeType>
967 : mChildMask(other.mChildMask)
968 , mValueMask(other.mValueMask)
969 , mOrigin(other.mOrigin)
970#if OPENVDB_ABI_VERSION_NUMBER >= 9
971 , mTransientData(other.mTransientData)
977template<
typename ChildT, Index Log2Dim>
978template<
typename OtherInternalNode>
983 : s(source), t(target), offV(offValue), onV(onValue) {
984 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
987 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
988 if (s->isChildMaskOn(i)) {
989 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild()),
992 t->mNodes[i].setValue(s->isValueMaskOn(i) ? onV : offV);
996 const OtherInternalNode*
s;
1001template<
typename ChildT, Index Log2Dim>
1002template<
typename OtherChildNodeType>
1007 : mChildMask(other.mChildMask)
1008 , mValueMask(other.mValueMask)
1009 , mOrigin(other.mOrigin)
1010#if OPENVDB_ABI_VERSION_NUMBER >= 9
1011 , mTransientData(other.mTransientData)
1018template<
typename ChildT, Index Log2Dim>
1022 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1023 delete mNodes[iter.pos()].getChild();
1031template<
typename ChildT, Index Log2Dim>
1037 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1038 sum += iter->leafCount();
1043template<
typename ChildT, Index Log2Dim>
1047 assert(vec.size() > ChildNodeType::LEVEL);
1048 const auto count = mChildMask.countOn();
1049 if (ChildNodeType::LEVEL > 0 && count > 0) {
1050 for (
auto iter = this->cbeginChildOn(); iter; ++iter) iter->nodeCount(vec);
1052 vec[ChildNodeType::LEVEL] += count;
1056template<
typename ChildT, Index Log2Dim>
1062 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1063 sum += iter->nonLeafCount();
1069template<
typename ChildT, Index Log2Dim>
1073 return this->getChildMask().countOn();
1077template<
typename ChildT, Index Log2Dim>
1081 Index64 sum = ChildT::NUM_VOXELS * mValueMask.countOn();
1082 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1083 sum += iter->onVoxelCount();
1089template<
typename ChildT, Index Log2Dim>
1093 Index64 sum = ChildT::NUM_VOXELS * (NUM_VALUES-mValueMask.countOn()-mChildMask.countOn());
1094 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1095 sum += iter->offVoxelCount();
1101template<
typename ChildT, Index Log2Dim>
1106 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1107 sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount();
1113template<
typename ChildT, Index Log2Dim>
1118 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1119 sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount();
1124template<
typename ChildT, Index Log2Dim>
1128 Index64 sum = mValueMask.countOn();
1129 for (
ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) {
1130 sum += iter->onTileCount();
1135template<
typename ChildT, Index Log2Dim>
1140 + mValueMask.memUsage() +
sizeof(mOrigin);
1141 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1142 sum += iter->memUsage();
1148template<
typename ChildT, Index Log2Dim>
1152 if (bbox.
isInside(this->getNodeBoundingBox()))
return;
1155 bbox.
expand(i.getCoord(), ChildT::DIM);
1158 i->evalActiveBoundingBox(bbox, visitVoxels);
1166template<
typename ChildT, Index Log2Dim>
1172 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1173 const Index i = iter.pos();
1174 ChildT*
child = mNodes[i].getChild();
1175 child->prune(tolerance);
1176 if (
child->isConstant(
value, state, tolerance)) {
1178 mChildMask.setOff(i);
1179 mValueMask.set(i, state);
1180 mNodes[i].setValue(
value);
1189template<
typename ChildT, Index Log2Dim>
1190template<
typename NodeT>
1195 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1197 const Index n = this->coordToOffset(xyz);
1198 if (mChildMask.isOff(n))
return nullptr;
1199 ChildT*
child = mNodes[n].getChild();
1201 mChildMask.setOff(n);
1202 mValueMask.set(n, state);
1203 mNodes[n].setValue(
value);
1206 ?
reinterpret_cast<NodeT*
>(
child)
1207 :
child->template stealNode<NodeT>(xyz,
value, state);
1215template<
typename ChildT, Index Log2Dim>
1216template<
typename NodeT>
1221 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1223 const Index n = this->coordToOffset(xyz);
1224 if (mChildMask.isOff(n))
return nullptr;
1225 ChildT*
child = mNodes[n].getChild();
1227 ?
reinterpret_cast<NodeT*
>(
child)
1228 :
child->template probeNode<NodeT>(xyz);
1233template<
typename ChildT, Index Log2Dim>
1234template<
typename NodeT,
typename AccessorT>
1239 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1241 const Index n = this->coordToOffset(xyz);
1242 if (mChildMask.isOff(n))
return nullptr;
1243 ChildT*
child = mNodes[n].getChild();
1244 acc.insert(xyz,
child);
1246 ?
reinterpret_cast<NodeT*
>(
child)
1247 :
child->template probeNodeAndCache<NodeT>(xyz, acc);
1252template<
typename ChildT, Index Log2Dim>
1253template<
typename NodeT>
1258 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1260 const Index n = this->coordToOffset(xyz);
1261 if (mChildMask.isOff(n))
return nullptr;
1262 const ChildT*
child = mNodes[n].getChild();
1264 ?
reinterpret_cast<const NodeT*
>(
child)
1265 :
child->template probeConstNode<NodeT>(xyz);
1270template<
typename ChildT, Index Log2Dim>
1271template<
typename NodeT,
typename AccessorT>
1276 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1278 const Index n = this->coordToOffset(xyz);
1279 if (mChildMask.isOff(n))
return nullptr;
1280 const ChildT*
child = mNodes[n].getChild();
1281 acc.insert(xyz,
child);
1283 ?
reinterpret_cast<const NodeT*
>(
child)
1284 :
child->template probeConstNodeAndCache<NodeT>(xyz, acc);
1292template<
typename ChildT, Index Log2Dim>
1293inline typename ChildT::LeafNodeType*
1296 return this->
template probeNode<LeafNodeType>(xyz);
1300template<
typename ChildT, Index Log2Dim>
1301template<
typename AccessorT>
1302inline typename ChildT::LeafNodeType*
1305 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
1309template<
typename ChildT, Index Log2Dim>
1310template<
typename AccessorT>
1311inline const typename ChildT::LeafNodeType*
1314 return this->probeConstLeafAndCache(xyz, acc);
1318template<
typename ChildT, Index Log2Dim>
1319inline const typename ChildT::LeafNodeType*
1322 return this->
template probeConstNode<LeafNodeType>(xyz);
1326template<
typename ChildT, Index Log2Dim>
1327template<
typename AccessorT>
1328inline const typename ChildT::LeafNodeType*
1331 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
1338template<
typename ChildT, Index Log2Dim>
1342 assert(leaf !=
nullptr);
1343 const Coord& xyz = leaf->origin();
1344 const Index n = this->coordToOffset(xyz);
1345 ChildT*
child =
nullptr;
1346 if (mChildMask.isOff(n)) {
1347 if (ChildT::LEVEL>0) {
1348 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1350 child =
reinterpret_cast<ChildT*
>(leaf);
1352 this->setChildNode(n,
child);
1354 if (ChildT::LEVEL>0) {
1355 child = mNodes[n].getChild();
1357 delete mNodes[n].getChild();
1358 child =
reinterpret_cast<ChildT*
>(leaf);
1359 mNodes[n].setChild(
child);
1362 child->addLeaf(leaf);
1366template<
typename ChildT, Index Log2Dim>
1367template<
typename AccessorT>
1371 assert(leaf !=
nullptr);
1372 const Coord& xyz = leaf->origin();
1373 const Index n = this->coordToOffset(xyz);
1374 ChildT*
child =
nullptr;
1375 if (mChildMask.isOff(n)) {
1376 if (ChildT::LEVEL>0) {
1377 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1378 acc.insert(xyz,
child);
1380 child =
reinterpret_cast<ChildT*
>(leaf);
1382 this->setChildNode(n,
child);
1384 if (ChildT::LEVEL>0) {
1385 child = mNodes[n].getChild();
1386 acc.insert(xyz,
child);
1388 delete mNodes[n].getChild();
1389 child =
reinterpret_cast<ChildT*
>(leaf);
1390 mNodes[n].setChild(
child);
1393 child->addLeafAndCache(leaf, acc);
1400template<
typename ChildT, Index Log2Dim>
1407 if (
Coord((xyz & ~(DIM-1))) != this->origin())
return false;
1409 const Index n = this->coordToOffset(xyz);
1411 this->resetChildNode(n,
child);
1416template<
typename ChildT, Index Log2Dim>
1420 assert(n < NUM_VALUES);
1421 this->makeChildNodeEmpty(n,
value);
1422 mValueMask.set(n, state);
1426template<
typename ChildT, Index Log2Dim>
1431 if (LEVEL >= level) {
1432 const Index n = this->coordToOffset(xyz);
1433 if (mChildMask.isOff(n)) {
1434 if (LEVEL > level) {
1435 ChildT*
child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1436 this->setChildNode(n,
child);
1439 mValueMask.set(n, state);
1440 mNodes[n].setValue(
value);
1443 ChildT*
child = mNodes[n].getChild();
1444 if (LEVEL > level) {
1448 mChildMask.setOff(n);
1449 mValueMask.set(n, state);
1450 mNodes[n].setValue(
value);
1457template<
typename ChildT, Index Log2Dim>
1458template<
typename AccessorT>
1463 if (LEVEL >= level) {
1464 const Index n = this->coordToOffset(xyz);
1465 if (mChildMask.isOff(n)) {
1466 if (LEVEL > level) {
1467 ChildT*
child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1468 this->setChildNode(n,
child);
1469 acc.insert(xyz,
child);
1470 child->addTileAndCache(level, xyz,
value, state, acc);
1472 mValueMask.set(n, state);
1473 mNodes[n].setValue(
value);
1476 ChildT*
child = mNodes[n].getChild();
1477 if (LEVEL > level) {
1478 acc.insert(xyz,
child);
1479 child->addTileAndCache(level, xyz,
value, state, acc);
1482 mChildMask.setOff(n);
1483 mValueMask.set(n, state);
1484 mNodes[n].setValue(
value);
1494template<
typename ChildT, Index Log2Dim>
1495inline typename ChildT::LeafNodeType*
1498 const Index n = this->coordToOffset(xyz);
1499 ChildT*
child =
nullptr;
1500 if (mChildMask.isOff(n)) {
1501 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1502 this->setChildNode(n,
child);
1504 child = mNodes[n].getChild();
1506 return child->touchLeaf(xyz);
1510template<
typename ChildT, Index Log2Dim>
1511template<
typename AccessorT>
1512inline typename ChildT::LeafNodeType*
1515 const Index n = this->coordToOffset(xyz);
1516 if (mChildMask.isOff(n)) {
1517 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), mValueMask.isOn(n)));
1519 acc.insert(xyz, mNodes[n].getChild());
1520 return mNodes[n].getChild()->touchLeafAndCache(xyz, acc);
1527template<
typename ChildT, Index Log2Dim>
1532 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1534 firstValue = mNodes[0].getValue();
1535 for (
Index i = 1; i < NUM_VALUES; ++i) {
1547template<
typename ChildT, Index Log2Dim>
1555 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1556 minValue = maxValue = mNodes[0].getValue();
1557 for (
Index i = 1; i < NUM_VALUES; ++i) {
1558 const ValueType& v = mNodes[i].getValue();
1560 if ((maxValue - v) > tolerance)
return false;
1562 }
else if (v > maxValue) {
1563 if ((v - minValue) > tolerance)
return false;
1574template<
typename ChildT, Index Log2Dim>
1581 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1582 if (iter->hasActiveTiles())
return true;
1589template<
typename ChildT, Index Log2Dim>
1593 const Index n = this->coordToOffset(xyz);
1594 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1595 return mNodes[n].getChild()->isValueOn(xyz);
1598template<
typename ChildT, Index Log2Dim>
1599template<
typename AccessorT>
1603 const Index n = this->coordToOffset(xyz);
1604 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1605 acc.insert(xyz, mNodes[n].getChild());
1606 return mNodes[n].getChild()->isValueOnAndCache(xyz, acc);
1610template<
typename ChildT, Index Log2Dim>
1611inline const typename ChildT::ValueType&
1614 const Index n = this->coordToOffset(xyz);
1615 return this->isChildMaskOff(n) ? mNodes[n].getValue()
1616 : mNodes[n].getChild()->getValue(xyz);
1619template<
typename ChildT, Index Log2Dim>
1620template<
typename AccessorT>
1621inline const typename ChildT::ValueType&
1624 const Index n = this->coordToOffset(xyz);
1625 if (this->isChildMaskOn(n)) {
1626 acc.insert(xyz, mNodes[n].getChild());
1627 return mNodes[n].getChild()->getValueAndCache(xyz, acc);
1629 return mNodes[n].getValue();
1633template<
typename ChildT, Index Log2Dim>
1637 const Index n = this->coordToOffset(xyz);
1638 return this->isChildMaskOff(n) ? LEVEL : mNodes[n].getChild()->getValueLevel(xyz);
1641template<
typename ChildT, Index Log2Dim>
1642template<
typename AccessorT>
1646 const Index n = this->coordToOffset(xyz);
1647 if (this->isChildMaskOn(n)) {
1648 acc.insert(xyz, mNodes[n].getChild());
1649 return mNodes[n].getChild()->getValueLevelAndCache(xyz, acc);
1655template<
typename ChildT, Index Log2Dim>
1659 const Index n = this->coordToOffset(xyz);
1660 if (this->isChildMaskOff(n)) {
1661 value = mNodes[n].getValue();
1662 return this->isValueMaskOn(n);
1664 return mNodes[n].getChild()->probeValue(xyz,
value);
1667template<
typename ChildT, Index Log2Dim>
1668template<
typename AccessorT>
1673 const Index n = this->coordToOffset(xyz);
1674 if (this->isChildMaskOn(n)) {
1675 acc.insert(xyz, mNodes[n].getChild());
1676 return mNodes[n].getChild()->probeValueAndCache(xyz,
value, acc);
1678 value = mNodes[n].getValue();
1679 return this->isValueMaskOn(n);
1683template<
typename ChildT, Index Log2Dim>
1687 const Index n = this->coordToOffset(xyz);
1688 bool hasChild = this->isChildMaskOn(n);
1689 if (!hasChild && this->isValueMaskOn(n)) {
1693 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
true));
1695 if (hasChild) mNodes[n].getChild()->setValueOff(xyz);
1699template<
typename ChildT, Index Log2Dim>
1703 const Index n = this->coordToOffset(xyz);
1704 bool hasChild = this->isChildMaskOn(n);
1705 if (!hasChild && !this->isValueMaskOn(n)) {
1709 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
false));
1711 if (hasChild) mNodes[n].getChild()->setValueOn(xyz);
1715template<
typename ChildT, Index Log2Dim>
1720 bool hasChild = this->isChildMaskOn(n);
1722 const bool active = this->isValueMaskOn(n);
1728 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1731 if (hasChild) mNodes[n].getChild()->setValueOff(xyz,
value);
1734template<
typename ChildT, Index Log2Dim>
1735template<
typename AccessorT>
1741 bool hasChild = this->isChildMaskOn(n);
1743 const bool active = this->isValueMaskOn(n);
1749 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1753 ChildT*
child = mNodes[n].getChild();
1754 acc.insert(xyz,
child);
1760template<
typename ChildT, Index Log2Dim>
1764 const Index n = this->coordToOffset(xyz);
1765 bool hasChild = this->isChildMaskOn(n);
1767 const bool active = this->isValueMaskOn(n);
1773 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1776 if (hasChild) mNodes[n].getChild()->setValueOn(xyz,
value);
1779template<
typename ChildT, Index Log2Dim>
1780template<
typename AccessorT>
1785 const Index n = this->coordToOffset(xyz);
1786 bool hasChild = this->isChildMaskOn(n);
1788 const bool active = this->isValueMaskOn(n);
1794 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1798 acc.insert(xyz, mNodes[n].getChild());
1799 mNodes[n].getChild()->setValueAndCache(xyz,
value, acc);
1804template<
typename ChildT, Index Log2Dim>
1808 const Index n = this->coordToOffset(xyz);
1809 bool hasChild = this->isChildMaskOn(n);
1813 const bool active = this->isValueMaskOn(n);
1815 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1817 if (hasChild) mNodes[n].getChild()->setValueOnly(xyz,
value);
1820template<
typename ChildT, Index Log2Dim>
1821template<
typename AccessorT>
1826 const Index n = this->coordToOffset(xyz);
1827 bool hasChild = this->isChildMaskOn(n);
1831 const bool active = this->isValueMaskOn(n);
1833 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1836 acc.insert(xyz, mNodes[n].getChild());
1837 mNodes[n].getChild()->setValueOnlyAndCache(xyz,
value, acc);
1842template<
typename ChildT, Index Log2Dim>
1846 const Index n = this->coordToOffset(xyz);
1847 bool hasChild = this->isChildMaskOn(n);
1849 if (on != this->isValueMaskOn(n)) {
1854 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1857 if (hasChild) mNodes[n].getChild()->setActiveState(xyz, on);
1860template<
typename ChildT, Index Log2Dim>
1861template<
typename AccessorT>
1865 const Index n = this->coordToOffset(xyz);
1866 bool hasChild = this->isChildMaskOn(n);
1868 if (on != this->isValueMaskOn(n)) {
1873 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1877 ChildT*
child = mNodes[n].getChild();
1878 acc.insert(xyz,
child);
1879 child->setActiveStateAndCache(xyz, on, acc);
1884template<
typename ChildT, Index Log2Dim>
1888 mValueMask = !mChildMask;
1889 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1890 mNodes[iter.pos()].getChild()->setValuesOn();
1895template<
typename ChildT, Index Log2Dim>
1896template<
typename ModifyOp>
1901 bool hasChild = this->isChildMaskOn(n);
1905 const bool active = this->isValueMaskOn(n);
1906 bool createChild = !active;
1910 const ValueType& tileVal = mNodes[n].getValue();
1917 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1920 if (hasChild) mNodes[n].getChild()->modifyValue(xyz, op);
1923template<
typename ChildT, Index Log2Dim>
1924template<
typename ModifyOp,
typename AccessorT>
1930 bool hasChild = this->isChildMaskOn(n);
1934 const bool active = this->isValueMaskOn(n);
1935 bool createChild = !active;
1939 const ValueType& tileVal = mNodes[n].getValue();
1946 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1951 acc.insert(xyz,
child);
1952 child->modifyValueAndCache(xyz, op, acc);
1957template<
typename ChildT, Index Log2Dim>
1958template<
typename ModifyOp>
1963 bool hasChild = this->isChildMaskOn(n);
1965 const bool tileState = this->isValueMaskOn(n);
1966 const ValueType& tileVal = mNodes[n].getValue();
1967 bool modifiedState = !tileState;
1969 op(modifiedVal, modifiedState);
1974 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
1977 if (hasChild) mNodes[n].getChild()->modifyValueAndActiveState(xyz, op);
1980template<
typename ChildT, Index Log2Dim>
1981template<
typename ModifyOp,
typename AccessorT>
1984 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
1987 bool hasChild = this->isChildMaskOn(n);
1989 const bool tileState = this->isValueMaskOn(n);
1990 const ValueType& tileVal = mNodes[n].getValue();
1991 bool modifiedState = !tileState;
1993 op(modifiedVal, modifiedState);
1998 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
2003 acc.insert(xyz,
child);
2004 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
2012template<
typename ChildT, Index Log2Dim>
2016 CoordBBox nodeBBox = this->getNodeBoundingBox();
2019 this->fill(nodeBBox, background,
false);
2020 }
else if (clipBBox.
isInside(nodeBBox)) {
2029 for (
Index pos = 0; pos < NUM_VALUES; ++pos) {
2030 const Coord xyz = this->offsetToGlobalCoord(pos);
2035 this->makeChildNodeEmpty(pos, background);
2036 mValueMask.setOff(pos);
2037 }
else if (!clipBBox.
isInside(tileBBox)) {
2040 if (this->isChildMaskOn(pos)) {
2041 mNodes[pos].getChild()->clip(clipBBox, background);
2046 const ValueType val = mNodes[pos].getValue();
2047 const bool on = this->isValueMaskOn(pos);
2048 mNodes[pos].setValue(background);
2049 mValueMask.setOff(pos);
2050 this->fill(tileBBox, val, on);
2062template<
typename ChildT, Index Log2Dim>
2066 auto clippedBBox = this->getNodeBoundingBox();
2067 clippedBBox.intersect(bbox);
2068 if (!clippedBBox)
return;
2072 Coord xyz, tileMin, tileMax;
2073 for (
int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.
x() + 1) {
2075 for (
int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.
y() + 1) {
2077 for (
int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.
z() + 1) {
2081 const Index n = this->coordToOffset(xyz);
2082 tileMin = this->offsetToGlobalCoord(n);
2083 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2089 ChildT*
child =
nullptr;
2090 if (this->isChildMaskOff(n)) {
2093 child =
new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)};
2094 this->setChildNode(n,
child);
2096 child = mNodes[n].getChild();
2109 this->makeChildNodeEmpty(n,
value);
2110 mValueMask.set(n, active);
2118template<
typename ChildT, Index Log2Dim>
2122 auto clippedBBox = this->getNodeBoundingBox();
2123 clippedBBox.intersect(bbox);
2124 if (!clippedBBox)
return;
2128 Coord xyz, tileMin, tileMax;
2129 for (
int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.
x() + 1) {
2131 for (
int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.
y() + 1) {
2133 for (
int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.
z() + 1) {
2137 const auto n = this->coordToOffset(xyz);
2140 ChildT*
child =
nullptr;
2141 if (this->isChildMaskOn(n)) {
2142 child = mNodes[n].getChild();
2146 child =
new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)};
2147 this->setChildNode(n,
child);
2151 tileMin = this->offsetToGlobalCoord(n);
2152 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2165template<
typename ChildT, Index Log2Dim>
2166template<
typename DenseT>
2170 using DenseValueType =
typename DenseT::ValueType;
2172 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2173 const Coord&
min = dense.bbox().min();
2174 for (
Coord xyz = bbox.
min(),
max; xyz[0] <= bbox.
max()[0]; xyz[0] =
max[0] + 1) {
2175 for (xyz[1] = bbox.
min()[1]; xyz[1] <= bbox.
max()[1]; xyz[1] =
max[1] + 1) {
2176 for (xyz[2] = bbox.
min()[2]; xyz[2] <= bbox.
max()[2]; xyz[2] =
max[2] + 1) {
2177 const Index n = this->coordToOffset(xyz);
2179 max = this->offsetToGlobalCoord(n).offsetBy(ChildT::DIM-1);
2184 if (this->isChildMaskOn(n)) {
2185 mNodes[n].getChild()->copyToDense(sub, dense);
2189 DenseValueType* a0 = dense.data() + zStride*sub.
min()[2];
2190 for (
Int32 x=sub.
min()[0], ex=sub.
max()[0]+1; x<ex; ++x) {
2191 DenseValueType* a1 = a0 + x*xStride;
2192 for (
Int32 y=sub.
min()[1], ey=sub.
max()[1]+1; y<ey; ++y) {
2193 DenseValueType* a2 = a1 + y*yStride;
2195 z < ez; ++z, a2 += zStride)
2197 *a2 = DenseValueType(
value);
2211template<
typename ChildT, Index Log2Dim>
2215 mChildMask.save(os);
2216 mValueMask.save(os);
2220 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[NUM_VALUES]);
2222 const ValueType zero = zeroVal<ValueType>();
2223 for (
Index i = 0; i < NUM_VALUES; ++i) {
2224 values[i] = (mChildMask.isOff(i) ? mNodes[i].getValue() : zero);
2230 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2231 iter->writeTopology(os, toHalf);
2236template<
typename ChildT, Index Log2Dim>
2243 mChildMask.load(is);
2244 mValueMask.load(is);
2247 for (
Index i = 0; i < NUM_VALUES; ++i) {
2248 if (this->isChildMaskOn(i)) {
2251 mNodes[i].setChild(
child);
2252 child->readTopology(is);
2256 mNodes[i].setValue(
value);
2260 const bool oldVersion =
2262 const Index numValues = (oldVersion ? mChildMask.countOff() : NUM_VALUES);
2266 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[numValues]);
2273 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2274 mNodes[iter.pos()].setValue(values[n++]);
2276 assert(n == numValues);
2278 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2279 mNodes[iter.pos()].setValue(values[iter.pos()]);
2284 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2286 mNodes[iter.pos()].setChild(
child);
2287 child->readTopology(is, fromHalf);
2296template<
typename ChildT, Index Log2Dim>
2297inline const typename ChildT::ValueType&
2300 return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].getValue());
2304template<
typename ChildT, Index Log2Dim>
2305inline const typename ChildT::ValueType&
2308 const Index n = NUM_VALUES - 1;
2309 return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].getValue());
2316template<
typename ChildT, Index Log2Dim>
2320 for (
Index i = 0; i < NUM_VALUES; ++i) {
2321 if (this->isChildMaskOn(i)) {
2322 mNodes[i].getChild()->negate();
2334template<
typename ChildT, Index Log2Dim>
2339 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2346 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2347 if (mNode->mChildMask.isOn(i)) {
2348 mNode->mNodes[i].getChild()->voxelizeActiveTiles(
true);
2349 }
else if (mNode->mValueMask.isOn(i)) {
2350 const Coord &ijk = mNode->offsetToGlobalCoord(i);
2352 child->voxelizeActiveTiles(
true);
2353 mNode->mNodes[i].setChild(
child);
2360template<
typename ChildT, Index Log2Dim>
2367 for (
ValueOnIter iter = this->beginValueOn(); iter; ++iter) {
2368 this->setChildNode(iter.pos(),
2371 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter)
2372 iter->voxelizeActiveTiles(
false);
2380template<
typename ChildT, Index Log2Dim>
2381template<MergePolicy Policy>
2394 const Index n = iter.pos();
2395 if (mChildMask.isOn(n)) {
2397 mNodes[n].getChild()->template merge<MERGE_ACTIVE_STATES>(*iter,
2398 background, otherBackground);
2399 }
else if (mValueMask.isOff(n)) {
2406 child->resetBackground(otherBackground, background);
2407 this->setChildNode(n,
child);
2413 const Index n = iter.pos();
2414 if (mValueMask.isOff(n)) {
2416 this->makeChildNodeEmpty(n, iter.getValue());
2417 mValueMask.setOn(n);
2426 const Index n = iter.pos();
2427 if (mChildMask.isOn(n)) {
2429 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2437 child->resetBackground(otherBackground, background);
2438 this->setChildNode(n,
child);
2448 const Index n = iter.pos();
2449 if (mChildMask.isOn(n)) {
2451 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2458 child->resetBackground(otherBackground, background);
2459 if (mValueMask.isOn(n)) {
2461 child->template merge<Policy>(mNodes[n].getValue(),
true);
2462 mValueMask.setOff(n);
2464 mChildMask.setOn(n);
2465 mNodes[n].setChild(
child);
2471 const Index n = iter.pos();
2472 if (mChildMask.isOn(n)) {
2474 mNodes[n].getChild()->template merge<Policy>(iter.getValue(),
true);
2475 }
else if (mValueMask.isOff(n)) {
2477 mNodes[n].setValue(iter.getValue());
2478 mValueMask.setOn(n);
2489template<
typename ChildT, Index Log2Dim>
2490template<MergePolicy Policy>
2499 if (!tileActive)
return;
2502 for (
ValueOffIter iter = this->beginValueOff(); iter; ++iter) {
2503 const Index n = iter.pos();
2504 if (mChildMask.isOn(n)) {
2506 mNodes[n].getChild()->template merge<Policy>(tileValue,
true);
2509 iter.setValue(tileValue);
2510 mValueMask.setOn(n);
2520template<
typename ChildT, Index Log2Dim>
2521template<
typename OtherInternalNode>
2526 { tV = (tV | sV) & ~tC; }
2529 : s(source), t(target), mPreserveTiles(preserveTiles) {
2531 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2534 if (!mPreserveTiles) t->mChildMask |= s->mChildMask;
2535 else t->mChildMask |= (s->mChildMask & !t->mValueMask);
2538 t->mValueMask.foreach(s->mValueMask, t->mChildMask, op);
2539 assert((t->mValueMask & t->mChildMask).isOff());
2542 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2543 if (s->mChildMask.isOn(i)) {
2544 const typename OtherInternalNode::ChildNodeType& other = *(s->mNodes[i].getChild());
2545 if (t->mChildMask.isOn(i)) {
2546 t->mNodes[i].getChild()->topologyUnion(other, mPreserveTiles);
2548 if (!mPreserveTiles || t->mValueMask.isOff(i)) {
2550 if (t->mValueMask.isOn(i))
child->setValuesOn();
2551 t->mNodes[i].setChild(
child);
2554 }
else if (s->mValueMask.isOn(i) && t->mChildMask.isOn(i)) {
2555 t->mNodes[i].getChild()->setValuesOn();
2559 const OtherInternalNode*
s;
2564template<
typename ChildT, Index Log2Dim>
2565template<
typename OtherChildT>
2572template<
typename ChildT, Index Log2Dim>
2573template<
typename OtherInternalNode>
2578 { tC = (tC & (sC | sV)) | (tV & sC); }
2581 const ValueType& background) : s(source), t(target), b(background) {
2583 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
2587 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op);
2589 t->mValueMask &= s->mValueMask;
2590 assert((t->mValueMask & t->mChildMask).isOff());
2593 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2594 if (t->mChildMask.isOn(i)) {
2595 ChildT*
child = t->mNodes[i].getChild();
2596 if (s->mChildMask.isOn(i)) {
2597 child->topologyIntersection(*(s->mNodes[i].getChild()), b);
2598 }
else if (s->mValueMask.isOff(i)) {
2600 t->mNodes[i].setValue(b);
2602 }
else if (t->mValueMask.isOn(i) && s->mChildMask.isOn(i)) {
2603 t->mNodes[i].setChild(
new ChildT(*(s->mNodes[i].getChild()),
2608 const OtherInternalNode*
s;
2613template<
typename ChildT, Index Log2Dim>
2614template<
typename OtherChildT>
2622template<
typename ChildT, Index Log2Dim>
2623template<
typename OtherInternalNode>
2628 { tC = (tC & (sC | ~sV)) | (tV & sC); }
2631 { tV &= ~((tC & sV) | (sC | sV)); }
2634 const ValueType& background) : s(source), t(target), b(background) {
2636 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
2641 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op1);
2644 t->mValueMask.foreach(t->mChildMask, s->mValueMask, oldChildMask, op2);
2645 assert((t->mValueMask & t->mChildMask).isOff());
2648 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2649 if (t->mChildMask.isOn(i)) {
2650 ChildT*
child = t->mNodes[i].getChild();
2651 if (s->mChildMask.isOn(i)) {
2652 child->topologyDifference(*(s->mNodes[i].getChild()), b);
2653 }
else if (s->mValueMask.isOn(i)) {
2655 t->mNodes[i].setValue(b);
2657 }
else if (t->mValueMask.isOn(i)) {
2658 if (s->mChildMask.isOn(i)) {
2659 const typename OtherInternalNode::ChildNodeType& other =
2660 *(s->mNodes[i].getChild());
2661 ChildT*
child =
new ChildT(other.origin(), t->mNodes[i].getValue(),
true);
2662 child->topologyDifference(other, b);
2663 t->mNodes[i].setChild(
child);
2668 const OtherInternalNode*
s;
2673template<
typename ChildT, Index Log2Dim>
2674template<
typename OtherChildT>
2686template<
typename ChildT, Index Log2Dim>
2687template<
typename CombineOp>
2691 const ValueType zero = zeroVal<ValueType>();
2695 for (
Index i = 0; i < NUM_VALUES; ++i) {
2699 op(args.
setARef(mNodes[i].getValue())
2703 mNodes[i].setValue(args.
result());
2712 }
else if (this->isChildMaskOff(i) && other.
isChildMaskOn(i)) {
2721 child->combine(mNodes[i].getValue(), isValueMaskOn(i), swappedOp);
2726 this->setChildNode(i,
child);
2732 *
child = mNodes[i].getChild(),
2736 if (
child && otherChild) {
2737 child->combine(*otherChild, op);
2744template<
typename ChildT, Index Log2Dim>
2745template<
typename CombineOp>
2751 for (
Index i = 0; i < NUM_VALUES; ++i) {
2752 if (this->isChildMaskOff(i)) {
2754 op(args.
setARef(mNodes[i].getValue())
2757 .setBIsActive(valueIsActive));
2758 mNodes[i].setValue(args.
result());
2773template<
typename ChildT, Index Log2Dim>
2774template<
typename CombineOp,
typename OtherNodeType>
2781 for (
Index i = 0; i < NUM_VALUES; ++i) {
2785 .
setBRef(other1.mNodes[i].getValue())
2788 this->makeChildNodeEmpty(i, args.
result());
2791 if (this->isChildMaskOff(i)) {
2795 : other1.mNodes[i].getChild()->origin();
2796 this->setChildNode(i,
new ChildNodeType(childOrigin, mNodes[i].getValue()));
2804 }
else if (other1.isChildMaskOff(i)) {
2808 other1.mNodes[i].getValue(), other1.isValueMaskOn(i), op);
2813 *other1.mNodes[i].getChild(), op);
2820template<
typename ChildT, Index Log2Dim>
2821template<
typename CombineOp,
typename OtherNodeType>
2824 bool valueIsActive, CombineOp& op)
2828 for (
Index i = 0; i < NUM_VALUES; ++i) {
2829 if (other.isChildMaskOff(i)) {
2832 .
setBRef(other.mNodes[i].getValue())
2835 this->makeChildNodeEmpty(i, args.
result());
2838 typename OtherNodeType::ChildNodeType* otherChild = other.mNodes[i].getChild();
2840 if (this->isChildMaskOff(i)) {
2847 mNodes[i].getChild()->combine2(
value, *otherChild, valueIsActive, op);
2853template<
typename ChildT, Index Log2Dim>
2854template<
typename CombineOp,
typename OtherValueType>
2857 bool valueIsActive, CombineOp& op)
2861 for (
Index i = 0; i < NUM_VALUES; ++i) {
2868 this->makeChildNodeEmpty(i, args.
result());
2873 if (this->isChildMaskOff(i)) {
2875 this->setChildNode(i,
2876 new ChildNodeType(otherChild->origin(), mNodes[i].getValue()));
2880 mNodes[i].getChild()->combine2(*otherChild,
value, valueIsActive, op);
2889template<
typename ChildT, Index Log2Dim>
2890template<
typename BBoxOp>
2897 if (op.template descent<LEVEL>()) {
2898 for (
ChildOnCIter i = this->cbeginChildOn(); i; ++i) i->visitActiveBBox(op);
2901 op.template operator()<LEVEL>(i->getNodeBoundingBox());
2907template<
typename ChildT, Index Log2Dim>
2908template<
typename VisitorOp>
2912 doVisit<InternalNode, VisitorOp, ChildAllIter>(*
this, op);
2916template<
typename ChildT, Index Log2Dim>
2917template<
typename VisitorOp>
2921 doVisit<const InternalNode, VisitorOp, ChildAllCIter>(*
this, op);
2925template<
typename ChildT, Index Log2Dim>
2926template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
2930 typename NodeT::ValueType val;
2931 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
2932 if (op(iter))
continue;
2933 if (
typename ChildAllIterT::ChildNodeType*
child = iter.probeChild(val)) {
2943template<
typename ChildT, Index Log2Dim>
2944template<
typename OtherNodeType,
typename VisitorOp>
2949 typename OtherNodeType::ChildAllIter>(*
this, other, op);
2953template<
typename ChildT, Index Log2Dim>
2954template<
typename OtherNodeType,
typename VisitorOp>
2959 typename OtherNodeType::ChildAllCIter>(*
this, other, op);
2963template<
typename ChildT, Index Log2Dim>
2966 typename OtherNodeT,
2968 typename ChildAllIterT,
2969 typename OtherChildAllIterT>
2974 static_assert(OtherNodeT::NUM_VALUES == NodeT::NUM_VALUES,
2975 "visit2() requires nodes to have the same dimensions");
2976 static_assert(OtherNodeT::LEVEL == NodeT::LEVEL,
2977 "visit2() requires nodes to be at the same tree level");
2979 typename NodeT::ValueType val;
2980 typename OtherNodeT::ValueType otherVal;
2982 ChildAllIterT iter =
self.beginChildAll();
2983 OtherChildAllIterT otherIter = other.beginChildAll();
2985 for ( ; iter && otherIter; ++iter, ++otherIter)
2987 const size_t skipBranch =
static_cast<size_t>(op(iter, otherIter));
2989 typename ChildAllIterT::ChildNodeType*
child =
2990 (skipBranch & 1U) ?
nullptr : iter.probeChild(val);
2991 typename OtherChildAllIterT::ChildNodeType* otherChild =
2992 (skipBranch & 2U) ?
nullptr : otherIter.probeChild(otherVal);
2994 if (
child !=
nullptr && otherChild !=
nullptr) {
2995 child->visit2Node(*otherChild, op);
2996 }
else if (
child !=
nullptr) {
2997 child->visit2(otherIter, op);
2998 }
else if (otherChild !=
nullptr) {
2999 otherChild->visit2(iter, op,
true);
3008template<
typename ChildT, Index Log2Dim>
3009template<
typename OtherChildAllIterType,
typename VisitorOp>
3012 VisitorOp& op,
bool otherIsLHS)
3014 doVisit2<InternalNode, VisitorOp, ChildAllIter, OtherChildAllIterType>(
3015 *
this, otherIter, op, otherIsLHS);
3019template<
typename ChildT, Index Log2Dim>
3020template<
typename OtherChildAllIterType,
typename VisitorOp>
3023 VisitorOp& op,
bool otherIsLHS)
const
3025 doVisit2<const InternalNode, VisitorOp, ChildAllCIter, OtherChildAllIterType>(
3026 *
this, otherIter, op, otherIsLHS);
3030template<
typename ChildT, Index Log2Dim>
3031template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT,
typename OtherChildAllIterT>
3034 VisitorOp& op,
bool otherIsLHS)
3036 if (!otherIter)
return;
3038 const size_t skipBitMask = (otherIsLHS ? 2U : 1U);
3040 typename NodeT::ValueType val;
3041 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
3042 const size_t skipBranch =
static_cast<size_t>(
3043 otherIsLHS ? op(otherIter, iter) : op(iter, otherIter));
3045 typename ChildAllIterT::ChildNodeType*
child =
3046 (skipBranch & skipBitMask) ?
nullptr : iter.probeChild(val);
3048 if (
child !=
nullptr)
child->visit2(otherIter, op, otherIsLHS);
3056template<
typename ChildT, Index Log2Dim>
3060 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3061 iter->writeBuffers(os, toHalf);
3066template<
typename ChildT, Index Log2Dim>
3070 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3071 iter->readBuffers(is, fromHalf);
3076template<
typename ChildT, Index Log2Dim>
3079 const CoordBBox& clipBBox,
bool fromHalf)
3081 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3086 iter->readBuffers(is, clipBBox, fromHalf);
3090 ValueType background = zeroVal<ValueType>();
3092 background = *
static_cast<const ValueType*
>(bgPtr);
3094 this->
clip(clipBBox, background);
3101template<
typename ChildT, Index Log2Dim>
3105 dims.push_back(Log2Dim);
3106 ChildNodeType::getNodeLog2Dims(dims);
3110template<
typename ChildT, Index Log2Dim>
3114 assert(n<(1<<3*Log2Dim));
3115 xyz.
setX(n >> 2*Log2Dim);
3116 n &= ((1<<2*Log2Dim)-1);
3117 xyz.
setY(n >> Log2Dim);
3118 xyz.
setZ(n & ((1<<Log2Dim)-1));
3122template<
typename ChildT, Index Log2Dim>
3126 return (((xyz[0] & (DIM-1u)) >> ChildNodeType::TOTAL) << 2*Log2Dim)
3127 + (((xyz[1] & (DIM-1u)) >> ChildNodeType::TOTAL) << Log2Dim)
3128 + ((xyz[2] & (DIM-1u)) >> ChildNodeType::TOTAL);
3132template<
typename ChildT, Index Log2Dim>
3137 this->offsetToLocalCoord(n, local);
3138 local <<= ChildT::TOTAL;
3139 return local + this->origin();
3146template<
typename ChildT, Index Log2Dim>
3147template<
typename ArrayT>
3151 using T =
typename ArrayT::value_type;
3153 using ArrayChildT =
typename std::conditional<
3154 std::is_const<typename std::remove_pointer<T>::type>
::value,
const ChildT, ChildT>::type;
3155 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3158 array.push_back(
reinterpret_cast<T
>(mNodes[iter.pos()].getChild()));
3160 iter->getNodes(array);
3166template<
typename ChildT, Index Log2Dim>
3167template<
typename ArrayT>
3171 using T =
typename ArrayT::value_type;
3173 static_assert(std::is_const<typename std::remove_pointer<T>::type>
::value,
3174 "argument to getNodes() must be an array of const node pointers");
3175 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3178 array.push_back(
reinterpret_cast<T
>(mNodes[iter.pos()].getChild()));
3180 iter->getNodes(array);
3190template<
typename ChildT, Index Log2Dim>
3191template<
typename ArrayT>
3195 using T =
typename ArrayT::value_type;
3197 using ArrayChildT =
typename std::conditional<
3198 std::is_const<typename std::remove_pointer<T>::type>
::value,
const ChildT, ChildT>::type;
3200 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3201 const Index n = iter.pos();
3203 array.push_back(
reinterpret_cast<T
>(mNodes[n].getChild()));
3204 mValueMask.set(n, state);
3205 mNodes[n].setValue(
value);
3207 iter->stealNodes(array,
value, state);
3218template<
typename ChildT, Index Log2Dim>
3224 for (
Index i = 0; i < NUM_VALUES; ++i) {
3225 if (this->isChildMaskOn(i)) {
3226 mNodes[i].getChild()->resetBackground(oldBackground, newBackground);
3227 }
else if (this->isValueMaskOff(i)) {
3229 mNodes[i].setValue(newBackground);
3237template<
typename ChildT, Index Log2Dim>
3238template<
typename OtherChildNodeType, Index OtherLog2Dim>
3243 if (Log2Dim != OtherLog2Dim || mChildMask != other->
mChildMask ||
3244 mValueMask != other->
mValueMask)
return false;
3245 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3246 if (!iter->hasSameTopology(other->
mNodes[iter.pos()].
getChild()))
return false;
3252template<
typename ChildT, Index Log2Dim>
3257 if (this->isChildMaskOn(i)) {
3258 delete mNodes[i].getChild();
3260 mChildMask.setOn(i);
3261 mValueMask.setOff(i);
3263 mNodes[i].setChild(
child);
3266template<
typename ChildT, Index Log2Dim>
3271 assert(mChildMask.isOff(i));
3272 mChildMask.setOn(i);
3273 mValueMask.setOff(i);
3274 mNodes[i].setChild(
child);
3278template<
typename ChildT, Index Log2Dim>
3282 if (this->isChildMaskOff(i)) {
3283 mNodes[i].setValue(
value);
3287 mChildMask.setOff(i);
3288 mNodes[i].setValue(
value);
3293template<
typename ChildT, Index Log2Dim>
3297 delete this->unsetChildNode(n,
value);
3300template<
typename ChildT, Index Log2Dim>
3304 assert(this->isChildMaskOn(n));
3305 return mNodes[n].getChild();
3309template<
typename ChildT, Index Log2Dim>
3313 assert(this->isChildMaskOn(n));
3314 return mNodes[n].getChild();
ValueT value
Definition: GridBuilder.h:1287
ChildT * child
Definition: GridBuilder.h:1286
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Definition: NanoVDB.h:860
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:451
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: Types.h:503
const AValueType & result() const
Get the output value.
Definition: Types.h:495
CombineArgs & setBIsActive(bool b)
Set the active state of the B value.
Definition: Types.h:519
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
Definition: Types.h:505
bool resultIsActive() const
Definition: Types.h:514
CombineArgs & setAIsActive(bool b)
Set the active state of the A value.
Definition: Types.h:517
Tag dispatch class that distinguishes constructors that deep copy.
Definition: Types.h:566
Tag dispatch class that distinguishes constructors during file input.
Definition: Types.h:570
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:564
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:248
void translate(const Coord &t)
Translate this bounding box by (tx, ty, tz).
Definition: Coord.h:457
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:417
const Coord & min() const
Definition: Coord.h:320
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition: Coord.h:411
const Coord & max() const
Definition: Coord.h:321
bool isInside(const Coord &xyz) const
Return true if point (x, y, z) is inside this bounding box.
Definition: Coord.h:399
void intersect(const CoordBBox &bbox)
Intersect this bounding box with the given bounding box.
Definition: Coord.h:443
static CoordBBox createCube(const Coord &min, ValueType dim)
Definition: Coord.h:312
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:25
Int32 y() const
Definition: Coord.h:131
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:91
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition: Coord.h:175
Int32 x() const
Definition: Coord.h:130
Coord & setZ(Int32 z)
Definition: Coord.h:81
Coord & setY(Int32 y)
Definition: Coord.h:80
static Coord max()
Return the largest possible coordinate.
Definition: Coord.h:46
static bool lessThan(const Coord &a, const Coord &b)
Definition: Coord.h:208
Int32 z() const
Definition: Coord.h:132
Coord & setX(Int32 x)
Definition: Coord.h:79
Definition: InternalNode.h:34
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1782
void visit(VisitorOp &)
Definition: InternalNode.h:2910
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Definition: InternalNode.h:335
void merge(InternalNode &other, const ValueType &background, const ValueType &otherBackground)
Efficiently merge another tree into this tree using one of several schemes.
Definition: InternalNode.h:2383
ChildOnCIter cbeginChildOn() const
Definition: InternalNode.h:220
const ValueType & getFirstValue() const
If the first entry in this node's table is a tile, return the tile's value. Otherwise,...
Definition: InternalNode.h:2298
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by the node regardless of it...
Definition: InternalNode.h:299
ChildOnCIter beginChildOn() const
Definition: InternalNode.h:223
ChildOnIter beginChildOn()
Definition: InternalNode.h:226
NodeType * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists,...
bool isChildMaskOff(Index n) const
Definition: InternalNode.h:770
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition: InternalNode.h:1591
void writeTopology(std::ostream &, bool toHalf=false) const
Definition: InternalNode.h:2213
void copyToDense(const CoordBBox &bbox, DenseT &dense) const
Copy into a dense grid the values of the voxels that lie within a given bounding box.
Definition: InternalNode.h:2168
void setChildNode(Index i, ChildNodeType *child)
Definition: InternalNode.h:3268
bool isChildMaskOff() const
Definition: InternalNode.h:771
ValueOffCIter cbeginValueOff() const
Definition: InternalNode.h:232
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
Index32 transientData() const
Return the transient data value.
Definition: InternalNode.h:273
void addLeafAndCache(LeafNodeType *leaf, AccessorT &)
Same as addLeaf() except, if necessary, update the accessor with pointers to the nodes along the path...
Definition: InternalNode.h:1369
static Index getChildDim()
Definition: InternalNode.h:256
void visit2(IterT &otherIter, VisitorOp &, bool otherIsLHS=false) const
const NodeMaskType & getChildMask() const
Definition: InternalNode.h:773
Index32 nonLeafCount() const
Definition: InternalNode.h:1058
void topologyIntersection(const InternalNode< OtherChildNodeType, Log2Dim > &other, const ValueType &background)
Intersects this tree's set of active values with the active values of the other tree,...
NodeMaskType mChildMask
Definition: InternalNode.h:825
bool isValueMaskOff() const
Definition: InternalNode.h:768
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition: InternalNode.h:3149
bool isValueMaskOn() const
Definition: InternalNode.h:766
void visit2(IterT &otherIter, VisitorOp &, bool otherIsLHS=false)
NodeT * stealNode(const Coord &xyz, const ValueType &value, bool state)
Return a pointer to the node of type NodeT that contains voxel (x, y, z) and replace it with a tile o...
Definition: InternalNode.h:1192
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition: InternalNode.h:2362
NodeMaskType mValueMask
Definition: InternalNode.h:825
InternalNode()
Default constructor.
Definition: InternalNode.h:72
bool isChildMaskOn(Index n) const
Definition: InternalNode.h:769
~InternalNode()
Definition: InternalNode.h:1020
Index64 onLeafVoxelCount() const
Definition: InternalNode.h:1103
const LeafNodeType * probeConstLeafAndCache(const Coord &xyz, AccessorT &acc) const
NodeMaskType getValueOffMask() const
Definition: InternalNode.h:774
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition: InternalNode.h:1294
static void doVisit(NodeT &, VisitorOp &)
Definition: InternalNode.h:2928
ValueAllCIter cbeginValueAll() const
Definition: InternalNode.h:233
void prune(const ValueType &tolerance=zeroVal< ValueType >())
Reduce the memory footprint of this tree by replacing with tiles any nodes whose values are all the s...
Definition: InternalNode.h:1168
ValueOnCIter beginValueOn() const
Definition: InternalNode.h:234
Index64 offLeafVoxelCount() const
Definition: InternalNode.h:1115
void resetBackground(const ValueType &oldBackground, const ValueType &newBackground)
Change inactive tiles or voxels with value oldBackground to newBackground or -oldBackground to -newBa...
Definition: InternalNode.h:3220
void addTile(Index level, const Coord &xyz, const ValueType &value, bool state)
Add a tile at the specified tree level that contains voxel (x, y, z), possibly creating a parent bran...
Definition: InternalNode.h:1428
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
Definition: InternalNode.h:269
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: InternalNode.h:267
bool isInactive() const
Return true if this node has no children and only contains inactive values.
Definition: InternalNode.h:330
static void doVisit2Node(NodeT &, OtherNodeT &, VisitorOp &)
Definition: InternalNode.h:2971
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: InternalNode.h:1960
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1823
void combine2(const InternalNode &other0, const OtherNodeType &other1, CombineOp &)
Definition: InternalNode.h:2776
friend class InternalNode
During topology-only construction, access is needed to protected/private members of other template in...
Definition: InternalNode.h:761
bool isValueMaskOff(Index n) const
Definition: InternalNode.h:767
void setValueOnly(const Coord &xyz, const ValueType &value)
Set the value of the voxel at the given coordinates but don't change its active state.
Definition: InternalNode.h:1806
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Definition: InternalNode.h:1320
Index getValueLevelAndCache(const Coord &xyz, AccessorT &) const
Return the level of the tree (0 = leaf) at which the value at the given coordinates resides.
Definition: InternalNode.h:1644
const NodeType * probeConstNodeAndCache(const Coord &xyz, AccessorT &) 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.
Definition: InternalNode.h:2064
ValueOffCIter beginValueOff() const
Definition: InternalNode.h:236
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1737
void addLeaf(LeafNodeType *leaf)
Add the specified leaf to this node, possibly creating a child branch in the process....
Definition: InternalNode.h:1340
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
ChildAllCIter cbeginChildAll() const
Definition: InternalNode.h:222
void clip(const CoordBBox &, const ValueType &background)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: InternalNode.h:2014
ChildAllIter beginChildAll()
Definition: InternalNode.h:228
static Index getLevel()
Definition: InternalNode.h:249
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Definition: InternalNode.h:1601
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,...
bool probeValue(const Coord &xyz, ValueType &value) const
Definition: InternalNode.h:1657
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don't change its value.
Definition: InternalNode.h:1844
ValueOnIter beginValueOn()
Definition: InternalNode.h:238
void modifyValueAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active....
Definition: InternalNode.h:1926
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...
ChildOffCIter cbeginChildOff() const
Definition: InternalNode.h:221
ChildOffIter beginChildOff()
Definition: InternalNode.h:227
Index64 onVoxelCount() const
Definition: InternalNode.h:1079
ChildOffCIter beginChildOff() const
Definition: InternalNode.h:224
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition: InternalNode.h:3124
void addTileAndCache(Index level, const Coord &xyz, const ValueType &, bool state, AccessorT &)
Same as addTile() except, if necessary, update the accessor with pointers to the nodes along the path...
Definition: InternalNode.h:1460
typename ChildNodeType::LeafNodeType LeafNodeType
Definition: InternalNode.h:37
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition: InternalNode.h:1685
NodeType * probeNodeAndCache(const Coord &xyz, AccessorT &)
Same as probeNode() except, if necessary, update the accessor with pointers to the nodes along the pa...
void writeBuffers(std::ostream &, bool toHalf=false) const
Definition: InternalNode.h:3058
ValueOnCIter cbeginValueOn() const
Definition: InternalNode.h:230
typename ChildNodeType::ValueType ValueType
Definition: InternalNode.h:38
Index32 leafCount() const
Definition: InternalNode.h:1033
const LeafNodeType * probeLeaf(const Coord &xyz) const
void resetChildNode(Index i, ChildNodeType *child)
Definition: InternalNode.h:3254
Index32 childCount() const
Definition: InternalNode.h:1071
Index getValueLevel(const Coord &xyz) const
Return the level of the tree (0 = leaf) at which the value at the given coordinates resides.
Definition: InternalNode.h:1635
Index64 onTileCount() const
Definition: InternalNode.h:1126
void modifyValue(const Coord &xyz, const ModifyOp &op)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active.
Definition: InternalNode.h:1898
void visitActiveBBox(BBoxOp &) const
Calls the templated functor BBoxOp with bounding box information for all active tiles and leaf nodes ...
Definition: InternalNode.h:2892
bool hasSameTopology(const InternalNode< OtherChildNodeType, OtherLog2Dim > *other) const
Return true if the given tree branch has the same node and active value topology as this tree branch ...
Definition: InternalNode.h:3240
void setValueMask(Index n, bool on)
Definition: InternalNode.h:786
Index64 offVoxelCount() const
Definition: InternalNode.h:1091
typename NodeMaskType::OffIterator MaskOffIterator
Definition: InternalNode.h:115
bool isConstant(ValueType &firstValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
Definition: InternalNode.h:1529
LeafNodeType * touchLeaf(const Coord &xyz)
Return the leaf node that contains voxel (x, y, z). If no such node exists, create one,...
Definition: InternalNode.h:1496
void denseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value and ensure that those voxels are a...
Definition: InternalNode.h:2120
static const Index NUM_VALUES
Definition: InternalNode.h:47
UnionType mNodes[NUM_VALUES]
Definition: InternalNode.h:821
void negate()
Change the sign of all the values represented in this node and its child nodes.
Definition: InternalNode.h:2318
void readTopology(std::istream &, bool fromHalf=false)
Definition: InternalNode.h:2238
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Definition: InternalNode.h:3134
ChildAllCIter beginChildAll() const
Definition: InternalNode.h:225
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Definition: InternalNode.h:1863
void setValuesOn()
Mark all values (both tiles and voxels) as active.
Definition: InternalNode.h:1886
void makeChildNodeEmpty(Index n, const ValueType &value)
Definition: InternalNode.h:3295
void setTransientData(Index32 transientData)
Set the transient data value.
Definition: InternalNode.h:275
typename ChildNodeType::BuildType BuildType
Definition: InternalNode.h:39
LeafNodeType * touchLeafAndCache(const Coord &xyz, AccessorT &)
Same as touchLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
void stealNodes(ArrayT &array, const ValueType &value, bool state)
Steals all nodes of a certain type from the tree and adds them to a container with the following API:
Definition: InternalNode.h:3193
ChildNodeType * getChildNode(Index n)
Returns a pointer to the child node at the linear offset n.
Definition: InternalNode.h:3302
typename NodeMaskType::OnIterator MaskOnIterator
Definition: InternalNode.h:114
const LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc) const
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Definition: InternalNode.h:1670
static void doVisit2(NodeT &, OtherChildAllIterT &, VisitorOp &, bool otherIsLHS)
Definition: InternalNode.h:3033
bool addChild(ChildNodeType *child)
Add the given child node at this level deducing the offset from it's origin. If a child node with thi...
Definition: InternalNode.h:1402
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
Expand the specified bounding box so that it includes the active tiles of this internal node as well ...
Definition: InternalNode.h:1150
bool isEmpty() const
Definition: InternalNode.h:302
const UnionType * getTable() const
Definition: InternalNode.h:781
static void getNodeLog2Dims(std::vector< Index > &dims)
Populated an std::vector with the dimension of all the nodes in the branch starting with this node.
Definition: InternalNode.h:3103
ValueOffIter beginValueOff()
Definition: InternalNode.h:240
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition: InternalNode.h:1701
_ChildNodeType ChildNodeType
Definition: InternalNode.h:36
static void offsetToLocalCoord(Index n, Coord &xyz)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0,...
Definition: InternalNode.h:3112
const NodeMaskType & getValueMask() const
Definition: InternalNode.h:772
const NodeType * probeConstNode(const Coord &xyz) const
bool hasActiveTiles() const
Return true if this node or any of its child nodes have any active tiles.
Definition: InternalNode.h:1576
void combine(InternalNode &other, CombineOp &)
Definition: InternalNode.h:2689
const ValueType & getValue(const Coord &xyz) const
Definition: InternalNode.h:1612
void nodeCount(std::vector< Index32 > &vec) const
Definition: InternalNode.h:1045
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
Definition: InternalNode.h:1137
ChildNodeType * unsetChildNode(Index i, const ValueType &value)
Definition: InternalNode.h:3280
void readBuffers(std::istream &, bool fromHalf=false)
Definition: InternalNode.h:3068
typename NodeMaskType::DenseIterator MaskDenseIterator
Definition: InternalNode.h:116
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: InternalNode.h:1983
ValueAllCIter beginValueAll() const
Definition: InternalNode.h:237
Coord mOrigin
Global grid index coordinates (x,y,z) of the local origin of this node.
Definition: InternalNode.h:827
static Index dim()
Definition: InternalNode.h:246
void visit2Node(OtherNodeType &other, VisitorOp &)
Definition: InternalNode.h:2946
bool isValueMaskOn(Index n) const
Definition: InternalNode.h:765
ValueAllIter beginValueAll()
Definition: InternalNode.h:241
const ValueType & getLastValue() const
If the last entry in this node's table is a tile, return the tile's value. Otherwise,...
Definition: InternalNode.h:2306
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:30
const ValueT & getValue() const
Definition: NodeUnion.h:45
ChildT * getChild() const
Definition: NodeUnion.h:42
void setValue(const ValueT &val)
Definition: NodeUnion.h:47
Definition: NodeMasks.h:271
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation.
Definition: NodeMasks.h:308
Index64 Word
Definition: NodeMasks.h:316
void toggle(Index32 n)
Toggle the state of the nth bit.
Definition: NodeMasks.h:483
void setOff(Index32 n)
Set the nth bit off.
Definition: NodeMasks.h:457
void setOn(Index32 n)
Set the nth bit on.
Definition: NodeMasks.h:452
Definition: NodeMasks.h:240
Definition: NodeMasks.h:209
BBox< Coord > CoordBBox
Definition: NanoVDB.h:1658
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
void writeCompressedValues(std::ostream &os, ValueT *srcBuf, Index srcCount, const MaskT &valueMask, const MaskT &childMask, bool toHalf)
Definition: Compression.h:645
void readCompressedValues(std::istream &is, ValueT *destBuf, Index destCount, const MaskT &valueMask, bool fromHalf)
Definition: Compression.h:465
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...
Level getLevel()
Return the current logging level.
Definition: logging.h:141
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:444
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
Definition: Math.h:407
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:127
Index32 Index
Definition: Types.h:54
uint32_t Index32
Definition: Types.h:52
int32_t Int32
Definition: Types.h:56
uint64_t Index64
Definition: Types.h:53
@ MERGE_ACTIVE_STATES
Definition: Types.h:389
@ MERGE_NODES
Definition: Types.h:390
@ MERGE_ACTIVE_STATES_AND_NODES
Definition: Types.h:391
@ OPENVDB_FILE_VERSION_NODE_MASK_COMPRESSION
Definition: version.h.in:246
@ OPENVDB_FILE_VERSION_INTERNALNODE_COMPRESSION
Definition: version.h.in:237
ValueType combine(const ValueType &v0, const ValueType &v1, const ValueType &v2, const openvdb::Vec3d &w)
Combine different value types.
Definition: AttributeTransferUtil.h:141
Definition: Exceptions.h:13
Base class for dense iterators over internal and leaf nodes.
Definition: Iterator.h:179
typename std::remove_const< UnsetItemT >::type NonConstValueType
Definition: Iterator.h:184
Definition: InternalNode.h:129
ChildIter(const MaskIterT &iter, NodeT *parent)
Definition: InternalNode.h:131
ChildIter()
Definition: InternalNode.h:130
ChildT & getItem(Index pos) const
Definition: InternalNode.h:134
void setItem(Index pos, const ChildT &c) const
Definition: InternalNode.h:141
Definition: InternalNode.h:120
Definition: InternalNode.h:120
Definition: InternalNode.h:891
DeepCopy(const OtherInternalNode *source, InternalNode *target)
Definition: InternalNode.h:892
InternalNode * t
Definition: InternalNode.h:906
const OtherInternalNode * s
Definition: InternalNode.h:905
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:896
Definition: InternalNode.h:172
DenseIter(const MaskDenseIterator &iter, NodeT *parent)
Definition: InternalNode.h:177
void unsetItem(Index pos, const ValueT &value) const
Definition: InternalNode.h:198
void setItem(Index pos, ChildT *child) const
Definition: InternalNode.h:192
DenseIter()
Definition: InternalNode.h:176
bool getItem(Index pos, ChildT *&child, NonConstValueT &value) const
Definition: InternalNode.h:180
typename BaseT::NonConstValueType NonConstValueT
Definition: InternalNode.h:174
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of an Intern...
Definition: InternalNode.h:64
Definition: InternalNode.h:941
TopologyCopy1(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:942
InternalNode * t
Definition: InternalNode.h:958
const OtherInternalNode * s
Definition: InternalNode.h:957
const ValueType & b
Definition: InternalNode.h:959
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:947
Definition: InternalNode.h:980
const ValueType & offV
Definition: InternalNode.h:998
TopologyCopy2(const OtherInternalNode *source, InternalNode *target, const ValueType &offValue, const ValueType &onValue)
Definition: InternalNode.h:981
InternalNode * t
Definition: InternalNode.h:997
const OtherInternalNode * s
Definition: InternalNode.h:996
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:986
Definition: InternalNode.h:2627
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
Definition: InternalNode.h:2627
Definition: InternalNode.h:2630
void operator()(W &tV, const W &sC, const W &sV, const W &tC) const
Definition: InternalNode.h:2630
Definition: InternalNode.h:2625
TopologyDifference(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:2633
typename NodeMaskType::Word W
Definition: InternalNode.h:2626
InternalNode * t
Definition: InternalNode.h:2669
const OtherInternalNode * s
Definition: InternalNode.h:2668
const ValueType & b
Definition: InternalNode.h:2670
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2647
Definition: InternalNode.h:2577
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
Definition: InternalNode.h:2577
Definition: InternalNode.h:2575
TopologyIntersection(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:2580
typename NodeMaskType::Word W
Definition: InternalNode.h:2576
InternalNode * t
Definition: InternalNode.h:2609
const OtherInternalNode * s
Definition: InternalNode.h:2608
const ValueType & b
Definition: InternalNode.h:2610
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2592
Definition: InternalNode.h:2525
void operator()(W &tV, const W &sV, const W &tC) const
Definition: InternalNode.h:2525
Definition: InternalNode.h:2523
typename NodeMaskType::Word W
Definition: InternalNode.h:2524
InternalNode * t
Definition: InternalNode.h:2560
const bool mPreserveTiles
Definition: InternalNode.h:2561
const OtherInternalNode * s
Definition: InternalNode.h:2559
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2541
TopologyUnion(const OtherInternalNode *source, InternalNode *target, const bool preserveTiles)
Definition: InternalNode.h:2528
ValueConverter<T>::Type is the type of an InternalNode having the same child hierarchy and dimensions...
Definition: InternalNode.h:55
Definition: InternalNode.h:150
void modifyItem(Index pos, const ModifyOp &op) const
Definition: InternalNode.h:162
ValueIter(const MaskIterT &iter, NodeT *parent)
Definition: InternalNode.h:152
const ValueT & getItem(Index pos) const
Definition: InternalNode.h:155
ValueIter()
Definition: InternalNode.h:151
void setItem(Index pos, const ValueT &v) const
Definition: InternalNode.h:158
Definition: InternalNode.h:119
Definition: InternalNode.h:119
Definition: InternalNode.h:2336
InternalNode * mNode
Definition: InternalNode.h:2357
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2344
VoxelizeActiveTiles(InternalNode &node)
Definition: InternalNode.h:2337
Definition: InternalNode.h:842
Base class for sparse iterators over internal and leaf nodes.
Definition: Iterator.h:115
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202