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>
29 template<
typename, Index,
typename>
struct SameInternalConfig;
32 template<
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>
65 static const bool value =
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);
272 void nodeCount(std::vector<Index32> &vec)
const;
277 Index64 onLeafVoxelCount()
const;
278 Index64 offLeafVoxelCount()
const;
288 void evalActiveBoundingBox(
CoordBBox& bbox,
bool visitVoxels =
true)
const;
295 bool isEmpty()
const {
return mChildMask.isOff(); }
302 bool isConstant(ValueType& firstValue,
bool& state,
303 const ValueType& tolerance = zeroVal<ValueType>())
const;
319 bool isConstant(ValueType& minValue, ValueType& maxValue,
320 bool& state,
const ValueType& tolerance = zeroVal<ValueType>())
const;
323 bool isInactive()
const {
return this->isChildMaskOff() && this->isValueMaskOff(); }
326 bool isValueOn(
const Coord& xyz)
const;
331 bool hasActiveTiles()
const;
333 const ValueType& getValue(
const Coord& xyz)
const;
334 bool probeValue(
const Coord& xyz, ValueType& value)
const;
342 const ValueType& getFirstValue()
const;
345 const ValueType& getLastValue()
const;
348 void setActiveState(
const Coord& xyz,
bool on);
350 void setValueOnly(
const Coord& xyz,
const ValueType& value);
352 void setValueOn(
const Coord& xyz);
354 void setValueOn(
const Coord& xyz,
const ValueType& value);
356 void setValueOff(
const Coord& xyz);
358 void setValueOff(
const Coord& xyz,
const ValueType& value);
362 template<
typename ModifyOp>
363 void modifyValue(
const Coord& xyz,
const ModifyOp& op);
365 template<
typename ModifyOp>
366 void modifyValueAndActiveState(
const Coord& xyz,
const ModifyOp& op);
372 template<
typename AccessorT>
379 template<
typename AccessorT>
380 bool isValueOnAndCache(
const Coord& xyz, AccessorT&)
const;
386 template<
typename AccessorT>
387 void setValueAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
393 template<
typename AccessorT>
394 void setValueOnlyAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
401 template<
typename ModifyOp,
typename AccessorT>
402 void modifyValueAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
408 template<
typename ModifyOp,
typename AccessorT>
409 void modifyValueAndActiveStateAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
415 template<
typename AccessorT>
416 void setValueOffAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
422 template<
typename AccessorT>
423 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&);
430 template<
typename AccessorT>
431 bool probeValueAndCache(
const Coord& xyz,
ValueType& value, AccessorT&)
const;
439 template<
typename AccessorT>
440 Index getValueLevelAndCache(
const Coord& xyz, AccessorT&)
const;
448 void writeTopology(std::ostream&,
bool toHalf =
false)
const;
449 void readTopology(std::istream&,
bool fromHalf =
false);
450 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
451 void readBuffers(std::istream&,
bool fromHalf =
false);
452 void readBuffers(std::istream&,
const CoordBBox&,
bool fromHalf =
false);
484 void voxelizeActiveTiles(
bool threaded =
true);
493 template<
typename DenseT>
498 template<MergePolicy Policy>
503 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive);
517 template<
typename OtherChildNodeType>
533 template<
typename OtherChildNodeType>
548 template<
typename OtherChildNodeType>
552 template<
typename CombineOp>
554 template<
typename CombineOp>
557 template<
typename CombineOp,
typename OtherNodeType >
558 void combine2(
const InternalNode& other0,
const OtherNodeType& other1, CombineOp&);
559 template<
typename CombineOp,
typename OtherNodeType >
560 void combine2(
const ValueType& value,
const OtherNodeType& other,
bool valIsActive, CombineOp&);
561 template<
typename CombineOp,
typename OtherValueType>
562 void combine2(
const InternalNode& other,
const OtherValueType&,
bool valIsActive, CombineOp&);
569 template<
typename BBoxOp>
void visitActiveBBox(BBoxOp&)
const;
571 template<
typename VisitorOp>
void visit(VisitorOp&);
572 template<
typename VisitorOp>
void visit(VisitorOp&)
const;
574 template<
typename OtherNodeType,
typename VisitorOp>
575 void visit2Node(OtherNodeType& other, VisitorOp&);
576 template<
typename OtherNodeType,
typename VisitorOp>
577 void visit2Node(OtherNodeType& other, VisitorOp&)
const;
578 template<
typename IterT,
typename VisitorOp>
579 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false);
580 template<
typename IterT,
typename VisitorOp>
581 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false)
const;
597 template<
typename AccessorT>
608 template<
typename NodeT>
609 NodeT* stealNode(
const Coord& xyz,
const ValueType& value,
bool state);
628 template<
typename AccessorT>
629 void addTileAndCache(
Index level,
const Coord& xyz,
const ValueType&,
bool state, AccessorT&);
632 template<
typename NodeType> NodeType* probeNode(
const Coord& xyz);
639 template<
typename NodeType,
typename AccessorT>
643 template<
typename NodeType,
typename AccessorT>
656 template<
typename AccessorT>
660 template<
typename AccessorT>
662 template<
typename AccessorT>
676 template<
typename AccessorT>
680 template<
typename ArrayT>
703 void getNodes(ArrayT& array);
704 template<
typename ArrayT>
705 void getNodes(ArrayT& array)
const;
731 template<
typename ArrayT>
732 void stealNodes(ArrayT& array,
const ValueType& value,
bool state);
740 template<
typename OtherChildNodeType, Index OtherLog2Dim>
777 void setValueMask(
Index n,
bool on) { mValueMask.set(n, mChildMask.isOn(n) ?
false : on); }
782 void makeChildNodeEmpty(
Index n,
const ValueType& value);
783 void setChildNode(
Index i, ChildNodeType* child);
784 void resetChildNode(
Index i, ChildNodeType* child);
785 ChildNodeType* unsetChildNode(
Index i,
const ValueType& value);
787 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
788 static inline void doVisit(NodeT&, VisitorOp&);
790 template<
typename NodeT,
typename OtherNodeT,
typename VisitorOp,
791 typename ChildAllIterT,
typename OtherChildAllIterT>
792 static inline void doVisit2Node(NodeT&, OtherNodeT&, VisitorOp&);
794 template<
typename NodeT,
typename VisitorOp,
795 typename ChildAllIterT,
typename OtherChildAllIterT>
796 static inline void doVisit2(NodeT&, OtherChildAllIterT&, VisitorOp&,
bool otherIsLHS);
802 ChildNodeType* getChildNode(
Index n);
803 const ChildNodeType* getChildNode(
Index n)
const;
808 struct VoxelizeActiveTiles;
809 template<
typename OtherInternalNode>
struct DeepCopy;
810 template<
typename OtherInternalNode>
struct TopologyCopy1;
811 template<
typename OtherInternalNode>
struct TopologyCopy2;
812 template<
typename OtherInternalNode>
struct TopologyUnion;
813 template<
typename OtherInternalNode>
struct TopologyDifference;
814 template<
typename OtherInternalNode>
struct TopologyIntersection;
828 template<
typename ChildT1, Index Dim1,
typename NodeT2>
832 static const bool value =
false;
835 template<
typename ChildT1, Index Dim1,
typename ChildT2>
837 static const bool value = ChildT1::template SameConfiguration<ChildT2>::value;
845 template<
typename ChildT, Index Log2Dim>
849 for (
Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(background);
853 template<
typename ChildT, Index Log2Dim>
856 mOrigin(origin[0] & ~(DIM - 1),
857 origin[1] & ~(DIM - 1),
858 origin[2] & ~(DIM - 1))
867 template<
typename ChildT, Index Log2Dim>
871 : mOrigin(origin[0] & ~(DIM-1), origin[1] & ~(DIM-1), origin[2] & ~(DIM-1))
877 template<
typename ChildT, Index Log2Dim>
878 template<
typename OtherInternalNode>
882 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
886 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
887 if (s->mChildMask.isOff(i)) {
888 t->mNodes[i].setValue(
ValueType(s->mNodes[i].getValue()));
890 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild())));
894 const OtherInternalNode*
s;
898 template<
typename ChildT, Index Log2Dim>
901 mChildMask(other.mChildMask),
902 mValueMask(other.mValueMask),
903 mOrigin(other.mOrigin)
910 template<
typename ChildT, Index Log2Dim>
911 template<
typename OtherChildNodeType>
914 : mChildMask(other.mChildMask)
915 , mValueMask(other.mValueMask)
916 , mOrigin(other.mOrigin)
921 template<
typename ChildT, Index Log2Dim>
922 template<
typename OtherInternalNode>
926 const ValueType& background) : s(source), t(target), b(background) {
927 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
931 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
932 if (s->isChildMaskOn(i)) {
933 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild()),
936 t->mNodes[i].setValue(b);
940 const OtherInternalNode*
s;
945 template<
typename ChildT, Index Log2Dim>
946 template<
typename OtherChildNodeType>
950 mChildMask(other.mChildMask),
951 mValueMask(other.mValueMask),
952 mOrigin(other.mOrigin)
957 template<
typename ChildT, Index Log2Dim>
958 template<
typename OtherInternalNode>
963 : s(source), t(target), offV(offValue), onV(onValue) {
964 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
967 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
968 if (s->isChildMaskOn(i)) {
969 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild()),
972 t->mNodes[i].setValue(s->isValueMaskOn(i) ? onV : offV);
976 const OtherInternalNode*
s;
981 template<
typename ChildT, Index Log2Dim>
982 template<
typename OtherChildNodeType>
987 mChildMask(other.mChildMask),
988 mValueMask(other.mValueMask),
989 mOrigin(other.mOrigin)
995 template<
typename ChildT, Index Log2Dim>
999 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1000 delete mNodes[iter.pos()].getChild();
1008 template<
typename ChildT, Index Log2Dim>
1014 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1015 sum += iter->leafCount();
1020 template<
typename ChildT, Index Log2Dim>
1024 assert(vec.size() > ChildNodeType::LEVEL);
1025 const auto count = mChildMask.countOn();
1026 if (ChildNodeType::LEVEL > 0 && count > 0) {
1027 for (
auto iter = this->cbeginChildOn(); iter; ++iter) iter->nodeCount(vec);
1029 vec[ChildNodeType::LEVEL] += count;
1033 template<
typename ChildT, Index Log2Dim>
1039 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1040 sum += iter->nonLeafCount();
1046 template<
typename ChildT, Index Log2Dim>
1050 return this->getChildMask().countOn();
1054 template<
typename ChildT, Index Log2Dim>
1058 Index64 sum = ChildT::NUM_VOXELS * mValueMask.countOn();
1059 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1060 sum += iter->onVoxelCount();
1066 template<
typename ChildT, Index Log2Dim>
1070 Index64 sum = ChildT::NUM_VOXELS * (NUM_VALUES-mValueMask.countOn()-mChildMask.countOn());
1071 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1072 sum += iter->offVoxelCount();
1078 template<
typename ChildT, Index Log2Dim>
1083 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1084 sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount();
1090 template<
typename ChildT, Index Log2Dim>
1095 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1096 sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount();
1101 template<
typename ChildT, Index Log2Dim>
1105 Index64 sum = mValueMask.countOn();
1106 for (
ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) {
1107 sum += iter->onTileCount();
1112 template<
typename ChildT, Index Log2Dim>
1117 + mValueMask.memUsage() +
sizeof(mOrigin);
1118 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1119 sum += iter->memUsage();
1125 template<
typename ChildT, Index Log2Dim>
1129 if (bbox.
isInside(this->getNodeBoundingBox()))
return;
1132 bbox.
expand(i.getCoord(), ChildT::DIM);
1135 i->evalActiveBoundingBox(bbox, visitVoxels);
1143 template<
typename ChildT, Index Log2Dim>
1149 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1150 const Index i = iter.pos();
1151 ChildT* child = mNodes[i].getChild();
1152 child->prune(tolerance);
1153 if (child->isConstant(value, state, tolerance)) {
1155 mChildMask.setOff(i);
1156 mValueMask.set(i, state);
1157 mNodes[i].setValue(value);
1166 template<
typename ChildT, Index Log2Dim>
1167 template<
typename NodeT>
1171 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1172 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1174 const Index n = this->coordToOffset(xyz);
1175 if (mChildMask.isOff(n))
return nullptr;
1176 ChildT* child = mNodes[n].getChild();
1177 if (std::is_same<NodeT, ChildT>::value) {
1178 mChildMask.setOff(n);
1179 mValueMask.set(n, state);
1180 mNodes[n].setValue(value);
1182 return (std::is_same<NodeT, ChildT>::value)
1183 ?
reinterpret_cast<NodeT*
>(child)
1184 : child->template stealNode<NodeT>(xyz, value, state);
1192 template<
typename ChildT, Index Log2Dim>
1193 template<
typename NodeT>
1197 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1198 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1200 const Index n = this->coordToOffset(xyz);
1201 if (mChildMask.isOff(n))
return nullptr;
1202 ChildT* child = mNodes[n].getChild();
1203 return (std::is_same<NodeT, ChildT>::value)
1204 ?
reinterpret_cast<NodeT*
>(child)
1205 : child->template probeNode<NodeT>(xyz);
1210 template<
typename ChildT, Index Log2Dim>
1211 template<
typename NodeT,
typename AccessorT>
1215 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1216 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1218 const Index n = this->coordToOffset(xyz);
1219 if (mChildMask.isOff(n))
return nullptr;
1220 ChildT* child = mNodes[n].getChild();
1221 acc.insert(xyz, child);
1222 return (std::is_same<NodeT, ChildT>::value)
1223 ?
reinterpret_cast<NodeT*
>(child)
1224 : child->template probeNodeAndCache<NodeT>(xyz, acc);
1229 template<
typename ChildT, Index Log2Dim>
1230 template<
typename NodeT>
1234 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1235 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1237 const Index n = this->coordToOffset(xyz);
1238 if (mChildMask.isOff(n))
return nullptr;
1239 const ChildT* child = mNodes[n].getChild();
1240 return (std::is_same<NodeT, ChildT>::value)
1241 ?
reinterpret_cast<const NodeT*
>(child)
1242 : child->template probeConstNode<NodeT>(xyz);
1247 template<
typename ChildT, Index Log2Dim>
1248 template<
typename NodeT,
typename AccessorT>
1252 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1253 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1255 const Index n = this->coordToOffset(xyz);
1256 if (mChildMask.isOff(n))
return nullptr;
1257 const ChildT* child = mNodes[n].getChild();
1258 acc.insert(xyz, child);
1259 return (std::is_same<NodeT, ChildT>::value)
1260 ?
reinterpret_cast<const NodeT*
>(child)
1261 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
1269 template<
typename ChildT, Index Log2Dim>
1270 inline typename ChildT::LeafNodeType*
1273 return this->
template probeNode<LeafNodeType>(xyz);
1277 template<
typename ChildT, Index Log2Dim>
1278 template<
typename AccessorT>
1279 inline typename ChildT::LeafNodeType*
1282 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
1286 template<
typename ChildT, Index Log2Dim>
1287 template<
typename AccessorT>
1288 inline const typename ChildT::LeafNodeType*
1291 return this->probeConstLeafAndCache(xyz, acc);
1295 template<
typename ChildT, Index Log2Dim>
1296 inline const typename ChildT::LeafNodeType*
1299 return this->
template probeConstNode<LeafNodeType>(xyz);
1303 template<
typename ChildT, Index Log2Dim>
1304 template<
typename AccessorT>
1305 inline const typename ChildT::LeafNodeType*
1308 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
1315 template<
typename ChildT, Index Log2Dim>
1319 assert(leaf !=
nullptr);
1320 const Coord& xyz = leaf->origin();
1321 const Index n = this->coordToOffset(xyz);
1322 ChildT* child =
nullptr;
1323 if (mChildMask.isOff(n)) {
1324 if (ChildT::LEVEL>0) {
1325 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1327 child =
reinterpret_cast<ChildT*
>(leaf);
1329 this->setChildNode(n, child);
1331 if (ChildT::LEVEL>0) {
1332 child = mNodes[n].getChild();
1334 delete mNodes[n].getChild();
1335 child =
reinterpret_cast<ChildT*
>(leaf);
1336 mNodes[n].setChild(child);
1339 child->addLeaf(leaf);
1343 template<
typename ChildT, Index Log2Dim>
1344 template<
typename AccessorT>
1348 assert(leaf !=
nullptr);
1349 const Coord& xyz = leaf->origin();
1350 const Index n = this->coordToOffset(xyz);
1351 ChildT* child =
nullptr;
1352 if (mChildMask.isOff(n)) {
1353 if (ChildT::LEVEL>0) {
1354 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1355 acc.insert(xyz, child);
1357 child =
reinterpret_cast<ChildT*
>(leaf);
1359 this->setChildNode(n, child);
1361 if (ChildT::LEVEL>0) {
1362 child = mNodes[n].getChild();
1363 acc.insert(xyz, child);
1365 delete mNodes[n].getChild();
1366 child =
reinterpret_cast<ChildT*
>(leaf);
1367 mNodes[n].setChild(child);
1370 child->addLeafAndCache(leaf, acc);
1377 template<
typename ChildT, Index Log2Dim>
1382 const Coord& xyz = child->origin();
1384 if (
Coord((xyz & ~(DIM-1))) != this->origin())
return false;
1386 const Index n = this->coordToOffset(xyz);
1388 this->resetChildNode(n, child);
1393 template<
typename ChildT, Index Log2Dim>
1397 assert(n < NUM_VALUES);
1398 this->makeChildNodeEmpty(n, value);
1399 mValueMask.set(n, state);
1403 template<
typename ChildT, Index Log2Dim>
1408 if (LEVEL >= level) {
1409 const Index n = this->coordToOffset(xyz);
1410 if (mChildMask.isOff(n)) {
1411 if (LEVEL > level) {
1412 ChildT* child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1413 this->setChildNode(n, child);
1414 child->addTile(level, xyz, value, state);
1416 mValueMask.set(n, state);
1417 mNodes[n].setValue(value);
1420 ChildT* child = mNodes[n].getChild();
1421 if (LEVEL > level) {
1422 child->addTile(level, xyz, value, state);
1425 mChildMask.setOff(n);
1426 mValueMask.set(n, state);
1427 mNodes[n].setValue(value);
1434 template<
typename ChildT, Index Log2Dim>
1435 template<
typename AccessorT>
1438 const ValueType& value,
bool state, AccessorT& acc)
1440 if (LEVEL >= level) {
1441 const Index n = this->coordToOffset(xyz);
1442 if (mChildMask.isOff(n)) {
1443 if (LEVEL > level) {
1444 ChildT* child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1445 this->setChildNode(n, child);
1446 acc.insert(xyz, child);
1447 child->addTileAndCache(level, xyz, value, state, acc);
1449 mValueMask.set(n, state);
1450 mNodes[n].setValue(value);
1453 ChildT* child = mNodes[n].getChild();
1454 if (LEVEL > level) {
1455 acc.insert(xyz, child);
1456 child->addTileAndCache(level, xyz, value, state, acc);
1459 mChildMask.setOff(n);
1460 mValueMask.set(n, state);
1461 mNodes[n].setValue(value);
1471 template<
typename ChildT, Index Log2Dim>
1472 inline typename ChildT::LeafNodeType*
1475 const Index n = this->coordToOffset(xyz);
1476 ChildT* child =
nullptr;
1477 if (mChildMask.isOff(n)) {
1478 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1479 this->setChildNode(n, child);
1481 child = mNodes[n].getChild();
1483 return child->touchLeaf(xyz);
1487 template<
typename ChildT, Index Log2Dim>
1488 template<
typename AccessorT>
1489 inline typename ChildT::LeafNodeType*
1492 const Index n = this->coordToOffset(xyz);
1493 if (mChildMask.isOff(n)) {
1494 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), mValueMask.isOn(n)));
1496 acc.insert(xyz, mNodes[n].getChild());
1497 return mNodes[n].getChild()->touchLeafAndCache(xyz, acc);
1504 template<
typename ChildT, Index Log2Dim>
1509 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1511 firstValue = mNodes[0].getValue();
1512 for (
Index i = 1; i < NUM_VALUES; ++i) {
1524 template<
typename ChildT, Index Log2Dim>
1532 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1533 minValue = maxValue = mNodes[0].getValue();
1534 for (
Index i = 1; i < NUM_VALUES; ++i) {
1535 const ValueType& v = mNodes[i].getValue();
1537 if ((maxValue - v) > tolerance)
return false;
1539 }
else if (v > maxValue) {
1540 if ((v - minValue) > tolerance)
return false;
1551 template<
typename ChildT, Index Log2Dim>
1558 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1559 if (iter->hasActiveTiles())
return true;
1566 template<
typename ChildT, Index Log2Dim>
1570 const Index n = this->coordToOffset(xyz);
1571 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1572 return mNodes[n].getChild()->isValueOn(xyz);
1575 template<
typename ChildT, Index Log2Dim>
1576 template<
typename AccessorT>
1580 const Index n = this->coordToOffset(xyz);
1581 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1582 acc.insert(xyz, mNodes[n].getChild());
1583 return mNodes[n].getChild()->isValueOnAndCache(xyz, acc);
1587 template<
typename ChildT, Index Log2Dim>
1588 inline const typename ChildT::ValueType&
1591 const Index n = this->coordToOffset(xyz);
1592 return this->isChildMaskOff(n) ? mNodes[n].getValue()
1593 : mNodes[n].getChild()->getValue(xyz);
1596 template<
typename ChildT, Index Log2Dim>
1597 template<
typename AccessorT>
1598 inline const typename ChildT::ValueType&
1601 const Index n = this->coordToOffset(xyz);
1602 if (this->isChildMaskOn(n)) {
1603 acc.insert(xyz, mNodes[n].getChild());
1604 return mNodes[n].getChild()->getValueAndCache(xyz, acc);
1606 return mNodes[n].getValue();
1610 template<
typename ChildT, Index Log2Dim>
1614 const Index n = this->coordToOffset(xyz);
1615 return this->isChildMaskOff(n) ? LEVEL : mNodes[n].getChild()->getValueLevel(xyz);
1618 template<
typename ChildT, Index Log2Dim>
1619 template<
typename AccessorT>
1623 const Index n = this->coordToOffset(xyz);
1624 if (this->isChildMaskOn(n)) {
1625 acc.insert(xyz, mNodes[n].getChild());
1626 return mNodes[n].getChild()->getValueLevelAndCache(xyz, acc);
1632 template<
typename ChildT, Index Log2Dim>
1636 const Index n = this->coordToOffset(xyz);
1637 if (this->isChildMaskOff(n)) {
1638 value = mNodes[n].getValue();
1639 return this->isValueMaskOn(n);
1641 return mNodes[n].getChild()->probeValue(xyz, value);
1644 template<
typename ChildT, Index Log2Dim>
1645 template<
typename AccessorT>
1650 const Index n = this->coordToOffset(xyz);
1651 if (this->isChildMaskOn(n)) {
1652 acc.insert(xyz, mNodes[n].getChild());
1653 return mNodes[n].getChild()->probeValueAndCache(xyz, value, acc);
1655 value = mNodes[n].getValue();
1656 return this->isValueMaskOn(n);
1660 template<
typename ChildT, Index Log2Dim>
1664 const Index n = this->coordToOffset(xyz);
1665 bool hasChild = this->isChildMaskOn(n);
1666 if (!hasChild && this->isValueMaskOn(n)) {
1670 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
true));
1672 if (hasChild) mNodes[n].getChild()->setValueOff(xyz);
1676 template<
typename ChildT, Index Log2Dim>
1680 const Index n = this->coordToOffset(xyz);
1681 bool hasChild = this->isChildMaskOn(n);
1682 if (!hasChild && !this->isValueMaskOn(n)) {
1686 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
false));
1688 if (hasChild) mNodes[n].getChild()->setValueOn(xyz);
1692 template<
typename ChildT, Index Log2Dim>
1697 bool hasChild = this->isChildMaskOn(n);
1699 const bool active = this->isValueMaskOn(n);
1705 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1708 if (hasChild) mNodes[n].getChild()->setValueOff(xyz, value);
1711 template<
typename ChildT, Index Log2Dim>
1712 template<
typename AccessorT>
1718 bool hasChild = this->isChildMaskOn(n);
1720 const bool active = this->isValueMaskOn(n);
1726 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1730 ChildT* child = mNodes[n].getChild();
1731 acc.insert(xyz, child);
1732 child->setValueOffAndCache(xyz, value, acc);
1737 template<
typename ChildT, Index Log2Dim>
1741 const Index n = this->coordToOffset(xyz);
1742 bool hasChild = this->isChildMaskOn(n);
1744 const bool active = this->isValueMaskOn(n);
1750 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1753 if (hasChild) mNodes[n].getChild()->setValueOn(xyz, value);
1756 template<
typename ChildT, Index Log2Dim>
1757 template<
typename AccessorT>
1762 const Index n = this->coordToOffset(xyz);
1763 bool hasChild = this->isChildMaskOn(n);
1765 const bool active = this->isValueMaskOn(n);
1771 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1775 acc.insert(xyz, mNodes[n].getChild());
1776 mNodes[n].getChild()->setValueAndCache(xyz, value, acc);
1781 template<
typename ChildT, Index Log2Dim>
1785 const Index n = this->coordToOffset(xyz);
1786 bool hasChild = this->isChildMaskOn(n);
1790 const bool active = this->isValueMaskOn(n);
1792 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1794 if (hasChild) mNodes[n].getChild()->setValueOnly(xyz, value);
1797 template<
typename ChildT, Index Log2Dim>
1798 template<
typename AccessorT>
1803 const Index n = this->coordToOffset(xyz);
1804 bool hasChild = this->isChildMaskOn(n);
1808 const bool active = this->isValueMaskOn(n);
1810 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1813 acc.insert(xyz, mNodes[n].getChild());
1814 mNodes[n].getChild()->setValueOnlyAndCache(xyz, value, acc);
1819 template<
typename ChildT, Index Log2Dim>
1823 const Index n = this->coordToOffset(xyz);
1824 bool hasChild = this->isChildMaskOn(n);
1826 if (on != this->isValueMaskOn(n)) {
1831 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1834 if (hasChild) mNodes[n].getChild()->setActiveState(xyz, on);
1837 template<
typename ChildT, Index Log2Dim>
1838 template<
typename AccessorT>
1842 const Index n = this->coordToOffset(xyz);
1843 bool hasChild = this->isChildMaskOn(n);
1845 if (on != this->isValueMaskOn(n)) {
1850 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1854 ChildT* child = mNodes[n].getChild();
1855 acc.insert(xyz, child);
1856 child->setActiveStateAndCache(xyz, on, acc);
1861 template<
typename ChildT, Index Log2Dim>
1865 mValueMask = !mChildMask;
1866 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1867 mNodes[iter.pos()].getChild()->setValuesOn();
1872 template<
typename ChildT, Index Log2Dim>
1873 template<
typename ModifyOp>
1878 bool hasChild = this->isChildMaskOn(n);
1882 const bool active = this->isValueMaskOn(n);
1883 bool createChild = !active;
1887 const ValueType& tileVal = mNodes[n].getValue();
1894 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1897 if (hasChild) mNodes[n].getChild()->modifyValue(xyz, op);
1900 template<
typename ChildT, Index Log2Dim>
1901 template<
typename ModifyOp,
typename AccessorT>
1907 bool hasChild = this->isChildMaskOn(n);
1911 const bool active = this->isValueMaskOn(n);
1912 bool createChild = !active;
1916 const ValueType& tileVal = mNodes[n].getValue();
1923 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1928 acc.insert(xyz, child);
1929 child->modifyValueAndCache(xyz, op, acc);
1934 template<
typename ChildT, Index Log2Dim>
1935 template<
typename ModifyOp>
1940 bool hasChild = this->isChildMaskOn(n);
1942 const bool tileState = this->isValueMaskOn(n);
1943 const ValueType& tileVal = mNodes[n].getValue();
1944 bool modifiedState = !tileState;
1946 op(modifiedVal, modifiedState);
1951 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
1954 if (hasChild) mNodes[n].getChild()->modifyValueAndActiveState(xyz, op);
1957 template<
typename ChildT, Index Log2Dim>
1958 template<
typename ModifyOp,
typename AccessorT>
1961 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
1964 bool hasChild = this->isChildMaskOn(n);
1966 const bool tileState = this->isValueMaskOn(n);
1967 const ValueType& tileVal = mNodes[n].getValue();
1968 bool modifiedState = !tileState;
1970 op(modifiedVal, modifiedState);
1975 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
1980 acc.insert(xyz, child);
1981 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
1989 template<
typename ChildT, Index Log2Dim>
1993 CoordBBox nodeBBox = this->getNodeBoundingBox();
1996 this->fill(nodeBBox, background,
false);
1997 }
else if (clipBBox.
isInside(nodeBBox)) {
2006 for (
Index pos = 0; pos < NUM_VALUES; ++pos) {
2007 const Coord xyz = this->offsetToGlobalCoord(pos);
2012 this->makeChildNodeEmpty(pos, background);
2013 mValueMask.setOff(pos);
2014 }
else if (!clipBBox.
isInside(tileBBox)) {
2017 if (this->isChildMaskOn(pos)) {
2018 mNodes[pos].getChild()->clip(clipBBox, background);
2023 const ValueType val = mNodes[pos].getValue();
2024 const bool on = this->isValueMaskOn(pos);
2025 mNodes[pos].setValue(background);
2026 mValueMask.setOff(pos);
2027 this->fill(tileBBox, val, on);
2039 template<
typename ChildT, Index Log2Dim>
2043 auto clippedBBox = this->getNodeBoundingBox();
2044 clippedBBox.intersect(bbox);
2045 if (!clippedBBox)
return;
2049 Coord xyz, tileMin, tileMax;
2050 for (
int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.
x() + 1) {
2052 for (
int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.
y() + 1) {
2054 for (
int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.
z() + 1) {
2058 const Index n = this->coordToOffset(xyz);
2059 tileMin = this->offsetToGlobalCoord(n);
2060 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2066 ChildT* child =
nullptr;
2067 if (this->isChildMaskOff(n)) {
2070 child =
new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)};
2071 this->setChildNode(n, child);
2073 child = mNodes[n].getChild();
2079 child->fill(
CoordBBox(xyz, tmp), value, active);
2086 this->makeChildNodeEmpty(n, value);
2087 mValueMask.set(n, active);
2095 template<
typename ChildT, Index Log2Dim>
2099 auto clippedBBox = this->getNodeBoundingBox();
2100 clippedBBox.intersect(bbox);
2101 if (!clippedBBox)
return;
2105 Coord xyz, tileMin, tileMax;
2106 for (
int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.
x() + 1) {
2108 for (
int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.
y() + 1) {
2110 for (
int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.
z() + 1) {
2114 const auto n = this->coordToOffset(xyz);
2117 ChildT* child =
nullptr;
2118 if (this->isChildMaskOn(n)) {
2119 child = mNodes[n].getChild();
2123 child =
new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)};
2124 this->setChildNode(n, child);
2128 tileMin = this->offsetToGlobalCoord(n);
2129 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2132 child->denseFill(
CoordBBox{xyz, clippedBBox.
max()}, value, active);
2142 template<
typename ChildT, Index Log2Dim>
2143 template<
typename DenseT>
2147 using DenseValueType =
typename DenseT::ValueType;
2149 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2150 const Coord&
min = dense.bbox().min();
2151 for (
Coord xyz = bbox.
min(),
max; xyz[0] <= bbox.
max()[0]; xyz[0] =
max[0] + 1) {
2152 for (xyz[1] = bbox.
min()[1]; xyz[1] <= bbox.
max()[1]; xyz[1] =
max[1] + 1) {
2153 for (xyz[2] = bbox.
min()[2]; xyz[2] <= bbox.
max()[2]; xyz[2] =
max[2] + 1) {
2154 const Index n = this->coordToOffset(xyz);
2156 max = this->offsetToGlobalCoord(n).offsetBy(ChildT::DIM-1);
2161 if (this->isChildMaskOn(n)) {
2162 mNodes[n].getChild()->copyToDense(sub, dense);
2164 const ValueType value = mNodes[n].getValue();
2166 DenseValueType* a0 = dense.data() + zStride*sub.
min()[2];
2167 for (
Int32 x=sub.
min()[0], ex=sub.
max()[0]+1; x<ex; ++x) {
2168 DenseValueType* a1 = a0 + x*xStride;
2169 for (
Int32 y=sub.
min()[1], ey=sub.
max()[1]+1; y<ey; ++y) {
2170 DenseValueType* a2 = a1 + y*yStride;
2172 z < ez; ++z, a2 += zStride)
2174 *a2 = DenseValueType(value);
2188 template<
typename ChildT, Index Log2Dim>
2192 mChildMask.save(os);
2193 mValueMask.save(os);
2197 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[NUM_VALUES]);
2199 const ValueType zero = zeroVal<ValueType>();
2200 for (
Index i = 0; i < NUM_VALUES; ++i) {
2201 values[i] = (mChildMask.isOff(i) ? mNodes[i].getValue() : zero);
2207 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2208 iter->writeTopology(os, toHalf);
2213 template<
typename ChildT, Index Log2Dim>
2220 mChildMask.load(is);
2221 mValueMask.load(is);
2224 for (
Index i = 0; i < NUM_VALUES; ++i) {
2225 if (this->isChildMaskOn(i)) {
2228 mNodes[i].setChild(child);
2229 child->readTopology(is);
2232 is.read(
reinterpret_cast<char*
>(&value),
sizeof(
ValueType));
2233 mNodes[i].setValue(value);
2237 const bool oldVersion =
2239 const Index numValues = (oldVersion ? mChildMask.countOff() : NUM_VALUES);
2243 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[numValues]);
2250 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2251 mNodes[iter.pos()].setValue(values[n++]);
2253 assert(n == numValues);
2255 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2256 mNodes[iter.pos()].setValue(values[iter.pos()]);
2261 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2263 mNodes[iter.pos()].setChild(child);
2264 child->readTopology(is, fromHalf);
2273 template<
typename ChildT, Index Log2Dim>
2274 inline const typename ChildT::ValueType&
2277 return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].getValue());
2281 template<
typename ChildT, Index Log2Dim>
2282 inline const typename ChildT::ValueType&
2285 const Index n = NUM_VALUES - 1;
2286 return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].getValue());
2293 template<
typename ChildT, Index Log2Dim>
2297 for (
Index i = 0; i < NUM_VALUES; ++i) {
2298 if (this->isChildMaskOn(i)) {
2299 mNodes[i].getChild()->negate();
2311 template<
typename ChildT, Index Log2Dim>
2316 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2323 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2324 if (mNode->mChildMask.isOn(i)) {
2325 mNode->mNodes[i].getChild()->voxelizeActiveTiles(
true);
2326 }
else if (mNode->mValueMask.isOn(i)) {
2327 const Coord &ijk = mNode->offsetToGlobalCoord(i);
2329 child->voxelizeActiveTiles(
true);
2330 mNode->mNodes[i].setChild(child);
2337 template<
typename ChildT, Index Log2Dim>
2344 for (
ValueOnIter iter = this->beginValueOn(); iter; ++iter) {
2345 this->setChildNode(iter.pos(),
2348 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter)
2349 iter->voxelizeActiveTiles(
false);
2357 template<
typename ChildT, Index Log2Dim>
2358 template<MergePolicy Policy>
2371 const Index n = iter.pos();
2372 if (mChildMask.isOn(n)) {
2374 mNodes[n].getChild()->template merge<MERGE_ACTIVE_STATES>(*iter,
2375 background, otherBackground);
2376 }
else if (mValueMask.isOff(n)) {
2383 child->resetBackground(otherBackground, background);
2384 this->setChildNode(n, child);
2390 const Index n = iter.pos();
2391 if (mValueMask.isOff(n)) {
2393 this->makeChildNodeEmpty(n, iter.getValue());
2394 mValueMask.setOn(n);
2403 const Index n = iter.pos();
2404 if (mChildMask.isOn(n)) {
2406 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2414 child->resetBackground(otherBackground, background);
2415 this->setChildNode(n, child);
2425 const Index n = iter.pos();
2426 if (mChildMask.isOn(n)) {
2428 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2435 child->resetBackground(otherBackground, background);
2436 if (mValueMask.isOn(n)) {
2438 child->template merge<Policy>(mNodes[n].getValue(),
true);
2439 mValueMask.setOff(n);
2441 mChildMask.setOn(n);
2442 mNodes[n].setChild(child);
2448 const Index n = iter.pos();
2449 if (mChildMask.isOn(n)) {
2451 mNodes[n].getChild()->template merge<Policy>(iter.getValue(),
true);
2452 }
else if (mValueMask.isOff(n)) {
2454 mNodes[n].setValue(iter.getValue());
2455 mValueMask.setOn(n);
2466 template<
typename ChildT, Index Log2Dim>
2467 template<MergePolicy Policy>
2476 if (!tileActive)
return;
2479 for (
ValueOffIter iter = this->beginValueOff(); iter; ++iter) {
2480 const Index n = iter.pos();
2481 if (mChildMask.isOn(n)) {
2483 mNodes[n].getChild()->template merge<Policy>(tileValue,
true);
2486 iter.setValue(tileValue);
2487 mValueMask.setOn(n);
2497 template<
typename ChildT, Index Log2Dim>
2498 template<
typename OtherInternalNode>
2503 { tV = (tV | sV) & ~tC; }
2507 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2510 t->mChildMask |= s->mChildMask;
2512 t->mValueMask.foreach(s->mValueMask, t->mChildMask, op);
2513 assert((t->mValueMask & t->mChildMask).isOff());
2516 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2517 if (s->mChildMask.isOn(i)) {
2518 const typename OtherInternalNode::ChildNodeType& other = *(s->mNodes[i].getChild());
2519 if (t->mChildMask.isOn(i)) {
2520 t->mNodes[i].getChild()->topologyUnion(other);
2522 ChildT* child =
new ChildT(other, t->mNodes[i].getValue(),
TopologyCopy());
2523 if (t->mValueMask.isOn(i)) child->setValuesOn();
2524 t->mNodes[i].setChild(child);
2526 }
else if (s->mValueMask.isOn(i) && t->mChildMask.isOn(i)) {
2527 t->mNodes[i].getChild()->setValuesOn();
2531 const OtherInternalNode*
s;
2535 template<
typename ChildT, Index Log2Dim>
2536 template<
typename OtherChildT>
2543 template<
typename ChildT, Index Log2Dim>
2544 template<
typename OtherInternalNode>
2549 { tC = (tC & (sC | sV)) | (tV & sC); }
2552 const ValueType& background) : s(source), t(target), b(background) {
2554 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
2558 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op);
2560 t->mValueMask &= s->mValueMask;
2561 assert((t->mValueMask & t->mChildMask).isOff());
2564 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2565 if (t->mChildMask.isOn(i)) {
2566 ChildT* child = t->mNodes[i].getChild();
2567 if (s->mChildMask.isOn(i)) {
2568 child->topologyIntersection(*(s->mNodes[i].getChild()), b);
2569 }
else if (s->mValueMask.isOff(i)) {
2571 t->mNodes[i].setValue(b);
2573 }
else if (t->mValueMask.isOn(i) && s->mChildMask.isOn(i)) {
2574 t->mNodes[i].setChild(
new ChildT(*(s->mNodes[i].getChild()),
2579 const OtherInternalNode*
s;
2584 template<
typename ChildT, Index Log2Dim>
2585 template<
typename OtherChildT>
2593 template<
typename ChildT, Index Log2Dim>
2594 template<
typename OtherInternalNode>
2599 { tC = (tC & (sC | ~sV)) | (tV & sC); }
2602 { tV &= ~((tC & sV) | (sC | sV)); }
2605 const ValueType& background) : s(source), t(target), b(background) {
2607 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
2612 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op1);
2615 t->mValueMask.foreach(t->mChildMask, s->mValueMask, oldChildMask, op2);
2616 assert((t->mValueMask & t->mChildMask).isOff());
2619 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2620 if (t->mChildMask.isOn(i)) {
2621 ChildT* child = t->mNodes[i].getChild();
2622 if (s->mChildMask.isOn(i)) {
2623 child->topologyDifference(*(s->mNodes[i].getChild()), b);
2624 }
else if (s->mValueMask.isOn(i)) {
2626 t->mNodes[i].setValue(b);
2628 }
else if (t->mValueMask.isOn(i)) {
2629 if (s->mChildMask.isOn(i)) {
2630 const typename OtherInternalNode::ChildNodeType& other =
2631 *(s->mNodes[i].getChild());
2632 ChildT* child =
new ChildT(other.origin(), t->mNodes[i].getValue(),
true);
2633 child->topologyDifference(other, b);
2634 t->mNodes[i].setChild(child);
2639 const OtherInternalNode*
s;
2644 template<
typename ChildT, Index Log2Dim>
2645 template<
typename OtherChildT>
2657 template<
typename ChildT, Index Log2Dim>
2658 template<
typename CombineOp>
2662 const ValueType zero = zeroVal<ValueType>();
2666 for (
Index i = 0; i < NUM_VALUES; ++i) {
2670 op(args.
setARef(mNodes[i].getValue())
2674 mNodes[i].setValue(args.
result());
2683 }
else if (this->isChildMaskOff(i) && other.
isChildMaskOn(i)) {
2692 child->combine(mNodes[i].getValue(), isValueMaskOn(i), swappedOp);
2697 this->setChildNode(i, child);
2703 *child = mNodes[i].getChild(),
2707 if (child && otherChild) {
2708 child->combine(*otherChild, op);
2715 template<
typename ChildT, Index Log2Dim>
2716 template<
typename CombineOp>
2722 for (
Index i = 0; i < NUM_VALUES; ++i) {
2723 if (this->isChildMaskOff(i)) {
2725 op(args.
setARef(mNodes[i].getValue())
2728 .setBIsActive(valueIsActive));
2729 mNodes[i].setValue(args.
result());
2735 if (child) child->combine(value, valueIsActive, op);
2744 template<
typename ChildT, Index Log2Dim>
2745 template<
typename CombineOp,
typename OtherNodeType>
2752 for (
Index i = 0; i < NUM_VALUES; ++i) {
2756 .
setBRef(other1.mNodes[i].getValue())
2759 this->makeChildNodeEmpty(i, args.
result());
2762 if (this->isChildMaskOff(i)) {
2766 : other1.mNodes[i].getChild()->origin();
2767 this->setChildNode(i,
new ChildNodeType(childOrigin, mNodes[i].getValue()));
2775 }
else if (other1.isChildMaskOff(i)) {
2779 other1.mNodes[i].getValue(), other1.isValueMaskOn(i), op);
2784 *other1.mNodes[i].getChild(), op);
2791 template<
typename ChildT, Index Log2Dim>
2792 template<
typename CombineOp,
typename OtherNodeType>
2795 bool valueIsActive, CombineOp& op)
2799 for (
Index i = 0; i < NUM_VALUES; ++i) {
2800 if (other.isChildMaskOff(i)) {
2803 .
setBRef(other.mNodes[i].getValue())
2806 this->makeChildNodeEmpty(i, args.
result());
2809 typename OtherNodeType::ChildNodeType* otherChild = other.mNodes[i].getChild();
2811 if (this->isChildMaskOff(i)) {
2818 mNodes[i].getChild()->combine2(value, *otherChild, valueIsActive, op);
2824 template<
typename ChildT, Index Log2Dim>
2825 template<
typename CombineOp,
typename OtherValueType>
2828 bool valueIsActive, CombineOp& op)
2832 for (
Index i = 0; i < NUM_VALUES; ++i) {
2839 this->makeChildNodeEmpty(i, args.
result());
2844 if (this->isChildMaskOff(i)) {
2846 this->setChildNode(i,
2847 new ChildNodeType(otherChild->origin(), mNodes[i].getValue()));
2851 mNodes[i].getChild()->combine2(*otherChild, value, valueIsActive, op);
2860 template<
typename ChildT, Index Log2Dim>
2861 template<
typename BBoxOp>
2868 if (op.template descent<LEVEL>()) {
2869 for (
ChildOnCIter i = this->cbeginChildOn(); i; ++i) i->visitActiveBBox(op);
2872 op.template operator()<LEVEL>(i->getNodeBoundingBox());
2878 template<
typename ChildT, Index Log2Dim>
2879 template<
typename VisitorOp>
2883 doVisit<InternalNode, VisitorOp, ChildAllIter>(*
this, op);
2887 template<
typename ChildT, Index Log2Dim>
2888 template<
typename VisitorOp>
2892 doVisit<const InternalNode, VisitorOp, ChildAllCIter>(*
this, op);
2896 template<
typename ChildT, Index Log2Dim>
2897 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
2901 typename NodeT::ValueType val;
2902 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
2903 if (op(iter))
continue;
2904 if (
typename ChildAllIterT::ChildNodeType* child = iter.probeChild(val)) {
2914 template<
typename ChildT, Index Log2Dim>
2915 template<
typename OtherNodeType,
typename VisitorOp>
2920 typename OtherNodeType::ChildAllIter>(*
this, other, op);
2924 template<
typename ChildT, Index Log2Dim>
2925 template<
typename OtherNodeType,
typename VisitorOp>
2930 typename OtherNodeType::ChildAllCIter>(*
this, other, op);
2934 template<
typename ChildT, Index Log2Dim>
2937 typename OtherNodeT,
2939 typename ChildAllIterT,
2940 typename OtherChildAllIterT>
2945 static_assert(OtherNodeT::NUM_VALUES == NodeT::NUM_VALUES,
2946 "visit2() requires nodes to have the same dimensions");
2947 static_assert(OtherNodeT::LEVEL == NodeT::LEVEL,
2948 "visit2() requires nodes to be at the same tree level");
2950 typename NodeT::ValueType val;
2951 typename OtherNodeT::ValueType otherVal;
2953 ChildAllIterT iter =
self.beginChildAll();
2954 OtherChildAllIterT otherIter = other.beginChildAll();
2956 for ( ; iter && otherIter; ++iter, ++otherIter)
2958 const size_t skipBranch =
static_cast<size_t>(op(iter, otherIter));
2960 typename ChildAllIterT::ChildNodeType* child =
2961 (skipBranch & 1U) ?
nullptr : iter.probeChild(val);
2962 typename OtherChildAllIterT::ChildNodeType* otherChild =
2963 (skipBranch & 2U) ?
nullptr : otherIter.probeChild(otherVal);
2965 if (child !=
nullptr && otherChild !=
nullptr) {
2966 child->visit2Node(*otherChild, op);
2967 }
else if (child !=
nullptr) {
2968 child->visit2(otherIter, op);
2969 }
else if (otherChild !=
nullptr) {
2970 otherChild->visit2(iter, op,
true);
2979 template<
typename ChildT, Index Log2Dim>
2980 template<
typename OtherChildAllIterType,
typename VisitorOp>
2983 VisitorOp& op,
bool otherIsLHS)
2985 doVisit2<InternalNode, VisitorOp, ChildAllIter, OtherChildAllIterType>(
2986 *
this, otherIter, op, otherIsLHS);
2990 template<
typename ChildT, Index Log2Dim>
2991 template<
typename OtherChildAllIterType,
typename VisitorOp>
2994 VisitorOp& op,
bool otherIsLHS)
const
2996 doVisit2<const InternalNode, VisitorOp, ChildAllCIter, OtherChildAllIterType>(
2997 *
this, otherIter, op, otherIsLHS);
3001 template<
typename ChildT, Index Log2Dim>
3002 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT,
typename OtherChildAllIterT>
3005 VisitorOp& op,
bool otherIsLHS)
3007 if (!otherIter)
return;
3009 const size_t skipBitMask = (otherIsLHS ? 2U : 1U);
3011 typename NodeT::ValueType val;
3012 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
3013 const size_t skipBranch =
static_cast<size_t>(
3014 otherIsLHS ? op(otherIter, iter) : op(iter, otherIter));
3016 typename ChildAllIterT::ChildNodeType* child =
3017 (skipBranch & skipBitMask) ?
nullptr : iter.probeChild(val);
3019 if (child !=
nullptr) child->visit2(otherIter, op, otherIsLHS);
3027 template<
typename ChildT, Index Log2Dim>
3031 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3032 iter->writeBuffers(os, toHalf);
3037 template<
typename ChildT, Index Log2Dim>
3041 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3042 iter->readBuffers(is, fromHalf);
3047 template<
typename ChildT, Index Log2Dim>
3050 const CoordBBox& clipBBox,
bool fromHalf)
3052 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3057 iter->readBuffers(is, clipBBox, fromHalf);
3061 ValueType background = zeroVal<ValueType>();
3063 background = *
static_cast<const ValueType*
>(bgPtr);
3065 this->
clip(clipBBox, background);
3072 template<
typename ChildT, Index Log2Dim>
3076 dims.push_back(Log2Dim);
3077 ChildNodeType::getNodeLog2Dims(dims);
3081 template<
typename ChildT, Index Log2Dim>
3085 assert(n<(1<<3*Log2Dim));
3086 xyz.
setX(n >> 2*Log2Dim);
3087 n &= ((1<<2*Log2Dim)-1);
3088 xyz.
setY(n >> Log2Dim);
3089 xyz.
setZ(n & ((1<<Log2Dim)-1));
3093 template<
typename ChildT, Index Log2Dim>
3097 return (((xyz[0] & (DIM-1u)) >> ChildNodeType::TOTAL) << 2*Log2Dim)
3098 + (((xyz[1] & (DIM-1u)) >> ChildNodeType::TOTAL) << Log2Dim)
3099 + ((xyz[2] & (DIM-1u)) >> ChildNodeType::TOTAL);
3103 template<
typename ChildT, Index Log2Dim>
3108 this->offsetToLocalCoord(n, local);
3109 local <<= ChildT::TOTAL;
3110 return local + this->origin();
3117 template<
typename ChildT, Index Log2Dim>
3118 template<
typename ArrayT>
3122 using T =
typename ArrayT::value_type;
3123 static_assert(std::is_pointer<T>::value,
"argument to getNodes() must be a pointer array");
3124 using ArrayChildT =
typename std::conditional<
3125 std::is_const<typename std::remove_pointer<T>::type>::value,
const ChildT, ChildT>::type;
3126 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3128 if (std::is_same<T, ArrayChildT*>::value) {
3129 array.push_back(
reinterpret_cast<T
>(mNodes[iter.pos()].getChild()));
3131 iter->getNodes(array);
3137 template<
typename ChildT, Index Log2Dim>
3138 template<
typename ArrayT>
3142 using T =
typename ArrayT::value_type;
3143 static_assert(std::is_pointer<T>::value,
"argument to getNodes() must be a pointer array");
3144 static_assert(std::is_const<
typename std::remove_pointer<T>::type>::value,
3145 "argument to getNodes() must be an array of const node pointers");
3146 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3148 if (std::is_same<T, const ChildT*>::value) {
3149 array.push_back(
reinterpret_cast<T
>(mNodes[iter.pos()].getChild()));
3151 iter->getNodes(array);
3161 template<
typename ChildT, Index Log2Dim>
3162 template<
typename ArrayT>
3166 using T =
typename ArrayT::value_type;
3167 static_assert(std::is_pointer<T>::value,
"argument to stealNodes() must be a pointer array");
3168 using ArrayChildT =
typename std::conditional<
3169 std::is_const<typename std::remove_pointer<T>::type>::value,
const ChildT, ChildT>::type;
3171 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3172 const Index n = iter.pos();
3173 if (std::is_same<T, ArrayChildT*>::value) {
3174 array.push_back(
reinterpret_cast<T
>(mNodes[n].getChild()));
3175 mValueMask.set(n, state);
3176 mNodes[n].setValue(value);
3178 iter->stealNodes(array, value, state);
3181 if (std::is_same<T, ArrayChildT*>::value) mChildMask.setOff();
3189 template<
typename ChildT, Index Log2Dim>
3195 for (
Index i = 0; i < NUM_VALUES; ++i) {
3196 if (this->isChildMaskOn(i)) {
3197 mNodes[i].getChild()->resetBackground(oldBackground, newBackground);
3198 }
else if (this->isValueMaskOff(i)) {
3200 mNodes[i].setValue(newBackground);
3208 template<
typename ChildT, Index Log2Dim>
3209 template<
typename OtherChildNodeType, Index OtherLog2Dim>
3214 if (Log2Dim != OtherLog2Dim || mChildMask != other->
mChildMask ||
3215 mValueMask != other->
mValueMask)
return false;
3216 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3217 if (!iter->hasSameTopology(other->
mNodes[iter.pos()].
getChild()))
return false;
3223 template<
typename ChildT, Index Log2Dim>
3228 if (this->isChildMaskOn(i)) {
3229 delete mNodes[i].getChild();
3231 mChildMask.setOn(i);
3232 mValueMask.setOff(i);
3234 mNodes[i].setChild(child);
3237 template<
typename ChildT, Index Log2Dim>
3242 assert(mChildMask.isOff(i));
3243 mChildMask.setOn(i);
3244 mValueMask.setOff(i);
3245 mNodes[i].setChild(child);
3249 template<
typename ChildT, Index Log2Dim>
3253 if (this->isChildMaskOff(i)) {
3254 mNodes[i].setValue(value);
3258 mChildMask.setOff(i);
3259 mNodes[i].setValue(value);
3264 template<
typename ChildT, Index Log2Dim>
3268 delete this->unsetChildNode(n, value);
3271 template<
typename ChildT, Index Log2Dim>
3275 assert(this->isChildMaskOn(n));
3276 return mNodes[n].getChild();
3280 template<
typename ChildT, Index Log2Dim>
3281 inline const ChildT*
3284 assert(this->isChildMaskOn(n));
3285 return mNodes[n].getChild();
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: openvdb/Types.h:429
CombineArgs & setBIsActive(bool b)
Set the active state of the B value.
Definition: openvdb/Types.h:497
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: openvdb/Types.h:481
CombineArgs & setAIsActive(bool b)
Set the active state of the A value.
Definition: openvdb/Types.h:495
const AValueType & result() const
Get the output value.
Definition: openvdb/Types.h:473
bool resultIsActive() const
Definition: openvdb/Types.h:492
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
Definition: openvdb/Types.h:483
Tag dispatch class that distinguishes constructors that deep copy.
Definition: openvdb/Types.h:544
Tag dispatch class that distinguishes constructors during file input.
Definition: openvdb/Types.h:548
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: openvdb/Types.h:542
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:249
const Coord & min() const
Definition: Coord.h:321
void translate(const Coord &t)
Translate this bounding box by (tx, ty, tz).
Definition: Coord.h:458
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:418
const Coord & max() const
Definition: Coord.h:322
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition: Coord.h:412
bool isInside(const Coord &xyz) const
Return true if point (x, y, z) is inside this bounding box.
Definition: Coord.h:400
void intersect(const CoordBBox &bbox)
Intersect this bounding box with the given bounding box.
Definition: Coord.h:444
static CoordBBox createCube(const Coord &min, ValueType dim)
Definition: Coord.h:313
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:26
Coord & setX(Int32 x)
Definition: Coord.h:80
Int32 y() const
Definition: Coord.h:132
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:92
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition: Coord.h:176
Coord & setY(Int32 y)
Definition: Coord.h:81
Int32 x() const
Definition: Coord.h:131
static Coord max()
Return the largest possible coordinate.
Definition: Coord.h:47
static bool lessThan(const Coord &a, const Coord &b)
Definition: Coord.h:209
Int32 z() const
Definition: Coord.h:133
Coord & setZ(Int32 z)
Definition: Coord.h:82
Definition: InternalNode.h:34
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1759
void visit(VisitorOp &)
Definition: InternalNode.h:2881
const NodeType * probeConstNode(const Coord &xyz) const
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Definition: InternalNode.h:328
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:2360
ChildOnCIter cbeginChildOn() const
Definition: InternalNode.h:220
void topologyUnion(const InternalNode< OtherChildNodeType, Log2Dim > &other)
Union this branch's set of active values with the other branch's active values. The value type of the...
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:2275
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:292
ChildOnCIter beginChildOn() const
Definition: InternalNode.h:223
ChildOnIter beginChildOn()
Definition: InternalNode.h:226
bool isChildMaskOff(Index n) const
Definition: InternalNode.h:763
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition: InternalNode.h:1568
void writeTopology(std::ostream &, bool toHalf=false) const
Definition: InternalNode.h:2190
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:2145
void setChildNode(Index i, ChildNodeType *child)
Definition: InternalNode.h:3239
bool isChildMaskOff() const
Definition: InternalNode.h:764
ValueOffCIter cbeginValueOff() const
Definition: InternalNode.h:232
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:1346
static Index getChildDim()
Definition: InternalNode.h:256
void visit2(IterT &otherIter, VisitorOp &, bool otherIsLHS=false) const
Index32 nonLeafCount() const
Definition: InternalNode.h:1035
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:818
bool isValueMaskOff() const
Definition: InternalNode.h:761
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition: InternalNode.h:3120
bool isValueMaskOn() const
Definition: InternalNode.h:759
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:1169
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition: InternalNode.h:2339
NodeMaskType mValueMask
Definition: InternalNode.h:818
InternalNode()
Default constructor.
Definition: InternalNode.h:72
bool isChildMaskOn(Index n) const
Definition: InternalNode.h:762
~InternalNode()
Definition: InternalNode.h:997
Index64 onLeafVoxelCount() const
Definition: InternalNode.h:1080
NodeMaskType getValueOffMask() const
Definition: InternalNode.h:767
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:1271
static void doVisit(NodeT &, VisitorOp &)
Definition: InternalNode.h:2899
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:1145
ValueOnCIter beginValueOn() const
Definition: InternalNode.h:234
Index64 offLeafVoxelCount() const
Definition: InternalNode.h:1092
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:3191
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:1405
const NodeMaskType & getValueMask() const
Definition: InternalNode.h:765
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
Definition: InternalNode.h:269
const LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc) const
bool isInactive() const
Return true if this node has no children and only contains inactive values.
Definition: InternalNode.h:323
static void doVisit2Node(NodeT &, OtherNodeT &, VisitorOp &)
Definition: InternalNode.h:2942
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: InternalNode.h:1937
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1800
void combine2(const InternalNode &other0, const OtherNodeType &other1, CombineOp &)
Definition: InternalNode.h:2747
friend class InternalNode
During topology-only construction, access is needed to protected/private members of other template in...
Definition: InternalNode.h:754
bool isValueMaskOff(Index n) const
Definition: InternalNode.h:760
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:1783
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Definition: InternalNode.h:1297
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:1621
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:2041
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
ValueOffCIter beginValueOff() const
Definition: InternalNode.h:236
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1714
void addLeaf(LeafNodeType *leaf)
Add the specified leaf to this node, possibly creating a child branch in the process....
Definition: InternalNode.h:1317
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:1991
ChildAllIter beginChildAll()
Definition: InternalNode.h:228
const NodeType * probeConstNodeAndCache(const Coord &xyz, AccessorT &) const
static Index getLevel()
Definition: InternalNode.h:249
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Definition: InternalNode.h:1578
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,...
const UnionType * getTable() const
Definition: InternalNode.h:774
bool probeValue(const Coord &xyz, ValueType &value) const
Definition: InternalNode.h:1634
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:1821
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:1903
ChildOffCIter cbeginChildOff() const
Definition: InternalNode.h:221
ChildOffIter beginChildOff()
Definition: InternalNode.h:227
Index64 onVoxelCount() const
Definition: InternalNode.h:1056
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:3095
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:1437
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:1662
void writeBuffers(std::ostream &, bool toHalf=false) const
Definition: InternalNode.h:3029
ValueOnCIter cbeginValueOn() const
Definition: InternalNode.h:230
LeafNodeType * touchLeafAndCache(const Coord &xyz, AccessorT &)
Same as touchLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
typename ChildNodeType::ValueType ValueType
Definition: InternalNode.h:38
Index32 leafCount() const
Definition: InternalNode.h:1010
void resetChildNode(Index i, ChildNodeType *child)
Definition: InternalNode.h:3225
const LeafNodeType * probeConstLeafAndCache(const Coord &xyz, AccessorT &acc) const
Index32 childCount() const
Definition: InternalNode.h:1048
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:1612
Index64 onTileCount() const
Definition: InternalNode.h:1103
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:1875
void visitActiveBBox(BBoxOp &) const
Calls the templated functor BBoxOp with bounding box information for all active tiles and leaf nodes ...
Definition: InternalNode.h:2863
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:3211
const NodeMaskType & getChildMask() const
Definition: InternalNode.h:766
Index64 offVoxelCount() const
Definition: InternalNode.h:1068
typename NodeMaskType::OffIterator MaskOffIterator
Definition: InternalNode.h:115
NodeType * probeNodeAndCache(const Coord &xyz, AccessorT &)
Same as probeNode() except, if necessary, update the accessor with pointers to the nodes along the pa...
bool isConstant(ValueType &firstValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
Definition: InternalNode.h:1506
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:1473
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:2097
static const Index NUM_VALUES
Definition: InternalNode.h:47
UnionType mNodes[NUM_VALUES]
Definition: InternalNode.h:814
void negate()
Change the sign of all the values represented in this node and its child nodes.
Definition: InternalNode.h:2295
void readTopology(std::istream &, bool fromHalf=false)
Definition: InternalNode.h:2215
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Definition: InternalNode.h:3105
ChildAllCIter beginChildAll() const
Definition: InternalNode.h:225
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Definition: InternalNode.h:1840
void setValuesOn()
Mark all values (both tiles and voxels) as active.
Definition: InternalNode.h:1863
void makeChildNodeEmpty(Index n, const ValueType &value)
Definition: InternalNode.h:3266
const LeafNodeType * probeLeaf(const Coord &xyz) const
typename ChildNodeType::BuildType BuildType
Definition: InternalNode.h:39
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:3164
ChildNodeType * getChildNode(Index n)
Returns a pointer to the child node at the linear offset n.
Definition: InternalNode.h:3273
typename NodeMaskType::OnIterator MaskOnIterator
Definition: InternalNode.h:114
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Definition: InternalNode.h:1647
static void doVisit2(NodeT &, OtherChildAllIterT &, VisitorOp &, bool otherIsLHS)
Definition: InternalNode.h:3004
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:1379
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:1127
bool isEmpty() const
Definition: InternalNode.h:295
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
static void getNodeLog2Dims(std::vector< Index > &dims)
Populated an stil::vector with the dimension of all the nodes in the branch starting with this node.
Definition: InternalNode.h:3074
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:1678
_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:3083
bool hasActiveTiles() const
Return true if this node or any of its child nodes have any active tiles.
Definition: InternalNode.h:1553
void combine(InternalNode &other, CombineOp &)
Definition: InternalNode.h:2660
const ValueType & getValue(const Coord &xyz) const
Definition: InternalNode.h:1589
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: InternalNode.h:267
void nodeCount(std::vector< Index32 > &vec) const
Definition: InternalNode.h:1022
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
Definition: InternalNode.h:1114
ChildNodeType * unsetChildNode(Index i, const ValueType &value)
Definition: InternalNode.h:3251
void readBuffers(std::istream &, bool fromHalf=false)
Definition: InternalNode.h:3039
typename NodeMaskType::DenseIterator MaskDenseIterator
Definition: InternalNode.h:116
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: InternalNode.h:1960
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:820
static Index dim()
Definition: InternalNode.h:246
NodeType * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists,...
void visit2Node(OtherNodeType &other, VisitorOp &)
Definition: InternalNode.h:2917
bool isValueMaskOn(Index n) const
Definition: InternalNode.h:758
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:2283
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
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...
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
Level getLevel()
Return the current logging level.
Definition: logging.h:138
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
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:444
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:127
Index32 Index
Definition: openvdb/Types.h:32
uint32_t Index32
Definition: openvdb/Types.h:30
@ OPENVDB_FILE_VERSION_NODE_MASK_COMPRESSION
Definition: version.h:194
@ OPENVDB_FILE_VERSION_INTERNALNODE_COMPRESSION
Definition: version.h:185
int32_t Int32
Definition: openvdb/Types.h:34
uint64_t Index64
Definition: openvdb/Types.h:31
@ MERGE_ACTIVE_STATES
Definition: openvdb/Types.h:367
@ MERGE_NODES
Definition: openvdb/Types.h:368
@ MERGE_ACTIVE_STATES_AND_NODES
Definition: openvdb/Types.h:369
ValueType combine(const ValueType &v0, const ValueType &v1, const ValueType &v2, const openvdb::Vec3d &w)
Combine different value types.
Definition: AttributeTransferUtil.h:140
Definition: openvdb/Exceptions.h:13
Definition: openvdb/Types.h:520
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
ChildT & getItem(Index pos) const
Definition: InternalNode.h:134
ChildIter(const MaskIterT &iter, NodeT *parent)
Definition: InternalNode.h:131
ChildIter()
Definition: InternalNode.h:130
void setItem(Index pos, const ChildT &c) const
Definition: InternalNode.h:141
Definition: InternalNode.h:120
Definition: InternalNode.h:120
Definition: InternalNode.h:880
DeepCopy(const OtherInternalNode *source, InternalNode *target)
Definition: InternalNode.h:881
InternalNode * t
Definition: InternalNode.h:895
const OtherInternalNode * s
Definition: InternalNode.h:894
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:885
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:924
TopologyCopy1(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:925
InternalNode * t
Definition: InternalNode.h:941
const OtherInternalNode * s
Definition: InternalNode.h:940
const ValueType & b
Definition: InternalNode.h:942
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:930
Definition: InternalNode.h:960
const ValueType & offV
Definition: InternalNode.h:978
TopologyCopy2(const OtherInternalNode *source, InternalNode *target, const ValueType &offValue, const ValueType &onValue)
Definition: InternalNode.h:961
InternalNode * t
Definition: InternalNode.h:977
const OtherInternalNode * s
Definition: InternalNode.h:976
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:966
Definition: InternalNode.h:2598
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
Definition: InternalNode.h:2598
Definition: InternalNode.h:2601
void operator()(W &tV, const W &sC, const W &sV, const W &tC) const
Definition: InternalNode.h:2601
Definition: InternalNode.h:2596
TopologyDifference(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:2604
typename NodeMaskType::Word W
Definition: InternalNode.h:2597
InternalNode * t
Definition: InternalNode.h:2640
const OtherInternalNode * s
Definition: InternalNode.h:2639
const ValueType & b
Definition: InternalNode.h:2641
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2618
Definition: InternalNode.h:2548
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
Definition: InternalNode.h:2548
Definition: InternalNode.h:2546
TopologyIntersection(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:2551
typename NodeMaskType::Word W
Definition: InternalNode.h:2547
InternalNode * t
Definition: InternalNode.h:2580
const OtherInternalNode * s
Definition: InternalNode.h:2579
const ValueType & b
Definition: InternalNode.h:2581
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2563
Definition: InternalNode.h:2502
void operator()(W &tV, const W &sV, const W &tC) const
Definition: InternalNode.h:2502
Definition: InternalNode.h:2500
typename NodeMaskType::Word W
Definition: InternalNode.h:2501
InternalNode * t
Definition: InternalNode.h:2532
const OtherInternalNode * s
Definition: InternalNode.h:2531
TopologyUnion(const OtherInternalNode *source, InternalNode *target)
Definition: InternalNode.h:2505
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2515
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
const ValueT & getItem(Index pos) const
Definition: InternalNode.h:155
ValueIter(const MaskIterT &iter, NodeT *parent)
Definition: InternalNode.h:152
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:2313
InternalNode * mNode
Definition: InternalNode.h:2334
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2321
VoxelizeActiveTiles(InternalNode &node)
Definition: InternalNode.h:2314
Definition: InternalNode.h:831
Base class for sparse iterators over internal and leaf nodes.
Definition: Iterator.h:115
Library and file format version numbers.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:101
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:153