35 #ifndef OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED 36 #define OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED 46 #include <tbb/parallel_for.h> 48 #include <type_traits> 59 template<
typename _ChildNodeType, Index Log2Dim>
65 using ValueType =
typename ChildNodeType::ValueType;
66 using BuildType =
typename ChildNodeType::BuildType;
72 TOTAL = Log2Dim + ChildNodeType::TOTAL,
74 NUM_VALUES = 1 << (3 * Log2Dim),
75 LEVEL = 1 + ChildNodeType::LEVEL;
77 NUM_VOXELS = uint64_t(1) << (3 * TOTAL);
81 template<
typename OtherValueType>
90 template<
typename OtherNodeType>
92 static const bool value =
109 InternalNode(
const Coord& origin,
const ValueType& fillValue,
bool active =
false);
111 #if OPENVDB_ABI_VERSION_NUMBER >= 3 123 template<
typename OtherChildNodeType>
129 template<
typename OtherChildNodeType>
136 template<
typename OtherChildNodeType>
138 const ValueType& offValue,
const ValueType& onValue,
TopologyCopy);
140 #if OPENVDB_ABI_VERSION_NUMBER < 5 159 template<
typename NodeT,
typename ChildT,
typename MaskIterT,
typename TagT>
161 MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>
165 MaskIterT,
ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>(iter, parent) {}
169 assert(this->parent().isChildMaskOn(pos));
170 return *(this->parent().getChildNode(pos));
174 void setItem(
Index pos,
const ChildT& c)
const { this->parent().resetChildNode(pos, &c); }
180 template<
typename NodeT,
typename ValueT,
typename MaskIterT,
typename TagT>
182 MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>
186 MaskIterT,
ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>(iter, parent) {}
188 const ValueT&
getItem(
Index pos)
const {
return this->parent().mNodes[pos].getValue(); }
191 void setItem(
Index pos,
const ValueT& v)
const { this->parent().mNodes[pos].setValue(v); }
194 template<
typename ModifyOp>
197 op(this->parent().mNodes[pos].getValue());
202 template<
typename NodeT,
typename ChildT,
typename ValueT,
typename TagT>
204 MaskDenseIterator, DenseIter<NodeT, ChildT, ValueT, TagT>, NodeT, ChildT, ValueT>
215 if (this->parent().isChildMaskOn(pos)) {
216 child = this->parent().getChildNode(pos);
220 value = this->parent().mNodes[pos].getValue();
227 this->parent().resetChildNode(pos, child);
233 this->parent().unsetChildNode(pos, value);
285 static void getNodeLog2Dims(std::vector<Index>& dims);
295 static void offsetToLocalCoord(
Index n,
Coord& xyz);
308 Index64 onLeafVoxelCount()
const;
309 Index64 offLeafVoxelCount()
const;
319 void evalActiveBoundingBox(
CoordBBox& bbox,
bool visitVoxels =
true)
const;
326 bool isEmpty()
const {
return mChildMask.isOff(); }
333 bool isConstant(ValueType& firstValue,
bool& state,
334 const ValueType& tolerance = zeroVal<ValueType>())
const;
350 bool isConstant(ValueType& minValue, ValueType& maxValue,
351 bool& state,
const ValueType& tolerance = zeroVal<ValueType>())
const;
354 bool isInactive()
const {
return this->isChildMaskOff() && this->isValueMaskOff(); }
357 bool isValueOn(
const Coord& xyz)
const;
362 bool hasActiveTiles()
const;
364 const ValueType& getValue(
const Coord& xyz)
const;
365 bool probeValue(
const Coord& xyz, ValueType& value)
const;
373 const ValueType& getFirstValue()
const;
376 const ValueType& getLastValue()
const;
379 void setActiveState(
const Coord& xyz,
bool on);
381 void setValueOnly(
const Coord& xyz,
const ValueType& value);
383 void setValueOn(
const Coord& xyz);
385 void setValueOn(
const Coord& xyz,
const ValueType& value);
387 void setValueOff(
const Coord& xyz);
389 void setValueOff(
const Coord& xyz,
const ValueType& value);
393 template<
typename ModifyOp>
394 void modifyValue(
const Coord& xyz,
const ModifyOp& op);
396 template<
typename ModifyOp>
397 void modifyValueAndActiveState(
const Coord& xyz,
const ModifyOp& op);
403 template<
typename AccessorT>
404 const ValueType& getValueAndCache(
const Coord& xyz, AccessorT&)
const;
410 template<
typename AccessorT>
411 bool isValueOnAndCache(
const Coord& xyz, AccessorT&)
const;
417 template<
typename AccessorT>
418 void setValueAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
424 template<
typename AccessorT>
425 void setValueOnlyAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
432 template<
typename ModifyOp,
typename AccessorT>
433 void modifyValueAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
439 template<
typename ModifyOp,
typename AccessorT>
440 void modifyValueAndActiveStateAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
446 template<
typename AccessorT>
447 void setValueOffAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
453 template<
typename AccessorT>
454 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&);
461 template<
typename AccessorT>
462 bool probeValueAndCache(
const Coord& xyz, ValueType& value, AccessorT&)
const;
470 template<
typename AccessorT>
471 Index getValueLevelAndCache(
const Coord& xyz, AccessorT&)
const;
479 void writeTopology(std::ostream&,
bool toHalf =
false)
const;
480 void readTopology(std::istream&,
bool fromHalf =
false);
481 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
482 void readBuffers(std::istream&,
bool fromHalf =
false);
483 void readBuffers(std::istream&,
const CoordBBox&,
bool fromHalf =
false);
501 void fill(
const CoordBBox& bbox,
const ValueType& value,
bool active =
true);
510 void denseFill(
const CoordBBox& bbox,
const ValueType& value,
bool active =
true);
515 void voxelizeActiveTiles(
bool threaded =
true);
524 template<
typename DenseT>
529 template<MergePolicy Policy>
530 void merge(
InternalNode& other,
const ValueType& background,
const ValueType& otherBackground);
534 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive);
548 template<
typename OtherChildNodeType>
564 template<
typename OtherChildNodeType>
566 const ValueType& background);
579 template<
typename OtherChildNodeType>
581 const ValueType& background);
583 template<
typename CombineOp>
585 template<
typename CombineOp>
586 void combine(
const ValueType& value,
bool valueIsActive, CombineOp&);
588 template<
typename CombineOp,
typename OtherNodeType >
589 void combine2(
const InternalNode& other0,
const OtherNodeType& other1, CombineOp&);
590 template<
typename CombineOp,
typename OtherNodeType >
591 void combine2(
const ValueType& value,
const OtherNodeType& other,
bool valIsActive, CombineOp&);
592 template<
typename CombineOp,
typename OtherValueType>
593 void combine2(
const InternalNode& other,
const OtherValueType&,
bool valIsActive, CombineOp&);
600 template<
typename BBoxOp>
void visitActiveBBox(BBoxOp&)
const;
602 template<
typename VisitorOp>
void visit(VisitorOp&);
603 template<
typename VisitorOp>
void visit(VisitorOp&)
const;
605 template<
typename OtherNodeType,
typename VisitorOp>
606 void visit2Node(OtherNodeType& other, VisitorOp&);
607 template<
typename OtherNodeType,
typename VisitorOp>
608 void visit2Node(OtherNodeType& other, VisitorOp&)
const;
609 template<
typename IterT,
typename VisitorOp>
610 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false);
611 template<
typename IterT,
typename VisitorOp>
612 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false)
const;
620 void prune(
const ValueType& tolerance = zeroVal<ValueType>());
624 void addLeaf(LeafNodeType* leaf);
628 template<
typename AccessorT>
629 void addLeafAndCache(LeafNodeType* leaf, AccessorT&);
639 template<
typename NodeT>
640 NodeT* stealNode(
const Coord& xyz,
const ValueType& value,
bool state);
644 void addTile(
Index level,
const Coord& xyz,
const ValueType& value,
bool state);
647 void addTile(
Index offset,
const ValueType& value,
bool state);
651 template<
typename AccessorT>
652 void addTileAndCache(
Index level,
const Coord& xyz,
const ValueType&,
bool state, AccessorT&);
655 template<
typename NodeType> NodeType* probeNode(
const Coord& xyz);
658 template<
typename NodeType>
const NodeType* probeConstNode(
const Coord& xyz)
const;
662 template<
typename NodeType,
typename AccessorT>
665 NodeType* probeNodeAndCache(
const Coord& xyz, AccessorT&);
666 template<
typename NodeType,
typename AccessorT>
667 const NodeType* probeConstNodeAndCache(
const Coord& xyz, AccessorT&)
const;
671 LeafNodeType* probeLeaf(
const Coord& xyz);
674 const LeafNodeType* probeConstLeaf(
const Coord& xyz)
const;
675 const LeafNodeType* probeLeaf(
const Coord& xyz)
const;
679 template<
typename AccessorT>
682 LeafNodeType* probeLeafAndCache(
const Coord& xyz, AccessorT& acc);
683 template<
typename AccessorT>
684 const LeafNodeType* probeConstLeafAndCache(
const Coord& xyz, AccessorT& acc)
const;
685 template<
typename AccessorT>
686 const LeafNodeType* probeLeafAndCache(
const Coord& xyz, AccessorT& acc)
const;
695 LeafNodeType* touchLeaf(
const Coord& xyz);
699 template<
typename AccessorT>
700 LeafNodeType* touchLeafAndCache(
const Coord& xyz, AccessorT&);
703 template<
typename ArrayT>
726 void getNodes(ArrayT& array);
727 template<
typename ArrayT>
728 void getNodes(ArrayT& array)
const;
754 template<
typename ArrayT>
755 void stealNodes(ArrayT& array,
const ValueType& value,
bool state);
759 void resetBackground(
const ValueType& oldBackground,
const ValueType& newBackground);
763 template<
typename OtherChildNodeType, Index OtherLog2Dim>
800 void setValueMask(
Index n,
bool on) { mValueMask.set(n, mChildMask.isOn(n) ? false : on); }
805 void makeChildNodeEmpty(
Index n,
const ValueType& value);
806 void setChildNode(
Index i, ChildNodeType* child);
807 void resetChildNode(
Index i, ChildNodeType* child);
808 ChildNodeType* unsetChildNode(
Index i,
const ValueType& value);
810 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
811 static inline void doVisit(NodeT&, VisitorOp&);
813 template<
typename NodeT,
typename OtherNodeT,
typename VisitorOp,
814 typename ChildAllIterT,
typename OtherChildAllIterT>
815 static inline void doVisit2Node(NodeT&, OtherNodeT&, VisitorOp&);
817 template<
typename NodeT,
typename VisitorOp,
818 typename ChildAllIterT,
typename OtherChildAllIterT>
819 static inline void doVisit2(NodeT&, OtherChildAllIterT&, VisitorOp&,
bool otherIsLHS);
825 ChildNodeType* getChildNode(
Index n);
826 const ChildNodeType* getChildNode(
Index n)
const;
831 struct VoxelizeActiveTiles;
832 template<
typename OtherInternalNode>
struct DeepCopy;
851 template<
typename ChildT1, Index Dim1,
typename NodeT2>
855 static const bool value =
false;
858 template<
typename ChildT1, Index Dim1,
typename ChildT2>
860 static const bool value = ChildT1::template SameConfiguration<ChildT2>::value;
868 template<
typename ChildT, Index Log2Dim>
872 for (
Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(background);
876 template<
typename ChildT, Index Log2Dim>
879 mOrigin(origin[0] & ~(DIM - 1),
880 origin[1] & ~(DIM - 1),
881 origin[2] & ~(DIM - 1))
888 #if OPENVDB_ABI_VERSION_NUMBER >= 3 891 template<
typename ChildT, Index Log2Dim>
895 : mOrigin(origin[0] & ~(DIM-1), origin[1] & ~(DIM-1), origin[2] & ~(DIM-1))
902 template<
typename ChildT, Index Log2Dim>
903 template<
typename OtherInternalNode>
907 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
911 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
912 if (s->mChildMask.isOff(i)) {
913 t->mNodes[i].setValue(
ValueType(s->mNodes[i].getValue()));
915 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild())));
919 const OtherInternalNode*
s;
923 template<
typename ChildT, Index Log2Dim>
926 mChildMask(other.mChildMask),
927 mValueMask(other.mValueMask),
928 mOrigin(other.mOrigin)
935 template<
typename ChildT, Index Log2Dim>
936 template<
typename OtherChildNodeType>
939 : mChildMask(other.mChildMask)
940 , mValueMask(other.mValueMask)
941 , mOrigin(other.mOrigin)
946 template<
typename ChildT, Index Log2Dim>
947 template<
typename OtherInternalNode>
951 const ValueType& background) : s(source), t(target), b(background) {
952 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
956 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
957 if (s->isChildMaskOn(i)) {
958 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild()),
961 t->mNodes[i].setValue(b);
965 const OtherInternalNode*
s;
970 template<
typename ChildT, Index Log2Dim>
971 template<
typename OtherChildNodeType>
975 mChildMask(other.mChildMask),
976 mValueMask(other.mValueMask),
977 mOrigin(other.mOrigin)
982 template<
typename ChildT, Index Log2Dim>
983 template<
typename OtherInternalNode>
988 : s(source), t(target), offV(offValue), onV(onValue) {
989 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
992 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
993 if (s->isChildMaskOn(i)) {
994 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild()),
997 t->mNodes[i].setValue(s->isValueMaskOn(i) ? onV : offV);
1001 const OtherInternalNode*
s;
1006 template<
typename ChildT, Index Log2Dim>
1007 template<
typename OtherChildNodeType>
1012 mChildMask(other.mChildMask),
1013 mValueMask(other.mValueMask),
1014 mOrigin(other.mOrigin)
1020 template<
typename ChildT, Index Log2Dim>
1024 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1025 delete mNodes[iter.pos()].getChild();
1033 template<
typename ChildT, Index Log2Dim>
1039 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1040 sum += iter->leafCount();
1046 template<
typename ChildT, Index Log2Dim>
1052 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1053 sum += iter->nonLeafCount();
1059 template<
typename ChildT, Index Log2Dim>
1063 Index64 sum = ChildT::NUM_VOXELS * mValueMask.countOn();
1064 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1065 sum += iter->onVoxelCount();
1071 template<
typename ChildT, Index Log2Dim>
1075 Index64 sum = ChildT::NUM_VOXELS * (NUM_VALUES-mValueMask.countOn()-mChildMask.countOn());
1076 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1077 sum += iter->offVoxelCount();
1083 template<
typename ChildT, Index Log2Dim>
1088 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1089 sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount();
1095 template<
typename ChildT, Index Log2Dim>
1100 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1101 sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount();
1106 template<
typename ChildT, Index Log2Dim>
1110 Index64 sum = mValueMask.countOn();
1111 for (
ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) {
1112 sum += iter->onTileCount();
1117 template<
typename ChildT, Index Log2Dim>
1122 + mValueMask.memUsage() +
sizeof(mOrigin);
1123 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1124 sum += iter->memUsage();
1130 template<
typename ChildT, Index Log2Dim>
1134 if (bbox.
isInside(this->getNodeBoundingBox()))
return;
1137 bbox.
expand(i.getCoord(), ChildT::DIM);
1140 i->evalActiveBoundingBox(bbox, visitVoxels);
1148 template<
typename ChildT, Index Log2Dim>
1154 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1155 const Index i = iter.pos();
1156 ChildT* child = mNodes[i].getChild();
1157 child->prune(tolerance);
1158 if (child->isConstant(value, state, tolerance)) {
1160 mChildMask.setOff(i);
1161 mValueMask.set(i, state);
1162 mNodes[i].setValue(value);
1171 template<
typename ChildT, Index Log2Dim>
1172 template<
typename NodeT>
1176 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1177 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1179 const Index n = this->coordToOffset(xyz);
1180 if (mChildMask.isOff(n))
return nullptr;
1181 ChildT* child = mNodes[n].getChild();
1182 if (std::is_same<NodeT, ChildT>::value) {
1183 mChildMask.setOff(n);
1184 mValueMask.set(n, state);
1185 mNodes[n].setValue(value);
1187 return (std::is_same<NodeT, ChildT>::value)
1188 ? reinterpret_cast<NodeT*>(child)
1189 : child->template stealNode<NodeT>(xyz, value, state);
1197 template<
typename ChildT, Index Log2Dim>
1198 template<
typename NodeT>
1202 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1203 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1205 const Index n = this->coordToOffset(xyz);
1206 if (mChildMask.isOff(n))
return nullptr;
1207 ChildT* child = mNodes[n].getChild();
1208 return (std::is_same<NodeT, ChildT>::value)
1209 ? reinterpret_cast<NodeT*>(child)
1210 : child->template probeNode<NodeT>(xyz);
1215 template<
typename ChildT, Index Log2Dim>
1216 template<
typename NodeT,
typename AccessorT>
1220 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
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();
1226 acc.insert(xyz, child);
1227 return (std::is_same<NodeT, ChildT>::value)
1228 ? reinterpret_cast<NodeT*>(child)
1229 : child->template probeNodeAndCache<NodeT>(xyz, acc);
1234 template<
typename ChildT, Index Log2Dim>
1235 template<
typename NodeT>
1239 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1240 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1242 const Index n = this->coordToOffset(xyz);
1243 if (mChildMask.isOff(n))
return nullptr;
1244 const ChildT* child = mNodes[n].getChild();
1245 return (std::is_same<NodeT, ChildT>::value)
1246 ? reinterpret_cast<const NodeT*>(child)
1247 : child->template probeConstNode<NodeT>(xyz);
1252 template<
typename ChildT, Index Log2Dim>
1253 template<
typename NodeT,
typename AccessorT>
1257 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
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();
1263 acc.insert(xyz, child);
1264 return (std::is_same<NodeT, ChildT>::value)
1265 ? reinterpret_cast<const NodeT*>(child)
1266 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
1274 template<
typename ChildT, Index Log2Dim>
1275 inline typename ChildT::LeafNodeType*
1278 return this->
template probeNode<LeafNodeType>(xyz);
1282 template<
typename ChildT, Index Log2Dim>
1283 template<
typename AccessorT>
1284 inline typename ChildT::LeafNodeType*
1287 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
1291 template<
typename ChildT, Index Log2Dim>
1292 template<
typename AccessorT>
1293 inline const typename ChildT::LeafNodeType*
1296 return this->probeConstLeafAndCache(xyz, acc);
1300 template<
typename ChildT, Index Log2Dim>
1301 inline const typename ChildT::LeafNodeType*
1304 return this->
template probeConstNode<LeafNodeType>(xyz);
1308 template<
typename ChildT, Index Log2Dim>
1309 template<
typename AccessorT>
1310 inline const typename ChildT::LeafNodeType*
1313 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
1320 template<
typename ChildT, Index Log2Dim>
1324 assert(leaf !=
nullptr);
1325 const Coord& xyz = leaf->origin();
1326 const Index n = this->coordToOffset(xyz);
1327 ChildT* child =
nullptr;
1328 if (mChildMask.isOff(n)) {
1329 if (ChildT::LEVEL>0) {
1330 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1332 child = reinterpret_cast<ChildT*>(leaf);
1334 this->setChildNode(n, child);
1336 if (ChildT::LEVEL>0) {
1337 child = mNodes[n].getChild();
1339 delete mNodes[n].getChild();
1340 child = reinterpret_cast<ChildT*>(leaf);
1341 mNodes[n].setChild(child);
1344 child->addLeaf(leaf);
1348 template<
typename ChildT, Index Log2Dim>
1349 template<
typename AccessorT>
1353 assert(leaf !=
nullptr);
1354 const Coord& xyz = leaf->origin();
1355 const Index n = this->coordToOffset(xyz);
1356 ChildT* child =
nullptr;
1357 if (mChildMask.isOff(n)) {
1358 if (ChildT::LEVEL>0) {
1359 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1360 acc.insert(xyz, child);
1362 child = reinterpret_cast<ChildT*>(leaf);
1364 this->setChildNode(n, child);
1366 if (ChildT::LEVEL>0) {
1367 child = mNodes[n].getChild();
1368 acc.insert(xyz, child);
1370 delete mNodes[n].getChild();
1371 child = reinterpret_cast<ChildT*>(leaf);
1372 mNodes[n].setChild(child);
1375 child->addLeafAndCache(leaf, acc);
1382 template<
typename ChildT, Index Log2Dim>
1386 assert(n < NUM_VALUES);
1387 this->makeChildNodeEmpty(n, value);
1388 mValueMask.set(n, state);
1392 template<
typename ChildT, Index Log2Dim>
1397 if (LEVEL >= level) {
1398 const Index n = this->coordToOffset(xyz);
1399 if (mChildMask.isOff(n)) {
1400 if (LEVEL > level) {
1401 ChildT* child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1402 this->setChildNode(n, child);
1403 child->addTile(level, xyz, value, state);
1405 mValueMask.set(n, state);
1406 mNodes[n].setValue(value);
1409 ChildT* child = mNodes[n].getChild();
1410 if (LEVEL > level) {
1411 child->addTile(level, xyz, value, state);
1414 mChildMask.setOff(n);
1415 mValueMask.set(n, state);
1416 mNodes[n].setValue(value);
1423 template<
typename ChildT, Index Log2Dim>
1424 template<
typename AccessorT>
1427 const ValueType& value,
bool state, AccessorT& acc)
1429 if (LEVEL >= level) {
1430 const Index n = this->coordToOffset(xyz);
1431 if (mChildMask.isOff(n)) {
1432 if (LEVEL > level) {
1433 ChildT* child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1434 this->setChildNode(n, child);
1435 acc.insert(xyz, child);
1436 child->addTileAndCache(level, xyz, value, state, acc);
1438 mValueMask.set(n, state);
1439 mNodes[n].setValue(value);
1442 ChildT* child = mNodes[n].getChild();
1443 if (LEVEL > level) {
1444 acc.insert(xyz, child);
1445 child->addTileAndCache(level, xyz, value, state, acc);
1448 mChildMask.setOff(n);
1449 mValueMask.set(n, state);
1450 mNodes[n].setValue(value);
1460 template<
typename ChildT, Index Log2Dim>
1461 inline typename ChildT::LeafNodeType*
1464 const Index n = this->coordToOffset(xyz);
1465 ChildT* child =
nullptr;
1466 if (mChildMask.isOff(n)) {
1467 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1468 this->setChildNode(n, child);
1470 child = mNodes[n].getChild();
1472 return child->touchLeaf(xyz);
1476 template<
typename ChildT, Index Log2Dim>
1477 template<
typename AccessorT>
1478 inline typename ChildT::LeafNodeType*
1481 const Index n = this->coordToOffset(xyz);
1482 if (mChildMask.isOff(n)) {
1483 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), mValueMask.isOn(n)));
1485 acc.insert(xyz, mNodes[n].getChild());
1486 return mNodes[n].getChild()->touchLeafAndCache(xyz, acc);
1493 template<
typename ChildT, Index Log2Dim>
1498 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1500 firstValue = mNodes[0].getValue();
1501 for (
Index i = 1; i < NUM_VALUES; ++i) {
1513 template<
typename ChildT, Index Log2Dim>
1521 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1522 minValue = maxValue = mNodes[0].getValue();
1523 for (
Index i = 1; i < NUM_VALUES; ++i) {
1524 const ValueType& v = mNodes[i].getValue();
1526 if ((maxValue - v) > tolerance)
return false;
1528 }
else if (v > maxValue) {
1529 if ((v - minValue) > tolerance)
return false;
1540 template<
typename ChildT, Index Log2Dim>
1545 const bool anyActiveTiles = !mValueMask.isOff();
1546 if (LEVEL==1 || anyActiveTiles)
return anyActiveTiles;
1547 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1548 if (iter->hasActiveTiles())
return true;
1555 template<
typename ChildT, Index Log2Dim>
1559 const Index n = this->coordToOffset(xyz);
1560 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1561 return mNodes[n].getChild()->isValueOn(xyz);
1564 template<
typename ChildT, Index Log2Dim>
1565 template<
typename AccessorT>
1569 const Index n = this->coordToOffset(xyz);
1570 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1571 acc.insert(xyz, mNodes[n].getChild());
1572 return mNodes[n].getChild()->isValueOnAndCache(xyz, acc);
1576 template<
typename ChildT, Index Log2Dim>
1577 inline const typename ChildT::ValueType&
1580 const Index n = this->coordToOffset(xyz);
1581 return this->isChildMaskOff(n) ? mNodes[n].getValue()
1582 : mNodes[n].getChild()->getValue(xyz);
1585 template<
typename ChildT, Index Log2Dim>
1586 template<
typename AccessorT>
1587 inline const typename ChildT::ValueType&
1590 const Index n = this->coordToOffset(xyz);
1591 if (this->isChildMaskOn(n)) {
1592 acc.insert(xyz, mNodes[n].getChild());
1593 return mNodes[n].getChild()->getValueAndCache(xyz, acc);
1595 return mNodes[n].getValue();
1599 template<
typename ChildT, Index Log2Dim>
1603 const Index n = this->coordToOffset(xyz);
1604 return this->isChildMaskOff(n) ? LEVEL : mNodes[n].getChild()->getValueLevel(xyz);
1607 template<
typename ChildT, Index Log2Dim>
1608 template<
typename AccessorT>
1612 const Index n = this->coordToOffset(xyz);
1613 if (this->isChildMaskOn(n)) {
1614 acc.insert(xyz, mNodes[n].getChild());
1615 return mNodes[n].getChild()->getValueLevelAndCache(xyz, acc);
1621 template<
typename ChildT, Index Log2Dim>
1625 const Index n = this->coordToOffset(xyz);
1626 if (this->isChildMaskOff(n)) {
1627 value = mNodes[n].getValue();
1628 return this->isValueMaskOn(n);
1630 return mNodes[n].getChild()->probeValue(xyz, value);
1633 template<
typename ChildT, Index Log2Dim>
1634 template<
typename AccessorT>
1639 const Index n = this->coordToOffset(xyz);
1640 if (this->isChildMaskOn(n)) {
1641 acc.insert(xyz, mNodes[n].getChild());
1642 return mNodes[n].getChild()->probeValueAndCache(xyz, value, acc);
1644 value = mNodes[n].getValue();
1645 return this->isValueMaskOn(n);
1649 template<
typename ChildT, Index Log2Dim>
1653 const Index n = this->coordToOffset(xyz);
1654 bool hasChild = this->isChildMaskOn(n);
1655 if (!hasChild && this->isValueMaskOn(n)) {
1659 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
true));
1661 if (hasChild) mNodes[n].getChild()->setValueOff(xyz);
1665 template<
typename ChildT, Index Log2Dim>
1669 const Index n = this->coordToOffset(xyz);
1670 bool hasChild = this->isChildMaskOn(n);
1671 if (!hasChild && !this->isValueMaskOn(n)) {
1675 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
false));
1677 if (hasChild) mNodes[n].getChild()->setValueOn(xyz);
1681 template<
typename ChildT, Index Log2Dim>
1686 bool hasChild = this->isChildMaskOn(n);
1688 const bool active = this->isValueMaskOn(n);
1694 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1697 if (hasChild) mNodes[n].getChild()->setValueOff(xyz, value);
1700 template<
typename ChildT, Index Log2Dim>
1701 template<
typename AccessorT>
1707 bool hasChild = this->isChildMaskOn(n);
1709 const bool active = this->isValueMaskOn(n);
1715 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1719 ChildT* child = mNodes[n].getChild();
1720 acc.insert(xyz, child);
1721 child->setValueOffAndCache(xyz, value, acc);
1726 template<
typename ChildT, Index Log2Dim>
1730 const Index n = this->coordToOffset(xyz);
1731 bool hasChild = this->isChildMaskOn(n);
1733 const bool active = this->isValueMaskOn(n);
1739 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1742 if (hasChild) mNodes[n].getChild()->setValueOn(xyz, value);
1745 template<
typename ChildT, Index Log2Dim>
1746 template<
typename AccessorT>
1751 const Index n = this->coordToOffset(xyz);
1752 bool hasChild = this->isChildMaskOn(n);
1754 const bool active = this->isValueMaskOn(n);
1760 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1764 acc.insert(xyz, mNodes[n].getChild());
1765 mNodes[n].getChild()->setValueAndCache(xyz, value, acc);
1770 template<
typename ChildT, Index Log2Dim>
1774 const Index n = this->coordToOffset(xyz);
1775 bool hasChild = this->isChildMaskOn(n);
1779 const bool active = this->isValueMaskOn(n);
1781 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1783 if (hasChild) mNodes[n].getChild()->setValueOnly(xyz, value);
1786 template<
typename ChildT, Index Log2Dim>
1787 template<
typename AccessorT>
1792 const Index n = this->coordToOffset(xyz);
1793 bool hasChild = this->isChildMaskOn(n);
1797 const bool active = this->isValueMaskOn(n);
1799 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1802 acc.insert(xyz, mNodes[n].getChild());
1803 mNodes[n].getChild()->setValueOnlyAndCache(xyz, value, acc);
1808 template<
typename ChildT, Index Log2Dim>
1812 const Index n = this->coordToOffset(xyz);
1813 bool hasChild = this->isChildMaskOn(n);
1815 if (on != this->isValueMaskOn(n)) {
1820 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1823 if (hasChild) mNodes[n].getChild()->setActiveState(xyz, on);
1826 template<
typename ChildT, Index Log2Dim>
1827 template<
typename AccessorT>
1831 const Index n = this->coordToOffset(xyz);
1832 bool hasChild = this->isChildMaskOn(n);
1834 if (on != this->isValueMaskOn(n)) {
1839 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1843 ChildT* child = mNodes[n].getChild();
1844 acc.insert(xyz, child);
1845 child->setActiveStateAndCache(xyz, on, acc);
1850 template<
typename ChildT, Index Log2Dim>
1854 mValueMask = !mChildMask;
1855 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1856 mNodes[iter.pos()].getChild()->setValuesOn();
1861 template<
typename ChildT, Index Log2Dim>
1862 template<
typename ModifyOp>
1867 bool hasChild = this->isChildMaskOn(n);
1871 const bool active = this->isValueMaskOn(n);
1872 bool createChild = !active;
1876 const ValueType& tileVal = mNodes[n].getValue();
1883 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1886 if (hasChild) mNodes[n].getChild()->modifyValue(xyz, op);
1889 template<
typename ChildT, Index Log2Dim>
1890 template<
typename ModifyOp,
typename AccessorT>
1896 bool hasChild = this->isChildMaskOn(n);
1900 const bool active = this->isValueMaskOn(n);
1901 bool createChild = !active;
1905 const ValueType& tileVal = mNodes[n].getValue();
1912 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1917 acc.insert(xyz, child);
1918 child->modifyValueAndCache(xyz, op, acc);
1923 template<
typename ChildT, Index Log2Dim>
1924 template<
typename ModifyOp>
1929 bool hasChild = this->isChildMaskOn(n);
1931 const bool tileState = this->isValueMaskOn(n);
1932 const ValueType& tileVal = mNodes[n].getValue();
1933 bool modifiedState = !tileState;
1935 op(modifiedVal, modifiedState);
1940 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
1943 if (hasChild) mNodes[n].getChild()->modifyValueAndActiveState(xyz, op);
1946 template<
typename ChildT, Index Log2Dim>
1947 template<
typename ModifyOp,
typename AccessorT>
1950 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
1953 bool hasChild = this->isChildMaskOn(n);
1955 const bool tileState = this->isValueMaskOn(n);
1956 const ValueType& tileVal = mNodes[n].getValue();
1957 bool modifiedState = !tileState;
1959 op(modifiedVal, modifiedState);
1964 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
1969 acc.insert(xyz, child);
1970 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
1978 template<
typename ChildT, Index Log2Dim>
1982 CoordBBox nodeBBox = this->getNodeBoundingBox();
1985 this->fill(nodeBBox, background,
false);
1986 }
else if (clipBBox.
isInside(nodeBBox)) {
1995 for (
Index pos = 0; pos < NUM_VALUES; ++pos) {
1996 const Coord xyz = this->offsetToGlobalCoord(pos);
2001 this->makeChildNodeEmpty(pos, background);
2002 mValueMask.setOff(pos);
2003 }
else if (!clipBBox.
isInside(tileBBox)) {
2006 if (this->isChildMaskOn(pos)) {
2007 mNodes[pos].getChild()->clip(clipBBox, background);
2011 tileBBox.intersect(clipBBox);
2012 const ValueType val = mNodes[pos].getValue();
2013 const bool on = this->isValueMaskOn(pos);
2014 mNodes[pos].setValue(background);
2015 mValueMask.setOff(pos);
2016 this->fill(tileBBox, val, on);
2028 template<
typename ChildT, Index Log2Dim>
2032 auto clippedBBox = this->getNodeBoundingBox();
2033 clippedBBox.intersect(bbox);
2034 if (!clippedBBox)
return;
2038 Coord xyz, tileMin, tileMax;
2039 for (
int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.
x() + 1) {
2041 for (
int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.
y() + 1) {
2043 for (
int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.
z() + 1) {
2047 const Index n = this->coordToOffset(xyz);
2048 tileMin = this->offsetToGlobalCoord(n);
2049 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2055 ChildT* child =
nullptr;
2056 if (this->isChildMaskOff(n)) {
2059 child =
new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)};
2060 this->setChildNode(n, child);
2062 child = mNodes[n].getChild();
2068 child->fill(
CoordBBox(xyz, tmp), value, active);
2075 this->makeChildNodeEmpty(n, value);
2076 mValueMask.set(n, active);
2084 template<
typename ChildT, Index Log2Dim>
2088 auto clippedBBox = this->getNodeBoundingBox();
2089 clippedBBox.intersect(bbox);
2090 if (!clippedBBox)
return;
2094 Coord xyz, tileMin, tileMax;
2095 for (
int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.
x() + 1) {
2097 for (
int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.
y() + 1) {
2099 for (
int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.
z() + 1) {
2103 const auto n = this->coordToOffset(xyz);
2106 ChildT* child =
nullptr;
2107 if (this->isChildMaskOn(n)) {
2108 child = mNodes[n].getChild();
2112 child =
new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)};
2113 this->setChildNode(n, child);
2117 tileMin = this->offsetToGlobalCoord(n);
2118 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2121 child->denseFill(
CoordBBox{xyz, clippedBBox.
max()}, value, active);
2131 template<
typename ChildT, Index Log2Dim>
2132 template<
typename DenseT>
2136 using DenseValueType =
typename DenseT::ValueType;
2138 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2139 const Coord&
min = dense.bbox().min();
2140 for (
Coord xyz = bbox.
min(),
max; xyz[0] <= bbox.
max()[0]; xyz[0] =
max[0] + 1) {
2141 for (xyz[1] = bbox.
min()[1]; xyz[1] <= bbox.
max()[1]; xyz[1] =
max[1] + 1) {
2142 for (xyz[2] = bbox.
min()[2]; xyz[2] <= bbox.
max()[2]; xyz[2] =
max[2] + 1) {
2143 const Index n = this->coordToOffset(xyz);
2145 max = this->offsetToGlobalCoord(n).offsetBy(ChildT::DIM-1);
2150 if (this->isChildMaskOn(n)) {
2151 mNodes[n].getChild()->copyToDense(sub, dense);
2153 const ValueType value = mNodes[n].getValue();
2155 DenseValueType* a0 = dense.data() + zStride*sub.
min()[2];
2156 for (
Int32 x=sub.
min()[0], ex=sub.
max()[0]+1; x<ex; ++x) {
2157 DenseValueType* a1 = a0 + x*xStride;
2158 for (
Int32 y=sub.
min()[1], ey=sub.
max()[1]+1; y<ey; ++y) {
2159 DenseValueType* a2 = a1 + y*yStride;
2161 z < ez; ++z, a2 += zStride)
2163 *a2 = DenseValueType(value);
2177 template<
typename ChildT, Index Log2Dim>
2181 mChildMask.save(os);
2182 mValueMask.save(os);
2186 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[NUM_VALUES]);
2188 const ValueType zero = zeroVal<ValueType>();
2189 for (
Index i = 0; i < NUM_VALUES; ++i) {
2190 values[i] = (mChildMask.isOff(i) ? mNodes[i].getValue() : zero);
2196 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2197 iter->writeTopology(os, toHalf);
2202 template<
typename ChildT, Index Log2Dim>
2206 #if OPENVDB_ABI_VERSION_NUMBER >= 3 2211 mChildMask.load(is);
2212 mValueMask.load(is);
2215 for (
Index i = 0; i < NUM_VALUES; ++i) {
2216 if (this->isChildMaskOn(i)) {
2218 #if OPENVDB_ABI_VERSION_NUMBER <= 2 2219 new ChildNodeType(offsetToGlobalCoord(i), zeroVal<ValueType>());
2223 mNodes[i].setChild(child);
2224 child->readTopology(is);
2227 is.read(reinterpret_cast<char*>(&value),
sizeof(
ValueType));
2228 mNodes[i].setValue(value);
2232 const bool oldVersion =
2234 const Index numValues = (oldVersion ? mChildMask.countOff() : NUM_VALUES);
2238 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[numValues]);
2245 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2246 mNodes[iter.pos()].setValue(values[n++]);
2248 assert(n == numValues);
2250 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2251 mNodes[iter.pos()].setValue(values[iter.pos()]);
2256 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2257 #if OPENVDB_ABI_VERSION_NUMBER <= 2 2262 mNodes[iter.pos()].setChild(child);
2263 child->readTopology(is, fromHalf);
2272 template<
typename ChildT, Index Log2Dim>
2273 inline const typename ChildT::ValueType&
2276 return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].getValue());
2280 template<
typename ChildT, Index Log2Dim>
2281 inline const typename ChildT::ValueType&
2284 const Index n = NUM_VALUES - 1;
2285 return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].getValue());
2292 template<
typename ChildT, Index Log2Dim>
2296 for (
Index i = 0; i < NUM_VALUES; ++i) {
2297 if (this->isChildMaskOn(i)) {
2298 mNodes[i].getChild()->negate();
2310 template<
typename ChildT, Index Log2Dim>
2315 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2322 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2323 if (mNode->mChildMask.isOn(i)) {
2324 mNode->mNodes[i].getChild()->voxelizeActiveTiles(
true);
2325 }
else if (mNode->mValueMask.isOn(i)) {
2326 const Coord &ijk = mNode->offsetToGlobalCoord(i);
2328 child->voxelizeActiveTiles(
true);
2329 mNode->mNodes[i].setChild(child);
2336 template<
typename ChildT, Index Log2Dim>
2343 for (
ValueOnIter iter = this->beginValueOn(); iter; ++iter) {
2344 this->setChildNode(iter.pos(),
2347 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter)
2348 iter->voxelizeActiveTiles(
false);
2356 template<
typename ChildT, Index Log2Dim>
2357 template<MergePolicy Policy>
2370 const Index n = iter.pos();
2371 if (mChildMask.isOn(n)) {
2373 mNodes[n].getChild()->template merge<MERGE_ACTIVE_STATES>(*iter,
2374 background, otherBackground);
2375 }
else if (mValueMask.isOff(n)) {
2382 child->resetBackground(otherBackground, background);
2383 this->setChildNode(n, child);
2389 const Index n = iter.pos();
2390 if (mValueMask.isOff(n)) {
2392 this->makeChildNodeEmpty(n, iter.getValue());
2393 mValueMask.setOn(n);
2402 const Index n = iter.pos();
2403 if (mChildMask.isOn(n)) {
2405 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2413 child->resetBackground(otherBackground, background);
2414 this->setChildNode(n, child);
2424 const Index n = iter.pos();
2425 if (mChildMask.isOn(n)) {
2427 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2434 child->resetBackground(otherBackground, background);
2435 if (mValueMask.isOn(n)) {
2437 child->template merge<Policy>(mNodes[n].getValue(),
true);
2438 mValueMask.setOff(n);
2440 mChildMask.setOn(n);
2441 mNodes[n].setChild(child);
2447 const Index n = iter.pos();
2448 if (mChildMask.isOn(n)) {
2450 mNodes[n].getChild()->template merge<Policy>(iter.getValue(),
true);
2451 }
else if (mValueMask.isOff(n)) {
2453 mNodes[n].setValue(iter.getValue());
2454 mValueMask.setOn(n);
2465 template<
typename ChildT, Index Log2Dim>
2466 template<MergePolicy Policy>
2475 if (!tileActive)
return;
2478 for (
ValueOffIter iter = this->beginValueOff(); iter; ++iter) {
2479 const Index n = iter.pos();
2480 if (mChildMask.isOn(n)) {
2482 mNodes[n].getChild()->template merge<Policy>(tileValue,
true);
2485 iter.setValue(tileValue);
2486 mValueMask.setOn(n);
2496 template<
typename ChildT, Index Log2Dim>
2497 template<
typename OtherInternalNode>
2502 { tV = (tV | sV) & ~tC; }
2506 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2509 t->mChildMask |= s->mChildMask;
2511 t->mValueMask.foreach(s->mValueMask, t->mChildMask, op);
2512 assert((t->mValueMask & t->mChildMask).isOff());
2515 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2516 if (s->mChildMask.isOn(i)) {
2517 const typename OtherInternalNode::ChildNodeType& other = *(s->mNodes[i].getChild());
2518 if (t->mChildMask.isOn(i)) {
2519 t->mNodes[i].getChild()->topologyUnion(other);
2521 ChildT* child =
new ChildT(other, t->mNodes[i].getValue(),
TopologyCopy());
2522 if (t->mValueMask.isOn(i)) child->setValuesOn();
2523 t->mNodes[i].setChild(child);
2525 }
else if (s->mValueMask.isOn(i) && t->mChildMask.isOn(i)) {
2526 t->mNodes[i].getChild()->setValuesOn();
2530 const OtherInternalNode*
s;
2534 template<
typename ChildT, Index Log2Dim>
2535 template<
typename OtherChildT>
2542 template<
typename ChildT, Index Log2Dim>
2543 template<
typename OtherInternalNode>
2544 struct InternalNode<ChildT, Log2Dim>::TopologyIntersection
2548 { tC = (tC & (sC | sV)) | (tV & sC); }
2551 const ValueType& background) : s(source), t(target), b(background) {
2553 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
2557 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op);
2559 t->mValueMask &= s->mValueMask;
2560 assert((t->mValueMask & t->mChildMask).isOff());
2563 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2564 if (t->mChildMask.isOn(i)) {
2565 ChildT* child = t->mNodes[i].getChild();
2566 if (s->mChildMask.isOn(i)) {
2567 child->topologyIntersection(*(s->mNodes[i].getChild()), b);
2568 }
else if (s->mValueMask.isOff(i)) {
2570 t->mNodes[i].setValue(b);
2572 }
else if (t->mValueMask.isOn(i) && s->mChildMask.isOn(i)) {
2573 t->mNodes[i].setChild(
new ChildT(*(s->mNodes[i].getChild()),
2578 const OtherInternalNode*
s;
2583 template<
typename ChildT, Index Log2Dim>
2584 template<
typename OtherChildT>
2592 template<
typename ChildT, Index Log2Dim>
2593 template<
typename OtherInternalNode>
2594 struct InternalNode<ChildT, Log2Dim>::TopologyDifference
2598 { tC = (tC & (sC | ~sV)) | (tV & sC); }
2601 { tV &= ~((tC & sV) | (sC | sV)); }
2604 const ValueType& background) : s(source), t(target), b(background) {
2606 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
2611 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op1);
2614 t->mValueMask.foreach(t->mChildMask, s->mValueMask, oldChildMask, op2);
2615 assert((t->mValueMask & t->mChildMask).isOff());
2618 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2619 if (t->mChildMask.isOn(i)) {
2620 ChildT* child = t->mNodes[i].getChild();
2621 if (s->mChildMask.isOn(i)) {
2622 child->topologyDifference(*(s->mNodes[i].getChild()), b);
2623 }
else if (s->mValueMask.isOn(i)) {
2625 t->mNodes[i].setValue(b);
2627 }
else if (t->mValueMask.isOn(i)) {
2628 if (s->mChildMask.isOn(i)) {
2629 const typename OtherInternalNode::ChildNodeType& other =
2630 *(s->mNodes[i].getChild());
2631 ChildT* child =
new ChildT(other.origin(), t->mNodes[i].getValue(),
true);
2632 child->topologyDifference(other, b);
2633 t->mNodes[i].setChild(child);
2638 const OtherInternalNode*
s;
2643 template<
typename ChildT, Index Log2Dim>
2644 template<
typename OtherChildT>
2656 template<
typename ChildT, Index Log2Dim>
2657 template<
typename CombineOp>
2661 const ValueType zero = zeroVal<ValueType>();
2665 for (
Index i = 0; i < NUM_VALUES; ++i) {
2669 op(args.
setARef(mNodes[i].getValue())
2670 .setAIsActive(isValueMaskOn(i))
2673 mNodes[i].setValue(args.
result());
2682 }
else if (this->isChildMaskOff(i) && other.
isChildMaskOn(i)) {
2691 child->combine(mNodes[i].getValue(), isValueMaskOn(i), swappedOp);
2696 this->setChildNode(i, child);
2702 *child = mNodes[i].getChild(),
2706 if (child && otherChild) {
2707 child->combine(*otherChild, op);
2714 template<
typename ChildT, Index Log2Dim>
2715 template<
typename CombineOp>
2721 for (
Index i = 0; i < NUM_VALUES; ++i) {
2722 if (this->isChildMaskOff(i)) {
2724 op(args.
setARef(mNodes[i].getValue())
2725 .setAIsActive(isValueMaskOn(i))
2727 .setBIsActive(valueIsActive));
2728 mNodes[i].setValue(args.
result());
2734 if (child) child->combine(value, valueIsActive, op);
2743 template<
typename ChildT, Index Log2Dim>
2744 template<
typename CombineOp,
typename OtherNodeType>
2751 for (
Index i = 0; i < NUM_VALUES; ++i) {
2755 .setBRef(other1.mNodes[i].getValue())
2756 .setBIsActive(other1.isValueMaskOn(i)));
2758 this->makeChildNodeEmpty(i, args.
result());
2761 if (this->isChildMaskOff(i)) {
2765 : other1.mNodes[i].getChild()->origin();
2766 this->setChildNode(i,
new ChildNodeType(childOrigin, mNodes[i].getValue()));
2774 }
else if (other1.isChildMaskOff(i)) {
2778 other1.mNodes[i].getValue(), other1.isValueMaskOn(i), op);
2783 *other1.mNodes[i].getChild(), op);
2790 template<
typename ChildT, Index Log2Dim>
2791 template<
typename CombineOp,
typename OtherNodeType>
2794 bool valueIsActive, CombineOp& op)
2798 for (
Index i = 0; i < NUM_VALUES; ++i) {
2799 if (other.isChildMaskOff(i)) {
2801 .setAIsActive(valueIsActive)
2802 .setBRef(other.mNodes[i].getValue())
2803 .setBIsActive(other.isValueMaskOn(i)));
2805 this->makeChildNodeEmpty(i, args.
result());
2808 typename OtherNodeType::ChildNodeType* otherChild = other.mNodes[i].getChild();
2810 if (this->isChildMaskOff(i)) {
2817 mNodes[i].getChild()->combine2(value, *otherChild, valueIsActive, op);
2823 template<
typename ChildT, Index Log2Dim>
2824 template<
typename CombineOp,
typename OtherValueType>
2827 bool valueIsActive, CombineOp& op)
2831 for (
Index i = 0; i < NUM_VALUES; ++i) {
2836 .setBIsActive(valueIsActive));
2838 this->makeChildNodeEmpty(i, args.
result());
2843 if (this->isChildMaskOff(i)) {
2845 this->setChildNode(i,
2846 new ChildNodeType(otherChild->origin(), mNodes[i].getValue()));
2850 mNodes[i].getChild()->combine2(*otherChild, value, valueIsActive, op);
2859 template<
typename ChildT, Index Log2Dim>
2860 template<
typename BBoxOp>
2871 if (op.template descent<LEVEL>()) {
2872 for (
ChildOnCIter i = this->cbeginChildOn(); i; ++i) i->visitActiveBBox(op);
2876 op.operator()<LEVEL>(i->getNodeBoundingBox());
2878 op.template operator()<LEVEL>(i->getNodeBoundingBox());
2885 template<
typename ChildT, Index Log2Dim>
2886 template<
typename VisitorOp>
2890 doVisit<InternalNode, VisitorOp, ChildAllIter>(*
this, op);
2894 template<
typename ChildT, Index Log2Dim>
2895 template<
typename VisitorOp>
2899 doVisit<const InternalNode, VisitorOp, ChildAllCIter>(*
this, op);
2903 template<
typename ChildT, Index Log2Dim>
2904 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
2908 typename NodeT::ValueType val;
2909 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
2910 if (op(iter))
continue;
2911 if (
typename ChildAllIterT::ChildNodeType* child = iter.probeChild(val)) {
2921 template<
typename ChildT, Index Log2Dim>
2922 template<
typename OtherNodeType,
typename VisitorOp>
2927 typename OtherNodeType::ChildAllIter>(*
this, other, op);
2931 template<
typename ChildT, Index Log2Dim>
2932 template<
typename OtherNodeType,
typename VisitorOp>
2937 typename OtherNodeType::ChildAllCIter>(*
this, other, op);
2941 template<
typename ChildT, Index Log2Dim>
2944 typename OtherNodeT,
2946 typename ChildAllIterT,
2947 typename OtherChildAllIterT>
2952 static_assert(OtherNodeT::NUM_VALUES == NodeT::NUM_VALUES,
2953 "visit2() requires nodes to have the same dimensions");
2954 static_assert(OtherNodeT::LEVEL == NodeT::LEVEL,
2955 "visit2() requires nodes to be at the same tree level");
2957 typename NodeT::ValueType val;
2958 typename OtherNodeT::ValueType otherVal;
2960 ChildAllIterT iter =
self.beginChildAll();
2961 OtherChildAllIterT otherIter = other.beginChildAll();
2963 for ( ; iter && otherIter; ++iter, ++otherIter)
2965 const size_t skipBranch = static_cast<size_t>(op(iter, otherIter));
2967 typename ChildAllIterT::ChildNodeType* child =
2968 (skipBranch & 1U) ?
nullptr : iter.probeChild(val);
2969 typename OtherChildAllIterT::ChildNodeType* otherChild =
2970 (skipBranch & 2U) ?
nullptr : otherIter.probeChild(otherVal);
2972 if (child !=
nullptr && otherChild !=
nullptr) {
2973 child->visit2Node(*otherChild, op);
2974 }
else if (child !=
nullptr) {
2975 child->visit2(otherIter, op);
2976 }
else if (otherChild !=
nullptr) {
2977 otherChild->visit2(iter, op,
true);
2986 template<
typename ChildT, Index Log2Dim>
2987 template<
typename OtherChildAllIterType,
typename VisitorOp>
2990 VisitorOp& op,
bool otherIsLHS)
2992 doVisit2<InternalNode, VisitorOp, ChildAllIter, OtherChildAllIterType>(
2993 *
this, otherIter, op, otherIsLHS);
2997 template<
typename ChildT, Index Log2Dim>
2998 template<
typename OtherChildAllIterType,
typename VisitorOp>
3001 VisitorOp& op,
bool otherIsLHS)
const 3003 doVisit2<const InternalNode, VisitorOp, ChildAllCIter, OtherChildAllIterType>(
3004 *
this, otherIter, op, otherIsLHS);
3008 template<
typename ChildT, Index Log2Dim>
3009 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT,
typename OtherChildAllIterT>
3012 VisitorOp& op,
bool otherIsLHS)
3014 if (!otherIter)
return;
3016 const size_t skipBitMask = (otherIsLHS ? 2U : 1U);
3018 typename NodeT::ValueType val;
3019 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
3020 const size_t skipBranch = static_cast<size_t>(
3021 otherIsLHS ? op(otherIter, iter) : op(iter, otherIter));
3023 typename ChildAllIterT::ChildNodeType* child =
3024 (skipBranch & skipBitMask) ?
nullptr : iter.probeChild(val);
3026 if (child !=
nullptr) child->visit2(otherIter, op, otherIsLHS);
3034 template<
typename ChildT, Index Log2Dim>
3038 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3039 iter->writeBuffers(os, toHalf);
3044 template<
typename ChildT, Index Log2Dim>
3048 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3049 iter->readBuffers(is, fromHalf);
3054 template<
typename ChildT, Index Log2Dim>
3057 const CoordBBox& clipBBox,
bool fromHalf)
3059 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3064 iter->readBuffers(is, clipBBox, fromHalf);
3068 ValueType background = zeroVal<ValueType>();
3070 background = *static_cast<const ValueType*>(bgPtr);
3072 this->
clip(clipBBox, background);
3079 template<
typename ChildT, Index Log2Dim>
3083 dims.push_back(Log2Dim);
3084 ChildNodeType::getNodeLog2Dims(dims);
3088 template<
typename ChildT, Index Log2Dim>
3092 assert(n<(1<<3*Log2Dim));
3093 xyz.
setX(n >> 2*Log2Dim);
3094 n &= ((1<<2*Log2Dim)-1);
3095 xyz.
setY(n >> Log2Dim);
3096 xyz.
setZ(n & ((1<<Log2Dim)-1));
3100 template<
typename ChildT, Index Log2Dim>
3104 return (((xyz[0] & (DIM-1u)) >> ChildNodeType::TOTAL) << 2*Log2Dim)
3105 + (((xyz[1] & (DIM-1u)) >> ChildNodeType::TOTAL) << Log2Dim)
3106 + ((xyz[2] & (DIM-1u)) >> ChildNodeType::TOTAL);
3110 template<
typename ChildT, Index Log2Dim>
3115 this->offsetToLocalCoord(n, local);
3116 local <<= ChildT::TOTAL;
3117 return local + this->origin();
3124 template<
typename ChildT, Index Log2Dim>
3125 template<
typename ArrayT>
3129 using T =
typename ArrayT::value_type;
3130 static_assert(std::is_pointer<T>::value,
"argument to getNodes() must be a pointer array");
3131 using ArrayChildT =
typename std::conditional<
3132 std::is_const<typename std::remove_pointer<T>::type>::value,
const ChildT, ChildT>::type;
3133 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3135 if (std::is_same<T, ArrayChildT*>::value) {
3136 array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild()));
3138 iter->getNodes(array);
3144 template<
typename ChildT, Index Log2Dim>
3145 template<
typename ArrayT>
3149 using T =
typename ArrayT::value_type;
3150 static_assert(std::is_pointer<T>::value,
"argument to getNodes() must be a pointer array");
3151 static_assert(std::is_const<
typename std::remove_pointer<T>::type>::value,
3152 "argument to getNodes() must be an array of const node pointers");
3153 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3155 if (std::is_same<T, const ChildT*>::value) {
3156 array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild()));
3158 iter->getNodes(array);
3168 template<
typename ChildT, Index Log2Dim>
3169 template<
typename ArrayT>
3173 using T =
typename ArrayT::value_type;
3174 static_assert(std::is_pointer<T>::value,
"argument to stealNodes() must be a pointer array");
3175 using ArrayChildT =
typename std::conditional<
3176 std::is_const<typename std::remove_pointer<T>::type>::value,
const ChildT, ChildT>::type;
3178 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3179 const Index n = iter.pos();
3180 if (std::is_same<T, ArrayChildT*>::value) {
3181 array.push_back(reinterpret_cast<T>(mNodes[n].getChild()));
3182 mValueMask.set(n, state);
3183 mNodes[n].setValue(value);
3185 iter->stealNodes(array, value, state);
3188 if (std::is_same<T, ArrayChildT*>::value) mChildMask.setOff();
3196 template<
typename ChildT, Index Log2Dim>
3202 for (
Index i = 0; i < NUM_VALUES; ++i) {
3203 if (this->isChildMaskOn(i)) {
3204 mNodes[i].getChild()->resetBackground(oldBackground, newBackground);
3205 }
else if (this->isValueMaskOff(i)) {
3207 mNodes[i].setValue(newBackground);
3215 template<
typename ChildT, Index Log2Dim>
3216 template<
typename OtherChildNodeType, Index OtherLog2Dim>
3221 if (Log2Dim != OtherLog2Dim || mChildMask != other->
mChildMask ||
3222 mValueMask != other->
mValueMask)
return false;
3223 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3224 if (!iter->hasSameTopology(other->
mNodes[iter.pos()].getChild()))
return false;
3230 template<
typename ChildT, Index Log2Dim>
3235 if (this->isChildMaskOn(i)) {
3236 delete mNodes[i].getChild();
3238 mChildMask.setOn(i);
3239 mValueMask.setOff(i);
3241 mNodes[i].setChild(child);
3244 template<
typename ChildT, Index Log2Dim>
3249 assert(mChildMask.isOff(i));
3250 mChildMask.setOn(i);
3251 mValueMask.setOff(i);
3252 mNodes[i].setChild(child);
3256 template<
typename ChildT, Index Log2Dim>
3260 if (this->isChildMaskOff(i)) {
3261 mNodes[i].setValue(value);
3265 mChildMask.setOff(i);
3266 mNodes[i].setValue(value);
3271 template<
typename ChildT, Index Log2Dim>
3275 delete this->unsetChildNode(n, value);
3278 template<
typename ChildT, Index Log2Dim>
3282 assert(this->isChildMaskOn(n));
3283 return mNodes[n].getChild();
3287 template<
typename ChildT, Index Log2Dim>
3288 inline const ChildT*
3291 assert(this->isChildMaskOn(n));
3292 return mNodes[n].getChild();
3299 #endif // OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED DenseIter(const MaskDenseIterator &iter, NodeT *parent)
Definition: InternalNode.h:210
Coord & setY(Int32 y)
Definition: Coord.h:107
Coord & setZ(Int32 z)
Definition: Coord.h:108
bool isConstant(ValueType &firstValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
Definition: InternalNode.h:1495
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition: InternalNode.h:3102
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1748
typename std::remove_const< UnsetItemT >::type NonConstValueType
Definition: Iterator.h:211
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition: InternalNode.h:1557
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:1892
Index64 onVoxelCount() const
Definition: InternalNode.h:1061
Definition: NodeMasks.h:272
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:1394
void readBuffers(std::istream &, bool fromHalf=false)
Definition: InternalNode.h:3046
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:56
void negate()
Change the sign of all the values represented in this node and its child nodes.
Definition: InternalNode.h:2294
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition: InternalNode.h:1667
ChildAllCIter cbeginChildAll() const
Definition: InternalNode.h:255
Index32 Index
Definition: Types.h:61
uint64_t Index64
Definition: Types.h:60
TopologyUnion(const OtherInternalNode *source, InternalNode *target)
Definition: InternalNode.h:2504
NodeMaskType mValueMask
Definition: InternalNode.h:841
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
Definition: InternalNode.h:1119
InternalNode * t
Definition: InternalNode.h:920
bool hasActiveTiles() const
Return true if this node or any of its child nodes have any active tiles.
Definition: InternalNode.h:1542
Coord & setX(Int32 x)
Definition: Coord.h:106
InternalNode * t
Definition: InternalNode.h:1002
ValueIter()
Definition: InternalNode.h:184
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition: InternalNode.h:2338
LeafNodeType * touchLeafAndCache(const Coord &xyz, AccessorT &)
Same as touchLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
Base class for dense iterators over internal and leaf nodes.
Definition: Iterator.h:205
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:1276
const OtherInternalNode * s
Definition: InternalNode.h:965
_ChildNodeType ChildNodeType
Definition: InternalNode.h:63
typename NodeMaskType::Word W
Definition: InternalNode.h:2500
Index32 leafCount() const
Definition: InternalNode.h:1035
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:1351
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:1810
ValueAllIter beginValueAll()
Definition: InternalNode.h:274
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:395
Base class for sparse iterators over internal and leaf nodes.
Definition: Iterator.h:141
Int32 z() const
Definition: Coord.h:159
void combine2(const InternalNode &other0, const OtherNodeType &other1, CombineOp &)
Definition: InternalNode.h:2746
ChildIter(const MaskIterT &iter, NodeT *parent)
Definition: InternalNode.h:164
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:518
void unsetItem(Index pos, const ValueT &value) const
Definition: InternalNode.h:231
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:2134
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2514
InternalNode * t
Definition: InternalNode.h:2639
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition: InternalNode.h:1651
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: InternalNode.h:1949
const Coord & max() const
Definition: Coord.h:338
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
const NodeType * probeConstNode(const Coord &xyz) const
Return a pointer to the node that contains voxel (x, y, z). If no such node exists,...
static void doVisit2Node(NodeT &, OtherNodeT &, VisitorOp &)
Definition: InternalNode.h:2949
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2320
void combine(InternalNode &other, CombineOp &)
Definition: InternalNode.h:2659
Definition: InternalNode.h:56
ValueIter(const MaskIterT &iter, NodeT *parent)
Definition: InternalNode.h:185
Definition: InternalNode.h:2600
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:2030
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation.
Definition: NodeMasks.h:309
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition: InternalNode.h:3127
NodeType * probeNodeAndCache(const Coord &xyz, AccessorT &)
Same as probeNode() except, if necessary, update the accessor with pointers to the nodes along the pa...
typename NodeMaskType::OnIterator MaskOnIterator
Definition: InternalNode.h:147
static void doVisit(NodeT &, VisitorOp &)
Definition: InternalNode.h:2906
Definition: InternalNode.h:836
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 AValueType & result() const
Get the output value.
Definition: Types.h:431
TopologyDifference(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:2603
void setOff(Index32 n)
Set the nth bit off.
Definition: NodeMasks.h:459
Definition: InternalNode.h:152
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
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:1462
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:955
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:1426
int32_t Int32
Definition: Types.h:63
bool isChildMaskOff(Index n) const
Definition: InternalNode.h:786
ChildNodeType * getChildNode(Index n)
Returns a pointer to the child node at the linear offset n.
Definition: InternalNode.h:3280
Index64 onTileCount() const
Definition: InternalNode.h:1108
Int32 x() const
Definition: Coord.h:157
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Definition: InternalNode.h:1567
bool resultIsActive() const
Definition: Types.h:450
typename NodeMaskType::OffIterator MaskOffIterator
Definition: InternalNode.h:148
Definition: InternalNode.h:2311
ChildOnCIter beginChildOn() const
Definition: InternalNode.h:256
const ValueType & b
Definition: InternalNode.h:2640
const OtherInternalNode * s
Definition: InternalNode.h:1001
Definition: InternalNode.h:181
void clip(const CoordBBox &, const ValueType &background)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: InternalNode.h:1980
void writeTopology(std::ostream &, bool toHalf=false) const
Definition: InternalNode.h:2179
static const Index NUM_VALUES
Definition: InternalNode.h:74
Definition: InternalNode.h:2547
Definition: InternalNode.h:152
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:3081
void visit2(IterT &otherIter, VisitorOp &, bool otherIsLHS=false)
const ValueT & getItem(Index pos) const
Definition: InternalNode.h:188
bool isInside(const Coord &xyz) const
Return true if point (x, y, z) is inside this bounding box.
Definition: Coord.h:404
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:3198
void setValue(const ValueT &val)
Definition: NodeUnion.h:74
void makeChildNodeEmpty(Index n, const ValueType &value)
Definition: InternalNode.h:3273
Definition: InternalNode.h:153
NodeType * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists,...
const NodeMaskType & getValueMask() const
Definition: InternalNode.h:788
ValueOnCIter beginValueOn() const
Definition: InternalNode.h:267
ChildOffCIter beginChildOff() const
Definition: InternalNode.h:257
Definition: NodeMasks.h:210
uint32_t Index32
Definition: Types.h:59
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
Definition: InternalNode.h:2597
ValueAllCIter beginValueAll() const
Definition: InternalNode.h:270
void operator()(W &tV, const W &sV, const W &tC) const
Definition: InternalNode.h:2501
bool probeValue(const Coord &xyz, ValueType &value) const
Definition: InternalNode.h:1623
Definition: InternalNode.h:833
ChildAllCIter beginChildAll() const
Definition: InternalNode.h:258
Definition: InternalNode.h:153
ChildT * getChild() const
Definition: NodeUnion.h:69
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:1132
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:323
typename NodeMaskType::DenseIterator MaskDenseIterator
Definition: InternalNode.h:149
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:2274
Definition: InternalNode.h:160
InternalNode * t
Definition: InternalNode.h:2531
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
Definition: NodeMasks.h:241
ValueOffIter beginValueOff()
Definition: InternalNode.h:273
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
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:2359
Definition: InternalNode.h:2597
void writeBuffers(std::ostream &, bool toHalf=false) const
Definition: InternalNode.h:3036
void visitActiveBBox(BBoxOp &) const
Calls the templated functor BBoxOp with bounding box information for all active tiles and leaf nodes ...
Definition: InternalNode.h:2862
ValueOnIter beginValueOn()
Definition: InternalNode.h:271
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:1174
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:991
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition: Coord.h:416
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Definition: InternalNode.h:1829
Definition: version.h:220
static Index dim()
Definition: InternalNode.h:279
static void doVisit2(NodeT &, OtherChildAllIterT &, VisitorOp &, bool otherIsLHS)
Definition: InternalNode.h:3011
~InternalNode()
Definition: InternalNode.h:1022
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of an Intern...
Definition: InternalNode.h:91
ChildT & getItem(Index pos) const
Definition: InternalNode.h:167
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:108
ChildOnCIter cbeginChildOn() const
Definition: InternalNode.h:253
ChildOnIter beginChildOn()
Definition: InternalNode.h:259
void setItem(Index pos, const ValueT &v) const
Definition: InternalNode.h:191
typename BaseT::NonConstValueType NonConstValueT
Definition: InternalNode.h:207
void resetChildNode(Index i, ChildNodeType *child)
Definition: InternalNode.h:3232
Definition: InternalNode.h:2501
const Coord & min() const
Definition: Coord.h:337
bool getItem(Index pos, ChildT *&child, NonConstValueT &value) const
Definition: InternalNode.h:213
Index64 offVoxelCount() const
Definition: InternalNode.h:1073
const OtherInternalNode * s
Definition: InternalNode.h:2530
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:3090
const ValueT & getValue() const
Definition: NodeUnion.h:72
VoxelizeActiveTiles(InternalNode &node)
Definition: InternalNode.h:2313
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:3218
const LeafNodeType * probeConstLeafAndCache(const Coord &xyz, AccessorT &acc) const
Same as probeLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
Definition: Exceptions.h:40
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:264
void modifyItem(Index pos, const ModifyOp &op) const
Definition: InternalNode.h:195
bool isValueMaskOff(Index n) const
Definition: InternalNode.h:783
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:2282
bool isChildMaskOff() const
Definition: InternalNode.h:787
bool isValueMaskOn() const
Definition: InternalNode.h:782
void readTopology(std::istream &, bool fromHalf=false)
Definition: InternalNode.h:2204
ChildOffIter beginChildOff()
Definition: InternalNode.h:260
const ValueType & b
Definition: InternalNode.h:967
const UnionType * getTable() const
Definition: InternalNode.h:797
const NodeMaskType & getChildMask() const
Definition: InternalNode.h:789
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:1864
Index32 nonLeafCount() const
Definition: InternalNode.h:1048
bool isApproxEqual(const Type &a, const Type &b)
Return true if a is equal to b to within the default floating-point comparison tolerance.
Definition: Math.h:358
NodeMaskType mChildMask
Definition: InternalNode.h:841
Index64 Word
Definition: NodeMasks.h:318
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:422
Definition: InternalNode.h:834
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:910
InternalNode * mNode
Definition: InternalNode.h:2333
void operator()(W &tV, const W &sC, const W &sV, const W &tC) const
Definition: InternalNode.h:2600
static Index getLevel()
Definition: InternalNode.h:282
bool isInactive() const
Return true if this node has no children and only contains inactive values.
Definition: InternalNode.h:354
bool isEmpty() const
Definition: InternalNode.h:326
TopologyCopy1(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:950
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:386
Library and file format version numbers.
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Definition: InternalNode.h:3112
void addLeaf(LeafNodeType *leaf)
Add the specified leaf to this node, possibly creating a child branch in the process....
Definition: InternalNode.h:1322
const ValueType & b
Definition: InternalNode.h:2580
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,...
InternalNode * t
Definition: InternalNode.h:966
bool isValueMaskOn(Index n) const
Definition: InternalNode.h:781
Int32 y() const
Definition: Coord.h:158
ValueConverter<T>::Type is the type of an InternalNode having the same child hierarchy and dimensions...
Definition: InternalNode.h:82
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: InternalNode.h:1926
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:2086
ChildOffCIter cbeginChildOff() const
Definition: InternalNode.h:254
DenseIter()
Definition: InternalNode.h:209
void setValuesOn()
Mark all values (both tiles and voxels) as active.
Definition: InternalNode.h:1852
DeepCopy(const OtherInternalNode *source, InternalNode *target)
Definition: InternalNode.h:906
Coord mOrigin
Global grid index coordinates (x,y,z) of the local origin of this node.
Definition: InternalNode.h:843
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 isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Definition: InternalNode.h:359
Definition: InternalNode.h:203
void visit(VisitorOp &)
Definition: InternalNode.h:2888
bool isChildMaskOn(Index n) const
Definition: InternalNode.h:785
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1703
ValueOffCIter beginValueOff() const
Definition: InternalNode.h:269
ValueAllCIter cbeginValueAll() const
Definition: InternalNode.h:266
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1789
const OtherInternalNode * s
Definition: InternalNode.h:919
Definition: version.h:229
Definition: InternalNode.h:835
const ValueType & getValue(const Coord &xyz) const
Definition: InternalNode.h:1578
typename ChildNodeType::ValueType ValueType
Definition: InternalNode.h:65
TopologyCopy2(const OtherInternalNode *source, InternalNode *target, const ValueType &offValue, const ValueType &onValue)
Definition: InternalNode.h:986
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:1150
void setItem(Index pos, const ChildT &c) const
Definition: InternalNode.h:174
void toggle(Index32 n)
Toggle the state of the nth bit.
Definition: NodeMasks.h:485
static Coord max()
Return the largest possible coordinate.
Definition: Coord.h:73
ValueOnCIter cbeginValueOn() const
Definition: InternalNode.h:263
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...
ChildNodeType * unsetChildNode(Index i, const ValueType &value)
Definition: InternalNode.h:3258
const OtherInternalNode * s
Definition: InternalNode.h:2638
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2617
Tag dispatch class that distinguishes constructors during file input.
Definition: Types.h:520
void writeCompressedValues(std::ostream &os, ValueT *srcBuf, Index srcCount, const MaskT &valueMask, const MaskT &childMask, bool toHalf)
Definition: Compression.h:462
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
Definition: InternalNode.h:2547
typename ChildNodeType::LeafNodeType LeafNodeType
Definition: InternalNode.h:64
void setItem(Index pos, ChildT *child) const
Definition: InternalNode.h:225
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Definition: InternalNode.h:1636
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
Definition: InternalNode.h:302
Definition: InternalNode.h:832
typename ChildNodeType::BuildType BuildType
Definition: InternalNode.h:66
void visit2Node(OtherNodeType &other, VisitorOp &)
Definition: InternalNode.h:2924
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: Types.h:439
static CoordBBox createCube(const Coord &min, ValueType dim)
Definition: Coord.h:329
UnionType mNodes[NUM_VALUES]
Definition: InternalNode.h:837
Index64 onLeafVoxelCount() const
Definition: InternalNode.h:1085
Index64 offLeafVoxelCount() const
Definition: InternalNode.h:1097
const ValueType & onV
Definition: InternalNode.h:1003
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: InternalNode.h:300
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
const NodeType * probeConstNodeAndCache(const Coord &xyz, AccessorT &) const
Same as probeNode() except, if necessary, update the accessor with pointers to the nodes along the pa...
Level getLevel()
Return the current logging level.
Definition: logging.h:165
static Index getChildDim()
Definition: InternalNode.h:289
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition: Coord.h:202
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:1610
typename NodeMaskType::Word W
Definition: InternalNode.h:2596
TopologyIntersection(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:2550
ValueOffCIter cbeginValueOff() const
Definition: InternalNode.h:265
static bool lessThan(const Coord &a, const Coord &b)
Definition: Coord.h:235
void readCompressedValues(std::istream &is, ValueT *destBuf, Index destCount, const MaskT &valueMask, bool fromHalf)
Definition: Compression.h:339
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:1772
Definition: InternalNode.h:60
Definition: InternalNode.h:837
const OtherInternalNode * s
Definition: InternalNode.h:2578
ChildIter()
Definition: InternalNode.h:163
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:1601
void setChildNode(Index i, ChildNodeType *child)
Definition: InternalNode.h:3246
NodeMaskType getValueOffMask() const
Definition: InternalNode.h:790
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:3171
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2562
InternalNode()
Default constructor.
Definition: InternalNode.h:99
void setOn(Index32 n)
Set the nth bit on.
Definition: NodeMasks.h:454
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists,...
Definition: InternalNode.h:1302
bool isValueMaskOff() const
Definition: InternalNode.h:784
InternalNode * t
Definition: InternalNode.h:2579
void translate(const Coord &t)
Definition: Coord.h:462
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:118
typename NodeMaskType::Word W
Definition: InternalNode.h:2546
ChildAllIter beginChildAll()
Definition: InternalNode.h:261