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 #ifndef OPENVDB_2_ABI_COMPATIBLE 123 template<
typename OtherChildNodeType>
129 template<
typename OtherChildNodeType>
136 template<
typename OtherChildNodeType>
138 const ValueType& offValue,
const ValueType& onValue,
TopologyCopy);
155 template<
typename NodeT,
typename ChildT,
typename MaskIterT,
typename TagT>
157 MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>
161 MaskIterT,
ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>(iter, parent) {}
165 assert(this->parent().isChildMaskOn(pos));
166 return *(this->parent().getChildNode(pos));
170 void setItem(
Index pos,
const ChildT& c)
const { this->parent().resetChildNode(pos, &c); }
176 template<
typename NodeT,
typename ValueT,
typename MaskIterT,
typename TagT>
178 MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>
182 MaskIterT,
ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>(iter, parent) {}
184 const ValueT&
getItem(
Index pos)
const {
return this->parent().mNodes[pos].getValue(); }
187 void setItem(
Index pos,
const ValueT& v)
const { this->parent().mNodes[pos].setValue(v); }
190 template<
typename ModifyOp>
193 op(this->parent().mNodes[pos].getValue());
198 template<
typename NodeT,
typename ChildT,
typename ValueT,
typename TagT>
200 MaskDenseIterator, DenseIter<NodeT, ChildT, ValueT, TagT>, NodeT, ChildT, ValueT>
211 if (this->parent().isChildMaskOn(pos)) {
212 child = this->parent().getChildNode(pos);
216 value = this->parent().mNodes[pos].getValue();
223 this->parent().resetChildNode(pos, child);
229 this->parent().unsetChildNode(pos, value);
281 static void getNodeLog2Dims(std::vector<Index>& dims);
291 static void offsetToLocalCoord(
Index n,
Coord& xyz);
304 Index64 onLeafVoxelCount()
const;
305 Index64 offLeafVoxelCount()
const;
315 void evalActiveBoundingBox(
CoordBBox& bbox,
bool visitVoxels =
true)
const;
322 bool isEmpty()
const {
return mChildMask.isOff(); }
329 bool isConstant(ValueType& firstValue,
bool& state,
330 const ValueType& tolerance = zeroVal<ValueType>())
const;
346 bool isConstant(ValueType& minValue, ValueType& maxValue,
347 bool& state,
const ValueType& tolerance = zeroVal<ValueType>())
const;
350 bool isInactive()
const {
return this->isChildMaskOff() && this->isValueMaskOff(); }
353 bool isValueOn(
const Coord& xyz)
const;
358 bool hasActiveTiles()
const;
360 const ValueType& getValue(
const Coord& xyz)
const;
361 bool probeValue(
const Coord& xyz, ValueType& value)
const;
369 const ValueType& getFirstValue()
const;
372 const ValueType& getLastValue()
const;
375 void setActiveState(
const Coord& xyz,
bool on);
377 void setValueOnly(
const Coord& xyz,
const ValueType& value);
379 void setValueOn(
const Coord& xyz);
381 void setValueOn(
const Coord& xyz,
const ValueType& value);
383 void setValueOff(
const Coord& xyz);
385 void setValueOff(
const Coord& xyz,
const ValueType& value);
389 template<
typename ModifyOp>
390 void modifyValue(
const Coord& xyz,
const ModifyOp& op);
392 template<
typename ModifyOp>
393 void modifyValueAndActiveState(
const Coord& xyz,
const ModifyOp& op);
399 template<
typename AccessorT>
400 const ValueType& getValueAndCache(
const Coord& xyz, AccessorT&)
const;
406 template<
typename AccessorT>
407 bool isValueOnAndCache(
const Coord& xyz, AccessorT&)
const;
413 template<
typename AccessorT>
414 void setValueAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
420 template<
typename AccessorT>
421 void setValueOnlyAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
428 template<
typename ModifyOp,
typename AccessorT>
429 void modifyValueAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
435 template<
typename ModifyOp,
typename AccessorT>
436 void modifyValueAndActiveStateAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
442 template<
typename AccessorT>
443 void setValueOffAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
449 template<
typename AccessorT>
450 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&);
457 template<
typename AccessorT>
458 bool probeValueAndCache(
const Coord& xyz, ValueType& value, AccessorT&)
const;
466 template<
typename AccessorT>
467 Index getValueLevelAndCache(
const Coord& xyz, AccessorT&)
const;
475 void writeTopology(std::ostream&,
bool toHalf =
false)
const;
476 void readTopology(std::istream&,
bool fromHalf =
false);
477 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
478 void readBuffers(std::istream&,
bool fromHalf =
false);
479 void readBuffers(std::istream&,
const CoordBBox&,
bool fromHalf =
false);
497 void fill(
const CoordBBox& bbox,
const ValueType& value,
bool active =
true);
506 void denseFill(
const CoordBBox& bbox,
const ValueType& value,
bool active =
true);
511 void voxelizeActiveTiles(
bool threaded =
true);
520 template<
typename DenseT>
525 template<MergePolicy Policy>
526 void merge(
InternalNode& other,
const ValueType& background,
const ValueType& otherBackground);
530 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive);
544 template<
typename OtherChildNodeType>
560 template<
typename OtherChildNodeType>
562 const ValueType& background);
575 template<
typename OtherChildNodeType>
577 const ValueType& background);
579 template<
typename CombineOp>
581 template<
typename CombineOp>
582 void combine(
const ValueType& value,
bool valueIsActive, CombineOp&);
584 template<
typename CombineOp,
typename OtherNodeType >
585 void combine2(
const InternalNode& other0,
const OtherNodeType& other1, CombineOp&);
586 template<
typename CombineOp,
typename OtherNodeType >
587 void combine2(
const ValueType& value,
const OtherNodeType& other,
bool valIsActive, CombineOp&);
588 template<
typename CombineOp,
typename OtherValueType>
589 void combine2(
const InternalNode& other,
const OtherValueType&,
bool valIsActive, CombineOp&);
596 template<
typename BBoxOp>
void visitActiveBBox(BBoxOp&)
const;
598 template<
typename VisitorOp>
void visit(VisitorOp&);
599 template<
typename VisitorOp>
void visit(VisitorOp&)
const;
601 template<
typename OtherNodeType,
typename VisitorOp>
602 void visit2Node(OtherNodeType& other, VisitorOp&);
603 template<
typename OtherNodeType,
typename VisitorOp>
604 void visit2Node(OtherNodeType& other, VisitorOp&)
const;
605 template<
typename IterT,
typename VisitorOp>
606 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false);
607 template<
typename IterT,
typename VisitorOp>
608 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false)
const;
616 void prune(
const ValueType& tolerance = zeroVal<ValueType>());
620 void addLeaf(LeafNodeType* leaf);
624 template<
typename AccessorT>
625 void addLeafAndCache(LeafNodeType* leaf, AccessorT&);
635 template<
typename NodeT>
636 NodeT* stealNode(
const Coord& xyz,
const ValueType& value,
bool state);
640 void addTile(
Index level,
const Coord& xyz,
const ValueType& value,
bool state);
643 void addTile(
Index offset,
const ValueType& value,
bool state);
647 template<
typename AccessorT>
648 void addTileAndCache(
Index level,
const Coord& xyz,
const ValueType&,
bool state, AccessorT&);
651 template<
typename NodeType> NodeType* probeNode(
const Coord& xyz);
654 template<
typename NodeType>
const NodeType* probeConstNode(
const Coord& xyz)
const;
658 template<
typename NodeType,
typename AccessorT>
661 NodeType* probeNodeAndCache(
const Coord& xyz, AccessorT&);
662 template<
typename NodeType,
typename AccessorT>
663 const NodeType* probeConstNodeAndCache(
const Coord& xyz, AccessorT&)
const;
667 LeafNodeType* probeLeaf(
const Coord& xyz);
670 const LeafNodeType* probeConstLeaf(
const Coord& xyz)
const;
671 const LeafNodeType* probeLeaf(
const Coord& xyz)
const;
675 template<
typename AccessorT>
678 LeafNodeType* probeLeafAndCache(
const Coord& xyz, AccessorT& acc);
679 template<
typename AccessorT>
680 const LeafNodeType* probeConstLeafAndCache(
const Coord& xyz, AccessorT& acc)
const;
681 template<
typename AccessorT>
682 const LeafNodeType* probeLeafAndCache(
const Coord& xyz, AccessorT& acc)
const;
691 LeafNodeType* touchLeaf(
const Coord& xyz);
695 template<
typename AccessorT>
696 LeafNodeType* touchLeafAndCache(
const Coord& xyz, AccessorT&);
699 template<
typename ArrayT>
722 void getNodes(ArrayT& array);
723 template<
typename ArrayT>
724 void getNodes(ArrayT& array)
const;
750 template<
typename ArrayT>
751 void stealNodes(ArrayT& array,
const ValueType& value,
bool state);
755 void resetBackground(
const ValueType& oldBackground,
const ValueType& newBackground);
759 template<
typename OtherChildNodeType, Index OtherLog2Dim>
796 void setValueMask(
Index n,
bool on) { mValueMask.set(n, mChildMask.isOn(n) ? false : on); }
801 void makeChildNodeEmpty(
Index n,
const ValueType& value);
802 void setChildNode(
Index i, ChildNodeType* child);
803 void resetChildNode(
Index i, ChildNodeType* child);
804 ChildNodeType* unsetChildNode(
Index i,
const ValueType& value);
806 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
807 static inline void doVisit(NodeT&, VisitorOp&);
809 template<
typename NodeT,
typename OtherNodeT,
typename VisitorOp,
810 typename ChildAllIterT,
typename OtherChildAllIterT>
811 static inline void doVisit2Node(NodeT&, OtherNodeT&, VisitorOp&);
813 template<
typename NodeT,
typename VisitorOp,
814 typename ChildAllIterT,
typename OtherChildAllIterT>
815 static inline void doVisit2(NodeT&, OtherChildAllIterT&, VisitorOp&,
bool otherIsLHS);
821 ChildNodeType* getChildNode(
Index n);
822 const ChildNodeType* getChildNode(
Index n)
const;
827 struct VoxelizeActiveTiles;
828 template<
typename OtherInternalNode>
struct DeepCopy;
847 template<
typename ChildT1, Index Dim1,
typename NodeT2>
851 static const bool value =
false;
854 template<
typename ChildT1, Index Dim1,
typename ChildT2>
856 static const bool value = ChildT1::template SameConfiguration<ChildT2>::value;
864 template<
typename ChildT, Index Log2Dim>
868 for (
Index i = 0;
i < NUM_VALUES; ++
i) mNodes[
i].setValue(background);
872 template<
typename ChildT, Index Log2Dim>
875 mOrigin(origin[0] & ~(DIM - 1),
876 origin[1] & ~(DIM - 1),
877 origin[2] & ~(DIM - 1))
884 #ifndef OPENVDB_2_ABI_COMPATIBLE 887 template<
typename ChildT, Index Log2Dim>
891 : mOrigin(origin[0] & ~(DIM-1), origin[1] & ~(DIM-1), origin[2] & ~(DIM-1))
898 template<
typename ChildT, Index Log2Dim>
899 template<
typename OtherInternalNode>
903 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
907 for (
Index i = r.begin(), end=r.end();
i!=end; ++
i) {
908 if (s->mChildMask.isOff(
i)) {
909 t->mNodes[
i].setValue(
ValueType(s->mNodes[
i].getValue()));
915 const OtherInternalNode*
s;
919 template<
typename ChildT, Index Log2Dim>
922 mChildMask(other.mChildMask),
923 mValueMask(other.mValueMask),
924 mOrigin(other.mOrigin)
931 template<
typename ChildT, Index Log2Dim>
932 template<
typename OtherChildNodeType>
935 : mChildMask(other.mChildMask)
936 , mValueMask(other.mValueMask)
937 , mOrigin(other.mOrigin)
942 template<
typename ChildT, Index Log2Dim>
943 template<
typename OtherInternalNode>
947 const ValueType& background) : s(source), t(target), b(background) {
948 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
952 for (
Index i = r.begin(), end=r.end();
i!=end; ++
i) {
953 if (s->isChildMaskOn(
i)) {
957 t->mNodes[
i].setValue(b);
961 const OtherInternalNode*
s;
966 template<
typename ChildT, Index Log2Dim>
967 template<
typename OtherChildNodeType>
971 mChildMask(other.mChildMask),
972 mValueMask(other.mValueMask),
973 mOrigin(other.mOrigin)
978 template<
typename ChildT, Index Log2Dim>
979 template<
typename OtherInternalNode>
984 : s(source), t(target), offV(offValue), onV(onValue) {
985 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
988 for (
Index i = r.begin(), end=r.end();
i!=end; ++
i) {
989 if (s->isChildMaskOn(
i)) {
993 t->mNodes[
i].setValue(s->isValueMaskOn(
i) ? onV : offV);
997 const OtherInternalNode*
s;
1002 template<
typename ChildT, Index Log2Dim>
1003 template<
typename OtherChildNodeType>
1008 mChildMask(other.mChildMask),
1009 mValueMask(other.mValueMask),
1010 mOrigin(other.mOrigin)
1016 template<
typename ChildT, Index Log2Dim>
1020 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1021 delete mNodes[iter.pos()].getChild();
1029 template<
typename ChildT, Index Log2Dim>
1035 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1036 sum += iter->leafCount();
1042 template<
typename ChildT, Index Log2Dim>
1048 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1049 sum += iter->nonLeafCount();
1055 template<
typename ChildT, Index Log2Dim>
1059 Index64 sum = ChildT::NUM_VOXELS * mValueMask.countOn();
1060 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1061 sum += iter->onVoxelCount();
1067 template<
typename ChildT, Index Log2Dim>
1071 Index64 sum = ChildT::NUM_VOXELS * (NUM_VALUES-mValueMask.countOn()-mChildMask.countOn());
1072 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1073 sum += iter->offVoxelCount();
1079 template<
typename ChildT, Index Log2Dim>
1084 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1085 sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount();
1091 template<
typename ChildT, Index Log2Dim>
1096 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1097 sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount();
1102 template<
typename ChildT, Index Log2Dim>
1106 Index64 sum = mValueMask.countOn();
1107 for (
ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) {
1108 sum += iter->onTileCount();
1113 template<
typename ChildT, Index Log2Dim>
1118 + mValueMask.memUsage() +
sizeof(mOrigin);
1119 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1120 sum += iter->memUsage();
1126 template<
typename ChildT, Index Log2Dim>
1130 if (bbox.
isInside(this->getNodeBoundingBox()))
return;
1133 bbox.
expand(
i.getCoord(), ChildT::DIM);
1136 i->evalActiveBoundingBox(bbox, visitVoxels);
1144 template<
typename ChildT, Index Log2Dim>
1150 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1151 const Index i = iter.pos();
1152 ChildT* child = mNodes[
i].getChild();
1153 child->prune(tolerance);
1154 if (child->isConstant(value, state, tolerance)) {
1156 mChildMask.setOff(
i);
1157 mValueMask.set(
i, state);
1158 mNodes[
i].setValue(value);
1167 template<
typename ChildT, Index Log2Dim>
1168 template<
typename NodeT>
1172 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1173 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1175 const Index n = this->coordToOffset(xyz);
1176 if (mChildMask.isOff(n))
return nullptr;
1177 ChildT* child = mNodes[n].getChild();
1178 if (std::is_same<NodeT, ChildT>::value) {
1179 mChildMask.setOff(n);
1180 mValueMask.set(n, state);
1181 mNodes[n].setValue(value);
1183 return (std::is_same<NodeT, ChildT>::value)
1184 ?
reinterpret_cast<NodeT*
>(child)
1185 : child->template stealNode<NodeT>(xyz, value, state);
1193 template<
typename ChildT, Index Log2Dim>
1194 template<
typename NodeT>
1198 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1199 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1201 const Index n = this->coordToOffset(xyz);
1202 if (mChildMask.isOff(n))
return nullptr;
1203 ChildT* child = mNodes[n].getChild();
1204 return (std::is_same<NodeT, ChildT>::value)
1205 ?
reinterpret_cast<NodeT*
>(child)
1206 : child->template probeNode<NodeT>(xyz);
1211 template<
typename ChildT, Index Log2Dim>
1212 template<
typename NodeT,
typename AccessorT>
1216 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1217 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1219 const Index n = this->coordToOffset(xyz);
1220 if (mChildMask.isOff(n))
return nullptr;
1221 ChildT* child = mNodes[n].getChild();
1222 acc.insert(xyz, child);
1223 return (std::is_same<NodeT, ChildT>::value)
1224 ?
reinterpret_cast<NodeT*
>(child)
1225 : child->template probeNodeAndCache<NodeT>(xyz, acc);
1230 template<
typename ChildT, Index Log2Dim>
1231 template<
typename NodeT>
1235 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1236 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1238 const Index n = this->coordToOffset(xyz);
1239 if (mChildMask.isOff(n))
return nullptr;
1240 const ChildT* child = mNodes[n].getChild();
1241 return (std::is_same<NodeT, ChildT>::value)
1242 ?
reinterpret_cast<const NodeT*
>(child)
1243 : child->template probeConstNode<NodeT>(xyz);
1248 template<
typename ChildT, Index Log2Dim>
1249 template<
typename NodeT,
typename AccessorT>
1253 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1254 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1256 const Index n = this->coordToOffset(xyz);
1257 if (mChildMask.isOff(n))
return nullptr;
1258 const ChildT* child = mNodes[n].getChild();
1259 acc.insert(xyz, child);
1260 return (std::is_same<NodeT, ChildT>::value)
1261 ?
reinterpret_cast<const NodeT*
>(child)
1262 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
1270 template<
typename ChildT, Index Log2Dim>
1271 inline typename ChildT::LeafNodeType*
1274 return this->
template probeNode<LeafNodeType>(xyz);
1278 template<
typename ChildT, Index Log2Dim>
1279 template<
typename AccessorT>
1280 inline typename ChildT::LeafNodeType*
1283 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
1287 template<
typename ChildT, Index Log2Dim>
1288 template<
typename AccessorT>
1289 inline const typename ChildT::LeafNodeType*
1292 return this->probeConstLeafAndCache(xyz, acc);
1296 template<
typename ChildT, Index Log2Dim>
1297 inline const typename ChildT::LeafNodeType*
1300 return this->
template probeConstNode<LeafNodeType>(xyz);
1304 template<
typename ChildT, Index Log2Dim>
1305 template<
typename AccessorT>
1306 inline const typename ChildT::LeafNodeType*
1309 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
1316 template<
typename ChildT, Index Log2Dim>
1320 assert(leaf !=
nullptr);
1321 const Coord& xyz = leaf->origin();
1322 const Index n = this->coordToOffset(xyz);
1323 ChildT* child =
nullptr;
1324 if (mChildMask.isOff(n)) {
1325 if (ChildT::LEVEL>0) {
1326 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1328 child =
reinterpret_cast<ChildT*
>(leaf);
1330 this->setChildNode(n, child);
1332 if (ChildT::LEVEL>0) {
1333 child = mNodes[n].getChild();
1335 delete mNodes[n].getChild();
1336 child =
reinterpret_cast<ChildT*
>(leaf);
1337 mNodes[n].setChild(child);
1340 child->addLeaf(leaf);
1344 template<
typename ChildT, Index Log2Dim>
1345 template<
typename AccessorT>
1349 assert(leaf !=
nullptr);
1350 const Coord& xyz = leaf->origin();
1351 const Index n = this->coordToOffset(xyz);
1352 ChildT* child =
nullptr;
1353 if (mChildMask.isOff(n)) {
1354 if (ChildT::LEVEL>0) {
1355 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1356 acc.insert(xyz, child);
1358 child =
reinterpret_cast<ChildT*
>(leaf);
1360 this->setChildNode(n, child);
1362 if (ChildT::LEVEL>0) {
1363 child = mNodes[n].getChild();
1364 acc.insert(xyz, child);
1366 delete mNodes[n].getChild();
1367 child =
reinterpret_cast<ChildT*
>(leaf);
1368 mNodes[n].setChild(child);
1371 child->addLeafAndCache(leaf, acc);
1378 template<
typename ChildT, Index Log2Dim>
1382 assert(n < NUM_VALUES);
1383 this->makeChildNodeEmpty(n, value);
1384 mValueMask.set(n, state);
1388 template<
typename ChildT, Index Log2Dim>
1393 if (LEVEL >= level) {
1394 const Index n = this->coordToOffset(xyz);
1395 if (mChildMask.isOff(n)) {
1396 if (LEVEL > level) {
1397 ChildT* child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1398 this->setChildNode(n, child);
1399 child->addTile(level, xyz, value, state);
1401 mValueMask.set(n, state);
1402 mNodes[n].setValue(value);
1405 ChildT* child = mNodes[n].getChild();
1406 if (LEVEL > level) {
1407 child->addTile(level, xyz, value, state);
1410 mChildMask.setOff(n);
1411 mValueMask.set(n, state);
1412 mNodes[n].setValue(value);
1419 template<
typename ChildT, Index Log2Dim>
1420 template<
typename AccessorT>
1423 const ValueType& value,
bool state, AccessorT& acc)
1425 if (LEVEL >= level) {
1426 const Index n = this->coordToOffset(xyz);
1427 if (mChildMask.isOff(n)) {
1428 if (LEVEL > level) {
1429 ChildT* child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1430 this->setChildNode(n, child);
1431 acc.insert(xyz, child);
1432 child->addTileAndCache(level, xyz, value, state, acc);
1434 mValueMask.set(n, state);
1435 mNodes[n].setValue(value);
1438 ChildT* child = mNodes[n].getChild();
1439 if (LEVEL > level) {
1440 acc.insert(xyz, child);
1441 child->addTileAndCache(level, xyz, value, state, acc);
1444 mChildMask.setOff(n);
1445 mValueMask.set(n, state);
1446 mNodes[n].setValue(value);
1456 template<
typename ChildT, Index Log2Dim>
1457 inline typename ChildT::LeafNodeType*
1460 const Index n = this->coordToOffset(xyz);
1461 ChildT* child =
nullptr;
1462 if (mChildMask.isOff(n)) {
1463 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1464 this->setChildNode(n, child);
1466 child = mNodes[n].getChild();
1468 return child->touchLeaf(xyz);
1472 template<
typename ChildT, Index Log2Dim>
1473 template<
typename AccessorT>
1474 inline typename ChildT::LeafNodeType*
1477 const Index n = this->coordToOffset(xyz);
1478 if (mChildMask.isOff(n)) {
1479 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), mValueMask.isOn(n)));
1481 acc.insert(xyz, mNodes[n].getChild());
1482 return mNodes[n].getChild()->touchLeafAndCache(xyz, acc);
1489 template<
typename ChildT, Index Log2Dim>
1494 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1496 firstValue = mNodes[0].getValue();
1497 for (
Index i = 1;
i < NUM_VALUES; ++
i) {
1509 template<
typename ChildT, Index Log2Dim>
1517 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1518 minValue = maxValue = mNodes[0].getValue();
1519 for (
Index i = 1;
i < NUM_VALUES; ++
i) {
1522 if ((maxValue - v) > tolerance)
return false;
1524 }
else if (v > maxValue) {
1525 if ((v - minValue) > tolerance)
return false;
1536 template<
typename ChildT, Index Log2Dim>
1541 const bool anyActiveTiles = !mValueMask.isOff();
1542 if (LEVEL==1 || anyActiveTiles)
return anyActiveTiles;
1543 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1544 if (iter->hasActiveTiles())
return true;
1551 template<
typename ChildT, Index Log2Dim>
1555 const Index n = this->coordToOffset(xyz);
1556 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1557 return mNodes[n].getChild()->isValueOn(xyz);
1560 template<
typename ChildT, Index Log2Dim>
1561 template<
typename AccessorT>
1565 const Index n = this->coordToOffset(xyz);
1566 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1567 acc.insert(xyz, mNodes[n].getChild());
1568 return mNodes[n].getChild()->isValueOnAndCache(xyz, acc);
1572 template<
typename ChildT, Index Log2Dim>
1573 inline const typename ChildT::ValueType&
1576 const Index n = this->coordToOffset(xyz);
1577 return this->isChildMaskOff(n) ? mNodes[n].getValue()
1578 : mNodes[n].getChild()->getValue(xyz);
1581 template<
typename ChildT, Index Log2Dim>
1582 template<
typename AccessorT>
1583 inline const typename ChildT::ValueType&
1586 const Index n = this->coordToOffset(xyz);
1587 if (this->isChildMaskOn(n)) {
1588 acc.insert(xyz, mNodes[n].getChild());
1589 return mNodes[n].getChild()->getValueAndCache(xyz, acc);
1591 return mNodes[n].getValue();
1595 template<
typename ChildT, Index Log2Dim>
1599 const Index n = this->coordToOffset(xyz);
1600 return this->isChildMaskOff(n) ? LEVEL : mNodes[n].getChild()->getValueLevel(xyz);
1603 template<
typename ChildT, Index Log2Dim>
1604 template<
typename AccessorT>
1608 const Index n = this->coordToOffset(xyz);
1609 if (this->isChildMaskOn(n)) {
1610 acc.insert(xyz, mNodes[n].getChild());
1611 return mNodes[n].getChild()->getValueLevelAndCache(xyz, acc);
1617 template<
typename ChildT, Index Log2Dim>
1621 const Index n = this->coordToOffset(xyz);
1622 if (this->isChildMaskOff(n)) {
1623 value = mNodes[n].getValue();
1624 return this->isValueMaskOn(n);
1626 return mNodes[n].getChild()->probeValue(xyz, value);
1629 template<
typename ChildT, Index Log2Dim>
1630 template<
typename AccessorT>
1635 const Index n = this->coordToOffset(xyz);
1636 if (this->isChildMaskOn(n)) {
1637 acc.insert(xyz, mNodes[n].getChild());
1638 return mNodes[n].getChild()->probeValueAndCache(xyz, value, acc);
1640 value = mNodes[n].getValue();
1641 return this->isValueMaskOn(n);
1645 template<
typename ChildT, Index Log2Dim>
1649 const Index n = this->coordToOffset(xyz);
1650 bool hasChild = this->isChildMaskOn(n);
1651 if (!hasChild && this->isValueMaskOn(n)) {
1655 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
true));
1657 if (hasChild) mNodes[n].getChild()->setValueOff(xyz);
1661 template<
typename ChildT, Index Log2Dim>
1665 const Index n = this->coordToOffset(xyz);
1666 bool hasChild = this->isChildMaskOn(n);
1667 if (!hasChild && !this->isValueMaskOn(n)) {
1671 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
false));
1673 if (hasChild) mNodes[n].getChild()->setValueOn(xyz);
1677 template<
typename ChildT, Index Log2Dim>
1682 bool hasChild = this->isChildMaskOn(n);
1684 const bool active = this->isValueMaskOn(n);
1690 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1693 if (hasChild) mNodes[n].getChild()->setValueOff(xyz, value);
1696 template<
typename ChildT, Index Log2Dim>
1697 template<
typename AccessorT>
1703 bool hasChild = this->isChildMaskOn(n);
1705 const bool active = this->isValueMaskOn(n);
1711 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1715 ChildT* child = mNodes[n].getChild();
1716 acc.insert(xyz, child);
1717 child->setValueOffAndCache(xyz, value, acc);
1722 template<
typename ChildT, Index Log2Dim>
1726 const Index n = this->coordToOffset(xyz);
1727 bool hasChild = this->isChildMaskOn(n);
1729 const bool active = this->isValueMaskOn(n);
1735 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1738 if (hasChild) mNodes[n].getChild()->setValueOn(xyz, value);
1741 template<
typename ChildT, Index Log2Dim>
1742 template<
typename AccessorT>
1747 const Index n = this->coordToOffset(xyz);
1748 bool hasChild = this->isChildMaskOn(n);
1750 const bool active = this->isValueMaskOn(n);
1756 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1760 acc.insert(xyz, mNodes[n].getChild());
1761 mNodes[n].getChild()->setValueAndCache(xyz, value, acc);
1766 template<
typename ChildT, Index Log2Dim>
1770 const Index n = this->coordToOffset(xyz);
1771 bool hasChild = this->isChildMaskOn(n);
1775 const bool active = this->isValueMaskOn(n);
1777 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1779 if (hasChild) mNodes[n].getChild()->setValueOnly(xyz, value);
1782 template<
typename ChildT, Index Log2Dim>
1783 template<
typename AccessorT>
1788 const Index n = this->coordToOffset(xyz);
1789 bool hasChild = this->isChildMaskOn(n);
1793 const bool active = this->isValueMaskOn(n);
1795 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1798 acc.insert(xyz, mNodes[n].getChild());
1799 mNodes[n].getChild()->setValueOnlyAndCache(xyz, value, acc);
1804 template<
typename ChildT, Index Log2Dim>
1808 const Index n = this->coordToOffset(xyz);
1809 bool hasChild = this->isChildMaskOn(n);
1811 if (on != this->isValueMaskOn(n)) {
1816 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1819 if (hasChild) mNodes[n].getChild()->setActiveState(xyz, on);
1822 template<
typename ChildT, Index Log2Dim>
1823 template<
typename AccessorT>
1827 const Index n = this->coordToOffset(xyz);
1828 bool hasChild = this->isChildMaskOn(n);
1830 if (on != this->isValueMaskOn(n)) {
1835 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1839 ChildT* child = mNodes[n].getChild();
1840 acc.insert(xyz, child);
1841 child->setActiveStateAndCache(xyz, on, acc);
1846 template<
typename ChildT, Index Log2Dim>
1850 mValueMask = !mChildMask;
1851 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1852 mNodes[iter.pos()].getChild()->setValuesOn();
1857 template<
typename ChildT, Index Log2Dim>
1858 template<
typename ModifyOp>
1863 bool hasChild = this->isChildMaskOn(n);
1867 const bool active = this->isValueMaskOn(n);
1868 bool createChild = !active;
1872 const ValueType& tileVal = mNodes[n].getValue();
1879 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1882 if (hasChild) mNodes[n].getChild()->modifyValue(xyz, op);
1885 template<
typename ChildT, Index Log2Dim>
1886 template<
typename ModifyOp,
typename AccessorT>
1892 bool hasChild = this->isChildMaskOn(n);
1896 const bool active = this->isValueMaskOn(n);
1897 bool createChild = !active;
1901 const ValueType& tileVal = mNodes[n].getValue();
1908 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1913 acc.insert(xyz, child);
1914 child->modifyValueAndCache(xyz, op, acc);
1919 template<
typename ChildT, Index Log2Dim>
1920 template<
typename ModifyOp>
1925 bool hasChild = this->isChildMaskOn(n);
1927 const bool tileState = this->isValueMaskOn(n);
1928 const ValueType& tileVal = mNodes[n].getValue();
1929 bool modifiedState = !tileState;
1931 op(modifiedVal, modifiedState);
1936 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
1939 if (hasChild) mNodes[n].getChild()->modifyValueAndActiveState(xyz, op);
1942 template<
typename ChildT, Index Log2Dim>
1943 template<
typename ModifyOp,
typename AccessorT>
1946 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
1949 bool hasChild = this->isChildMaskOn(n);
1951 const bool tileState = this->isValueMaskOn(n);
1952 const ValueType& tileVal = mNodes[n].getValue();
1953 bool modifiedState = !tileState;
1955 op(modifiedVal, modifiedState);
1960 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
1965 acc.insert(xyz, child);
1966 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
1974 template<
typename ChildT, Index Log2Dim>
1978 CoordBBox nodeBBox = this->getNodeBoundingBox();
1981 this->fill(nodeBBox, background,
false);
1982 }
else if (clipBBox.
isInside(nodeBBox)) {
1991 for (
Index pos = 0; pos < NUM_VALUES; ++pos) {
1992 const Coord xyz = this->offsetToGlobalCoord(pos);
1997 this->makeChildNodeEmpty(pos, background);
1998 mValueMask.setOff(pos);
1999 }
else if (!clipBBox.
isInside(tileBBox)) {
2002 if (this->isChildMaskOn(pos)) {
2003 mNodes[pos].getChild()->clip(clipBBox, background);
2007 tileBBox.intersect(clipBBox);
2008 const ValueType val = mNodes[pos].getValue();
2009 const bool on = this->isValueMaskOn(pos);
2010 mNodes[pos].setValue(background);
2011 mValueMask.setOff(pos);
2012 this->fill(tileBBox, val, on);
2024 template<
typename ChildT, Index Log2Dim>
2028 auto clippedBBox = this->getNodeBoundingBox();
2029 clippedBBox.intersect(bbox);
2030 if (!clippedBBox)
return;
2034 Coord xyz, tileMin, tileMax;
2035 for (
int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.
x() + 1) {
2037 for (
int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.
y() + 1) {
2039 for (
int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.
z() + 1) {
2043 const Index n = this->coordToOffset(xyz);
2044 tileMin = this->offsetToGlobalCoord(n);
2045 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2051 ChildT* child =
nullptr;
2052 if (this->isChildMaskOff(n)) {
2055 child =
new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)};
2056 this->setChildNode(n, child);
2058 child = mNodes[n].getChild();
2064 child->fill(
CoordBBox(xyz, tmp), value, active);
2071 this->makeChildNodeEmpty(n, value);
2072 mValueMask.set(n, active);
2080 template<
typename ChildT, Index Log2Dim>
2084 auto clippedBBox = this->getNodeBoundingBox();
2085 clippedBBox.intersect(bbox);
2086 if (!clippedBBox)
return;
2090 Coord xyz, tileMin, tileMax;
2091 for (
int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.
x() + 1) {
2093 for (
int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.
y() + 1) {
2095 for (
int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.
z() + 1) {
2099 const auto n = this->coordToOffset(xyz);
2102 ChildT* child =
nullptr;
2103 if (this->isChildMaskOn(n)) {
2104 child = mNodes[n].getChild();
2108 child =
new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)};
2109 this->setChildNode(n, child);
2113 tileMin = this->offsetToGlobalCoord(n);
2114 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2117 child->denseFill(
CoordBBox{xyz, clippedBBox.
max()}, value, active);
2127 template<
typename ChildT, Index Log2Dim>
2128 template<
typename DenseT>
2132 using DenseValueType =
typename DenseT::ValueType;
2134 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2135 const Coord&
min = dense.bbox().min();
2136 for (
Coord xyz = bbox.
min(),
max; xyz[0] <= bbox.
max()[0]; xyz[0] =
max[0] + 1) {
2137 for (xyz[1] = bbox.
min()[1]; xyz[1] <= bbox.
max()[1]; xyz[1] =
max[1] + 1) {
2138 for (xyz[2] = bbox.
min()[2]; xyz[2] <= bbox.
max()[2]; xyz[2] =
max[2] + 1) {
2139 const Index n = this->coordToOffset(xyz);
2141 max = this->offsetToGlobalCoord(n).offsetBy(ChildT::DIM-1);
2146 if (this->isChildMaskOn(n)) {
2147 mNodes[n].getChild()->copyToDense(sub, dense);
2149 const ValueType value = mNodes[n].getValue();
2151 DenseValueType* a0 = dense.data() + zStride*sub.
min()[2];
2152 for (
Int32 x=sub.
min()[0], ex=sub.
max()[0]+1; x<ex; ++x) {
2153 DenseValueType* a1 = a0 + x*xStride;
2154 for (
Int32 y=sub.
min()[1], ey=sub.
max()[1]+1; y<ey; ++y) {
2155 DenseValueType* a2 = a1 + y*yStride;
2157 z < ez; ++z, a2 += zStride)
2159 *a2 = DenseValueType(value);
2173 template<
typename ChildT, Index Log2Dim>
2177 mChildMask.save(os);
2178 mValueMask.save(os);
2182 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[NUM_VALUES]);
2184 const ValueType zero = zeroVal<ValueType>();
2185 for (
Index i = 0;
i < NUM_VALUES; ++
i) {
2186 values[
i] = (mChildMask.isOff(
i) ? mNodes[
i].getValue() : zero);
2192 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2193 iter->writeTopology(os, toHalf);
2198 template<
typename ChildT, Index Log2Dim>
2202 #ifndef OPENVDB_2_ABI_COMPATIBLE 2207 mChildMask.load(is);
2208 mValueMask.load(is);
2211 for (
Index i = 0;
i < NUM_VALUES; ++
i) {
2212 if (this->isChildMaskOn(
i)) {
2214 #ifdef OPENVDB_2_ABI_COMPATIBLE 2219 mNodes[
i].setChild(child);
2220 child->readTopology(is);
2223 is.read(reinterpret_cast<char*>(&value),
sizeof(
ValueType));
2224 mNodes[
i].setValue(value);
2228 const bool oldVersion =
2230 const Index numValues = (oldVersion ? mChildMask.countOff() : NUM_VALUES);
2234 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[numValues]);
2241 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2242 mNodes[iter.pos()].setValue(values[n++]);
2244 assert(n == numValues);
2246 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2247 mNodes[iter.pos()].setValue(values[iter.pos()]);
2252 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2253 #ifdef OPENVDB_2_ABI_COMPATIBLE 2258 mNodes[iter.pos()].setChild(child);
2259 child->readTopology(is, fromHalf);
2268 template<
typename ChildT, Index Log2Dim>
2269 inline const typename ChildT::ValueType&
2272 return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].getValue());
2276 template<
typename ChildT, Index Log2Dim>
2277 inline const typename ChildT::ValueType&
2280 const Index n = NUM_VALUES - 1;
2281 return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].getValue());
2288 template<
typename ChildT, Index Log2Dim>
2292 for (
Index i = 0;
i < NUM_VALUES; ++
i) {
2293 if (this->isChildMaskOn(
i)) {
2294 mNodes[
i].getChild()->negate();
2306 template<
typename ChildT, Index Log2Dim>
2311 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2318 for (
Index i = r.begin(), end=r.end();
i!=end; ++
i) {
2319 if (mNode->mChildMask.isOn(
i)) {
2320 mNode->mNodes[
i].getChild()->voxelizeActiveTiles(
true);
2321 }
else if (mNode->mValueMask.isOn(
i)) {
2322 const Coord &ijk = mNode->offsetToGlobalCoord(
i);
2324 child->voxelizeActiveTiles(
true);
2325 mNode->mNodes[
i].setChild(child);
2332 template<
typename ChildT, Index Log2Dim>
2339 for (
ValueOnIter iter = this->beginValueOn(); iter; ++iter) {
2340 this->setChildNode(iter.pos(),
2343 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter)
2344 iter->voxelizeActiveTiles(
false);
2352 template<
typename ChildT, Index Log2Dim>
2353 template<MergePolicy Policy>
2366 const Index n = iter.pos();
2367 if (mChildMask.isOn(n)) {
2369 mNodes[n].getChild()->template merge<MERGE_ACTIVE_STATES>(*iter,
2370 background, otherBackground);
2371 }
else if (mValueMask.isOff(n)) {
2378 child->resetBackground(otherBackground, background);
2379 this->setChildNode(n, child);
2385 const Index n = iter.pos();
2386 if (mValueMask.isOff(n)) {
2388 this->makeChildNodeEmpty(n, iter.getValue());
2389 mValueMask.setOn(n);
2398 const Index n = iter.pos();
2399 if (mChildMask.isOn(n)) {
2401 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2409 child->resetBackground(otherBackground, background);
2410 this->setChildNode(n, child);
2420 const Index n = iter.pos();
2421 if (mChildMask.isOn(n)) {
2423 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2430 child->resetBackground(otherBackground, background);
2431 if (mValueMask.isOn(n)) {
2433 child->template merge<Policy>(mNodes[n].getValue(),
true);
2434 mValueMask.setOff(n);
2436 mChildMask.setOn(n);
2437 mNodes[n].setChild(child);
2443 const Index n = iter.pos();
2444 if (mChildMask.isOn(n)) {
2446 mNodes[n].getChild()->template merge<Policy>(iter.getValue(),
true);
2447 }
else if (mValueMask.isOff(n)) {
2449 mNodes[n].setValue(iter.getValue());
2450 mValueMask.setOn(n);
2461 template<
typename ChildT, Index Log2Dim>
2462 template<MergePolicy Policy>
2471 if (!tileActive)
return;
2474 for (
ValueOffIter iter = this->beginValueOff(); iter; ++iter) {
2475 const Index n = iter.pos();
2476 if (mChildMask.isOn(n)) {
2478 mNodes[n].getChild()->template merge<Policy>(tileValue,
true);
2481 iter.setValue(tileValue);
2482 mValueMask.setOn(n);
2492 template<
typename ChildT, Index Log2Dim>
2493 template<
typename OtherInternalNode>
2498 { tV = (tV | sV) & ~tC; }
2502 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2505 t->mChildMask |= s->mChildMask;
2507 t->mValueMask.foreach(s->mValueMask, t->mChildMask, op);
2508 assert((t->mValueMask & t->mChildMask).isOff());
2511 for (
Index i = r.begin(), end=r.end();
i!=end; ++
i) {
2512 if (s->mChildMask.isOn(
i)) {
2513 const typename OtherInternalNode::ChildNodeType& other = *(s->mNodes[
i].getChild());
2514 if (t->mChildMask.isOn(
i)) {
2515 t->mNodes[
i].getChild()->topologyUnion(other);
2517 ChildT* child =
new ChildT(other, t->mNodes[
i].getValue(),
TopologyCopy());
2518 if (t->mValueMask.isOn(
i)) child->setValuesOn();
2519 t->mNodes[
i].setChild(child);
2521 }
else if (s->mValueMask.isOn(
i) && t->mChildMask.isOn(
i)) {
2522 t->mNodes[
i].getChild()->setValuesOn();
2526 const OtherInternalNode*
s;
2530 template<
typename ChildT, Index Log2Dim>
2531 template<
typename OtherChildT>
2538 template<
typename ChildT, Index Log2Dim>
2539 template<
typename OtherInternalNode>
2540 struct InternalNode<ChildT, Log2Dim>::TopologyIntersection
2544 { tC = (tC & (sC | sV)) | (tV & sC); }
2547 const ValueType& background) : s(source), t(target), b(background) {
2549 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
2553 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op);
2555 t->mValueMask &= s->mValueMask;
2556 assert((t->mValueMask & t->mChildMask).isOff());
2559 for (
Index i = r.begin(), end=r.end();
i!=end; ++
i) {
2560 if (t->mChildMask.isOn(
i)) {
2561 ChildT* child = t->mNodes[
i].getChild();
2562 if (s->mChildMask.isOn(
i)) {
2563 child->topologyIntersection(*(s->mNodes[
i].getChild()), b);
2564 }
else if (s->mValueMask.isOff(
i)) {
2566 t->mNodes[
i].setValue(b);
2568 }
else if (t->mValueMask.isOn(
i) && s->mChildMask.isOn(
i)) {
2569 t->mNodes[
i].setChild(
new ChildT(*(s->mNodes[
i].getChild()),
2574 const OtherInternalNode*
s;
2579 template<
typename ChildT, Index Log2Dim>
2580 template<
typename OtherChildT>
2588 template<
typename ChildT, Index Log2Dim>
2589 template<
typename OtherInternalNode>
2590 struct InternalNode<ChildT, Log2Dim>::TopologyDifference
2594 { tC = (tC & (sC | ~sV)) | (tV & sC); }
2597 { tV &= ~((tC & sV) | (sC | sV)); }
2600 const ValueType& background) : s(source), t(target), b(background) {
2602 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
2607 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op1);
2610 t->mValueMask.foreach(t->mChildMask, s->mValueMask, oldChildMask, op2);
2611 assert((t->mValueMask & t->mChildMask).isOff());
2614 for (
Index i = r.begin(), end=r.end();
i!=end; ++
i) {
2615 if (t->mChildMask.isOn(
i)) {
2616 ChildT* child = t->mNodes[
i].getChild();
2617 if (s->mChildMask.isOn(
i)) {
2618 child->topologyDifference(*(s->mNodes[
i].getChild()), b);
2619 }
else if (s->mValueMask.isOn(
i)) {
2621 t->mNodes[
i].setValue(b);
2623 }
else if (t->mValueMask.isOn(
i)) {
2624 if (s->mChildMask.isOn(
i)) {
2625 const typename OtherInternalNode::ChildNodeType& other =
2626 *(s->mNodes[
i].getChild());
2627 ChildT* child =
new ChildT(other.origin(), t->mNodes[
i].getValue(),
true);
2628 child->topologyDifference(other, b);
2629 t->mNodes[
i].setChild(child);
2634 const OtherInternalNode*
s;
2639 template<
typename ChildT, Index Log2Dim>
2640 template<
typename OtherChildT>
2652 template<
typename ChildT, Index Log2Dim>
2653 template<
typename CombineOp>
2657 const ValueType zero = zeroVal<ValueType>();
2661 for (
Index i = 0;
i < NUM_VALUES; ++
i) {
2665 op(args.setARef(mNodes[
i].getValue())
2666 .setAIsActive(isValueMaskOn(
i))
2669 mNodes[
i].setValue(args.result());
2670 mValueMask.set(
i, args.resultIsActive());
2687 child->combine(mNodes[
i].getValue(), isValueMaskOn(
i), swappedOp);
2692 this->setChildNode(
i, child);
2698 *child = mNodes[
i].getChild(),
2702 if (child && otherChild) {
2703 child->combine(*otherChild, op);
2710 template<
typename ChildT, Index Log2Dim>
2711 template<
typename CombineOp>
2717 for (
Index i = 0;
i < NUM_VALUES; ++
i) {
2718 if (this->isChildMaskOff(
i)) {
2720 op(args.
setARef(mNodes[
i].getValue())
2721 .setAIsActive(isValueMaskOn(
i))
2723 .setBIsActive(valueIsActive));
2724 mNodes[
i].setValue(args.
result());
2730 if (child) child->combine(value, valueIsActive, op);
2739 template<
typename ChildT, Index Log2Dim>
2740 template<
typename CombineOp,
typename OtherNodeType>
2747 for (
Index i = 0;
i < NUM_VALUES; ++
i) {
2751 .setBRef(other1.mNodes[
i].getValue())
2752 .setBIsActive(other1.isValueMaskOn(
i)));
2754 this->makeChildNodeEmpty(
i, args.
result());
2757 if (this->isChildMaskOff(
i)) {
2761 : other1.mNodes[
i].getChild()->origin();
2762 this->setChildNode(
i,
new ChildNodeType(childOrigin, mNodes[
i].getValue()));
2770 }
else if (other1.isChildMaskOff(
i)) {
2774 other1.mNodes[
i].getValue(), other1.isValueMaskOn(
i), op);
2779 *other1.mNodes[
i].getChild(), op);
2786 template<
typename ChildT, Index Log2Dim>
2787 template<
typename CombineOp,
typename OtherNodeType>
2790 bool valueIsActive, CombineOp& op)
2794 for (
Index i = 0;
i < NUM_VALUES; ++
i) {
2795 if (other.isChildMaskOff(
i)) {
2797 .setAIsActive(valueIsActive)
2798 .setBRef(other.mNodes[
i].getValue())
2799 .setBIsActive(other.isValueMaskOn(
i)));
2801 this->makeChildNodeEmpty(
i, args.
result());
2804 typename OtherNodeType::ChildNodeType* otherChild = other.mNodes[
i].getChild();
2806 if (this->isChildMaskOff(
i)) {
2813 mNodes[
i].getChild()->combine2(value, *otherChild, valueIsActive, op);
2819 template<
typename ChildT, Index Log2Dim>
2820 template<
typename CombineOp,
typename OtherValueType>
2823 bool valueIsActive, CombineOp& op)
2827 for (
Index i = 0;
i < NUM_VALUES; ++
i) {
2832 .setBIsActive(valueIsActive));
2834 this->makeChildNodeEmpty(
i, args.
result());
2839 if (this->isChildMaskOff(
i)) {
2841 this->setChildNode(
i,
2846 mNodes[
i].getChild()->combine2(*otherChild, value, valueIsActive, op);
2855 template<
typename ChildT, Index Log2Dim>
2856 template<
typename BBoxOp>
2867 if (op.template descent<LEVEL>()) {
2868 for (
ChildOnCIter i = this->cbeginChildOn();
i; ++
i)
i->visitActiveBBox(op);
2872 op.operator()<LEVEL>(
i->getNodeBoundingBox());
2874 op.template operator()<LEVEL>(
i->getNodeBoundingBox());
2881 template<
typename ChildT, Index Log2Dim>
2882 template<
typename VisitorOp>
2886 doVisit<InternalNode, VisitorOp, ChildAllIter>(*
this, op);
2890 template<
typename ChildT, Index Log2Dim>
2891 template<
typename VisitorOp>
2895 doVisit<const InternalNode, VisitorOp, ChildAllCIter>(*
this, op);
2899 template<
typename ChildT, Index Log2Dim>
2900 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
2904 typename NodeT::ValueType val;
2905 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
2906 if (op(iter))
continue;
2907 if (
typename ChildAllIterT::ChildNodeType* child = iter.probeChild(val)) {
2917 template<
typename ChildT, Index Log2Dim>
2918 template<
typename OtherNodeType,
typename VisitorOp>
2923 typename OtherNodeType::ChildAllIter>(*
this, other, op);
2927 template<
typename ChildT, Index Log2Dim>
2928 template<
typename OtherNodeType,
typename VisitorOp>
2933 typename OtherNodeType::ChildAllCIter>(*
this, other, op);
2937 template<
typename ChildT, Index Log2Dim>
2940 typename OtherNodeT,
2942 typename ChildAllIterT,
2943 typename OtherChildAllIterT>
2948 static_assert(OtherNodeT::NUM_VALUES == NodeT::NUM_VALUES,
2949 "visit2() requires nodes to have the same dimensions");
2950 static_assert(OtherNodeT::LEVEL == NodeT::LEVEL,
2951 "visit2() requires nodes to be at the same tree level");
2953 typename NodeT::ValueType val;
2954 typename OtherNodeT::ValueType otherVal;
2956 ChildAllIterT iter =
self.beginChildAll();
2957 OtherChildAllIterT otherIter = other.beginChildAll();
2959 for ( ; iter && otherIter; ++iter, ++otherIter)
2961 const size_t skipBranch =
static_cast<size_t>(op(iter, otherIter));
2963 typename ChildAllIterT::ChildNodeType* child =
2964 (skipBranch & 1U) ?
nullptr : iter.probeChild(val);
2965 typename OtherChildAllIterT::ChildNodeType* otherChild =
2966 (skipBranch & 2U) ?
nullptr : otherIter.probeChild(otherVal);
2968 if (child !=
nullptr && otherChild !=
nullptr) {
2969 child->visit2Node(*otherChild, op);
2970 }
else if (child !=
nullptr) {
2971 child->visit2(otherIter, op);
2972 }
else if (otherChild !=
nullptr) {
2973 otherChild->visit2(iter, op,
true);
2982 template<
typename ChildT, Index Log2Dim>
2983 template<
typename OtherChildAllIterType,
typename VisitorOp>
2986 VisitorOp& op,
bool otherIsLHS)
2988 doVisit2<InternalNode, VisitorOp, ChildAllIter, OtherChildAllIterType>(
2989 *
this, otherIter, op, otherIsLHS);
2993 template<
typename ChildT, Index Log2Dim>
2994 template<
typename OtherChildAllIterType,
typename VisitorOp>
2997 VisitorOp& op,
bool otherIsLHS)
const 2999 doVisit2<const InternalNode, VisitorOp, ChildAllCIter, OtherChildAllIterType>(
3000 *
this, otherIter, op, otherIsLHS);
3004 template<
typename ChildT, Index Log2Dim>
3005 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT,
typename OtherChildAllIterT>
3008 VisitorOp& op,
bool otherIsLHS)
3010 if (!otherIter)
return;
3012 const size_t skipBitMask = (otherIsLHS ? 2U : 1U);
3014 typename NodeT::ValueType val;
3015 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
3016 const size_t skipBranch =
static_cast<size_t>(
3017 otherIsLHS ? op(otherIter, iter) : op(iter, otherIter));
3019 typename ChildAllIterT::ChildNodeType* child =
3020 (skipBranch & skipBitMask) ?
nullptr : iter.probeChild(val);
3022 if (child !=
nullptr) child->visit2(otherIter, op, otherIsLHS);
3030 template<
typename ChildT, Index Log2Dim>
3034 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3035 iter->writeBuffers(os, toHalf);
3040 template<
typename ChildT, Index Log2Dim>
3044 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3045 iter->readBuffers(is, fromHalf);
3050 template<
typename ChildT, Index Log2Dim>
3053 const CoordBBox& clipBBox,
bool fromHalf)
3055 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3060 iter->readBuffers(is, clipBBox, fromHalf);
3064 ValueType background = zeroVal<ValueType>();
3066 background = *
static_cast<const ValueType*
>(bgPtr);
3068 this->
clip(clipBBox, background);
3075 template<
typename ChildT, Index Log2Dim>
3079 dims.push_back(Log2Dim);
3080 ChildNodeType::getNodeLog2Dims(dims);
3084 template<
typename ChildT, Index Log2Dim>
3088 assert(n<(1<<3*Log2Dim));
3089 xyz.
setX(n >> 2*Log2Dim);
3090 n &= ((1<<2*Log2Dim)-1);
3091 xyz.
setY(n >> Log2Dim);
3092 xyz.
setZ(n & ((1<<Log2Dim)-1));
3096 template<
typename ChildT, Index Log2Dim>
3100 return (((xyz[0] & (DIM-1u)) >> ChildNodeType::TOTAL) << 2*Log2Dim)
3101 + (((xyz[1] & (DIM-1u)) >> ChildNodeType::TOTAL) << Log2Dim)
3102 + ((xyz[2] & (DIM-1u)) >> ChildNodeType::TOTAL);
3106 template<
typename ChildT, Index Log2Dim>
3111 this->offsetToLocalCoord(n, local);
3112 local <<= ChildT::TOTAL;
3113 return local + this->origin();
3120 template<
typename ChildT, Index Log2Dim>
3121 template<
typename ArrayT>
3125 using T =
typename ArrayT::value_type;
3126 static_assert(std::is_pointer<T>::value,
"argument to getNodes() must be a pointer array");
3127 using ArrayChildT =
typename std::conditional<
3128 std::is_const<typename std::remove_pointer<T>::type>::value,
const ChildT, ChildT>::type;
3129 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3131 if (std::is_same<T, ArrayChildT*>::value) {
3132 array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild()));
3134 iter->getNodes(array);
3140 template<
typename ChildT, Index Log2Dim>
3141 template<
typename ArrayT>
3145 using T =
typename ArrayT::value_type;
3146 static_assert(std::is_pointer<T>::value,
"argument to getNodes() must be a pointer array");
3147 static_assert(std::is_const<
typename std::remove_pointer<T>::type>::value,
3148 "argument to getNodes() must be an array of const node pointers");
3149 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3151 if (std::is_same<T, const ChildT*>::value) {
3152 array.push_back(reinterpret_cast<T>(mNodes[iter.pos()].getChild()));
3154 iter->getNodes(array);
3164 template<
typename ChildT, Index Log2Dim>
3165 template<
typename ArrayT>
3169 using T =
typename ArrayT::value_type;
3170 static_assert(std::is_pointer<T>::value,
"argument to stealNodes() must be a pointer array");
3171 using ArrayChildT =
typename std::conditional<
3172 std::is_const<typename std::remove_pointer<T>::type>::value,
const ChildT, ChildT>::type;
3174 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
3175 const Index n = iter.pos();
3176 if (std::is_same<T, ArrayChildT*>::value) {
3177 array.push_back(reinterpret_cast<T>(mNodes[n].getChild()));
3178 mValueMask.set(n, state);
3179 mNodes[n].setValue(value);
3181 iter->stealNodes(array, value, state);
3184 if (std::is_same<T, ArrayChildT*>::value) mChildMask.setOff();
3192 template<
typename ChildT, Index Log2Dim>
3198 for (
Index i = 0;
i < NUM_VALUES; ++
i) {
3199 if (this->isChildMaskOn(
i)) {
3200 mNodes[
i].getChild()->resetBackground(oldBackground, newBackground);
3201 }
else if (this->isValueMaskOff(
i)) {
3203 mNodes[
i].setValue(newBackground);
3211 template<
typename ChildT, Index Log2Dim>
3212 template<
typename OtherChildNodeType, Index OtherLog2Dim>
3217 if (Log2Dim != OtherLog2Dim || mChildMask != other->
mChildMask ||
3218 mValueMask != other->
mValueMask)
return false;
3219 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3220 if (!iter->hasSameTopology(other->
mNodes[iter.pos()].getChild()))
return false;
3226 template<
typename ChildT, Index Log2Dim>
3231 if (this->isChildMaskOn(
i)) {
3232 delete mNodes[
i].getChild();
3234 mChildMask.setOn(
i);
3235 mValueMask.setOff(
i);
3237 mNodes[
i].setChild(child);
3240 template<
typename ChildT, Index Log2Dim>
3245 assert(mChildMask.isOff(
i));
3246 mChildMask.setOn(
i);
3247 mValueMask.setOff(
i);
3248 mNodes[
i].setChild(child);
3252 template<
typename ChildT, Index Log2Dim>
3256 if (this->isChildMaskOff(
i)) {
3257 mNodes[
i].setValue(value);
3261 mChildMask.setOff(
i);
3262 mNodes[
i].setValue(value);
3267 template<
typename ChildT, Index Log2Dim>
3271 delete this->unsetChildNode(n, value);
3274 template<
typename ChildT, Index Log2Dim>
3278 assert(this->isChildMaskOn(n));
3279 return mNodes[n].getChild();
3283 template<
typename ChildT, Index Log2Dim>
3284 inline const ChildT*
3287 assert(this->isChildMaskOn(n));
3288 return mNodes[n].getChild();
3295 #endif // OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition: Coord.h:115
bool isValueMaskOff(Index n) const
Definition: InternalNode.h:779
bool hasActiveTiles() const
Return true if this node or any of its child nodes have any active tiles.
Definition: InternalNode.h:1538
Index64 onLeafVoxelCount() const
Definition: InternalNode.h:1081
Base class for sparse iterators over internal and leaf nodes.
Definition: Iterator.h:143
Level getLevel()
Return the current logging level.
Definition: logging.h:164
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition: InternalNode.h:1647
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
Definition: InternalNode.h:2543
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...
TopologyDifference(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:2599
const ValueT & getValue() const
Definition: NodeUnion.h:71
LeafNodeType * touchLeafAndCache(const Coord &xyz, AccessorT &)
Same as touchLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
void addLeaf(LeafNodeType *leaf)
Add the specified leaf to this node, possibly creating a child branch in the process. If the leaf node already exists, replace it.
Definition: InternalNode.h:1318
void resetChildNode(Index i, ChildNodeType *child)
Definition: InternalNode.h:3228
TopologyCopy2(const OtherInternalNode *source, InternalNode *target, const ValueType &offValue, const ValueType &onValue)
Definition: InternalNode.h:982
Int32 z() const
Definition: Coord.h:156
_ChildNodeType ChildNodeType
Definition: InternalNode.h:63
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
TopologyUnion(const OtherInternalNode *source, InternalNode *target)
Definition: InternalNode.h:2500
Coord & setZ(Int32 z)
Definition: Coord.h:105
void readBuffers(std::istream &, bool fromHalf=false)
Definition: InternalNode.h:3042
bool isEmpty() const
Definition: InternalNode.h:322
Definition: InternalNode.h:199
Definition: InternalNode.h:832
NodeMaskType mChildMask
Definition: InternalNode.h:837
ValueOffCIter cbeginValueOff() const
Definition: InternalNode.h:261
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:58
const NodeType * probeConstNode(const Coord &xyz) const
Return a pointer to the node that contains voxel (x, y, z). If no such node exists, return nullptr.
const ValueType & b
Definition: InternalNode.h:2636
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2613
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:987
DenseIter()
Definition: InternalNode.h:205
Int32 y() const
Definition: Coord.h:155
ChildAllCIter cbeginChildAll() const
Definition: InternalNode.h:251
const OtherInternalNode * s
Definition: InternalNode.h:2634
uint32_t Index32
Definition: Types.h:55
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:391
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:3167
Definition: InternalNode.h:2497
ChildOffIter beginChildOff()
Definition: InternalNode.h:256
static void doVisit2Node(NodeT &, OtherNodeT &, VisitorOp &)
Definition: InternalNode.h:2945
const NodeMaskType & getChildMask() const
Definition: InternalNode.h:785
ChildAllIter beginChildAll()
Definition: InternalNode.h:257
tbb::atomic< Index32 > i
Definition: LeafBuffer.h:71
NodeType * probeNodeAndCache(const Coord &xyz, AccessorT &)
Same as probeNode() except, if necessary, update the accessor with pointers to the nodes along the pa...
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:354
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition: InternalNode.h:1922
ChildT & getItem(Index pos) const
Definition: InternalNode.h:163
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1699
void modifyItem(Index pos, const ModifyOp &op) const
Definition: InternalNode.h:191
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:1458
InternalNode * t
Definition: InternalNode.h:2635
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:1597
ChildIter()
Definition: InternalNode.h:159
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:261
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:1888
UnionType mNodes[NUM_VALUES]
Definition: InternalNode.h:833
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:419
void topologyDifference(const InternalNode< OtherChildNodeType, Log2Dim > &other, const ValueType &background)
Difference this node's set of active values with the active values of the other node, whose ValueType may be different. So a resulting voxel will be active only if the original voxel is active in this node and inactive in the other node.
ChildOnIter beginChildOn()
Definition: InternalNode.h:255
Definition: InternalNode.h:2307
ValueConverter<T>::Type is the type of an InternalNode having the same child hierarchy and dimensions...
Definition: InternalNode.h:82
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:1146
const OtherInternalNode * s
Definition: InternalNode.h:961
bool probeValue(const Coord &xyz, ValueType &value) const
Definition: InternalNode.h:1619
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
Index32 nonLeafCount() const
Definition: InternalNode.h:1044
Definition: InternalNode.h:2593
Index32 Index
Definition: Types.h:57
Definition: NodeMasks.h:270
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:319
Tag dispatch class that distinguishes constructors during file input.
Definition: Types.h:505
NodeMaskType mValueMask
Definition: InternalNode.h:837
void setValuesOn()
Mark all values (both tiles and voxels) as active.
Definition: InternalNode.h:1848
InternalNode * t
Definition: InternalNode.h:916
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Definition: InternalNode.h:1563
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:2026
Definition: InternalNode.h:149
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition: InternalNode.h:3098
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:1347
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Definition: InternalNode.h:355
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:906
const ValueType & getFirstValue() const
If the first entry in this node's table is a tile, return the tile's value. Otherwise, return the result of calling getFirstValue() on the child.
Definition: InternalNode.h:2270
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:1128
void setItem(Index pos, const ValueT &v) const
Definition: InternalNode.h:187
const ValueType & b
Definition: InternalNode.h:963
Definition: InternalNode.h:831
static Index dim()
Definition: InternalNode.h:275
const NodeMaskType & getValueMask() const
Definition: InternalNode.h:784
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition: InternalNode.h:1553
LeafNodeType * probeLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return nullptr.
Definition: InternalNode.h:1272
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:2130
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...
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:2355
NodeMaskType getValueOffMask() const
Definition: InternalNode.h:786
void writeCompressedValues(std::ostream &os, ValueT *srcBuf, Index srcCount, const MaskT &valueMask, const MaskT &childMask, bool toHalf)
Definition: Compression.h:462
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:1860
void operator()(W &tV, const W &sC, const W &sV, const W &tC) const
Definition: InternalNode.h:2596
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition: InternalNode.h:1945
typename NodeMaskType::Word W
Definition: InternalNode.h:2496
const UnionType * getTable() const
Definition: InternalNode.h:793
typename ChildNodeType::ValueType ValueType
Definition: InternalNode.h:65
void setItem(Index pos, const ChildT &c) const
Definition: InternalNode.h:170
const AValueType & result() const
Get the output value.
Definition: Types.h:416
bool isChildMaskOn(Index n) const
Definition: InternalNode.h:781
Definition: InternalNode.h:830
uint64_t Index64
Definition: Types.h:56
Definition: InternalNode.h:833
const ValueType & onV
Definition: InternalNode.h:999
static Index getChildDim()
Definition: InternalNode.h:285
#define OPENVDB_VERSION_NAME
Definition: version.h:43
void toggle(Index32 n)
Toggle the state of the nth bit.
Definition: NodeMasks.h:483
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1785
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
Definition: InternalNode.h:2593
bool isValueMaskOn(Index n) const
Definition: InternalNode.h:777
void translate(const Coord &t)
Translate this bounding box by .
Definition: Coord.h:458
bool isChildMaskOff() const
Definition: InternalNode.h:783
ChildOnCIter cbeginChildOn() const
Definition: InternalNode.h:249
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, return nullptr.
Definition: InternalNode.h:1298
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:108
void readTopology(std::istream &, bool fromHalf=false)
Definition: InternalNode.h:2200
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
Definition: InternalNode.h:1115
ValueAllCIter cbeginValueAll() const
Definition: InternalNode.h:262
Index64 onTileCount() const
Definition: InternalNode.h:1104
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2510
Definition: InternalNode.h:828
typename ChildNodeType::BuildType BuildType
Definition: InternalNode.h:66
typename NodeMaskType::OffIterator MaskOffIterator
Definition: InternalNode.h:144
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:1606
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...
Definition: InternalNode.h:2596
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Definition: InternalNode.h:1632
const OtherInternalNode * s
Definition: InternalNode.h:2574
void readCompressedValues(std::istream &is, ValueT *destBuf, Index destCount, const MaskT &valueMask, bool fromHalf)
Definition: Compression.h:339
InternalNode * t
Definition: InternalNode.h:2527
ChildAllCIter beginChildAll() const
Definition: InternalNode.h:254
Index32 leafCount() const
Definition: InternalNode.h:1031
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of an Intern...
Definition: InternalNode.h:91
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition: InternalNode.h:2334
static Coord max()
Return the largest possible coordinate.
Definition: Coord.h:70
static void doVisit(NodeT &, VisitorOp &)
Definition: InternalNode.h:2902
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:3194
bool isInside(const Coord &xyz) const
Return true if point (x, y, z) is inside this bounding box.
Definition: Coord.h:401
Definition: Exceptions.h:39
Coord & setX(Int32 x)
Definition: Coord.h:103
bool isInactive() const
Return true if this node has no children and only contains inactive values.
Definition: InternalNode.h:350
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:3214
ValueOffIter beginValueOff()
Definition: InternalNode.h:269
InternalNode * t
Definition: InternalNode.h:962
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition: Coord.h:199
ValueIter()
Definition: InternalNode.h:180
Definition: version.h:110
bool isConstant(ValueType &firstValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
Definition: InternalNode.h:1491
void visit(VisitorOp &)
Definition: InternalNode.h:2884
const Coord & max() const
Definition: Coord.h:335
void unsetItem(Index pos, const ValueT &value) const
Definition: InternalNode.h:227
Definition: NodeMasks.h:239
ValueOnCIter cbeginValueOn() const
Definition: InternalNode.h:259
Definition: InternalNode.h:177
bool resultIsActive() const
Definition: Types.h:435
bool getItem(Index pos, ChildT *&child, NonConstValueT &value) const
Definition: InternalNode.h:209
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition: Types.h:371
Definition: version.h:101
typename NodeMaskType::OnIterator MaskOnIterator
Definition: InternalNode.h:143
Definition: InternalNode.h:148
void clip(const CoordBBox &, const ValueType &background)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition: InternalNode.h:1976
ValueIter(const MaskIterT &iter, NodeT *parent)
Definition: InternalNode.h:181
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:1768
Definition: InternalNode.h:829
virtual ~InternalNode()
Definition: InternalNode.h:1018
Definition: InternalNode.h:148
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Definition: InternalNode.h:1825
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition: InternalNode.h:1663
void topologyIntersection(const InternalNode< OtherChildNodeType, Log2Dim > &other, const ValueType &background)
Intersects this tree's set of active values with the active values of the other tree, whose ValueType may be different.
typename NodeMaskType::Word W
Definition: InternalNode.h:2592
typename BaseT::NonConstValueType NonConstValueT
Definition: InternalNode.h:203
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
void writeTopology(std::ostream &, bool toHalf=false) const
Definition: InternalNode.h:2175
ValueOnIter beginValueOn()
Definition: InternalNode.h:267
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition: Types.h:424
void setItem(Index pos, ChildT *child) const
Definition: InternalNode.h:221
void combine2(const InternalNode &other0, const OtherNodeType &other1, CombineOp &)
Definition: InternalNode.h:2742
static void doVisit2(NodeT &, OtherChildAllIterT &, VisitorOp &, bool otherIsLHS)
Definition: InternalNode.h:3007
Index64 offVoxelCount() const
Definition: InternalNode.h:1069
ValueAllIter beginValueAll()
Definition: InternalNode.h:270
ChildNodeType * unsetChildNode(Index i, const ValueType &value)
Definition: InternalNode.h:3254
static CoordBBox createCube(const Coord &min, ValueType dim)
Definition: Coord.h:326
typename NodeMaskType::Word W
Definition: InternalNode.h:2542
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:2082
void visit2(IterT &otherIter, VisitorOp &, bool otherIsLHS=false)
void combine(InternalNode &other, CombineOp &)
Definition: InternalNode.h:2655
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:1422
TopologyCopy1(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:946
VoxelizeActiveTiles(InternalNode &node)
Definition: InternalNode.h:2309
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...
Int32 x() const
Definition: Coord.h:154
ChildOffCIter beginChildOff() const
Definition: InternalNode.h:253
ValueOnCIter beginValueOn() const
Definition: InternalNode.h:263
Definition: NodeMasks.h:208
NodeType * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists, return nullptr.
InternalNode * t
Definition: InternalNode.h:2575
ValueOffCIter beginValueOff() const
Definition: InternalNode.h:265
TopologyIntersection(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition: InternalNode.h:2546
DeepCopy(const OtherInternalNode *source, InternalNode *target)
Definition: InternalNode.h:902
Index64 Word
Definition: NodeMasks.h:316
ChildNodeType * getChildNode(Index n)
Returns a pointer to the child node at the linear offset n.
Definition: InternalNode.h:3276
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:3077
ValueAllCIter beginValueAll() const
Definition: InternalNode.h:266
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:951
const ValueType & b
Definition: InternalNode.h:2576
Index64 offLeafVoxelCount() const
Definition: InternalNode.h:1093
DenseIter(const MaskDenseIterator &iter, NodeT *parent)
Definition: InternalNode.h:206
const ValueT & getItem(Index pos) const
Definition: InternalNode.h:184
bool isValueMaskOff() const
Definition: InternalNode.h:780
InternalNode()
Default constructor.
Definition: InternalNode.h:99
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:503
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:48
Definition: InternalNode.h:149
void negate()
Change the sign of all the values represented in this node and its child nodes.
Definition: InternalNode.h:2290
const ValueType & getLastValue() const
If the last entry in this node's table is a tile, return the tile's value. Otherwise, return the result of calling getLastValue() on the child.
Definition: InternalNode.h:2278
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
int32_t Int32
Definition: Types.h:59
static const Index NUM_VALUES
Definition: InternalNode.h:74
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:3086
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
Definition: NodeMasks.h:307
InternalNode * mNode
Definition: InternalNode.h:2329
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2316
ChildOffCIter cbeginChildOff() const
Definition: InternalNode.h:250
bool isValueMaskOn() const
Definition: InternalNode.h:778
void setValue(const ValueT &val)
Definition: NodeUnion.h:73
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
const OtherInternalNode * s
Definition: InternalNode.h:997
ChildIter(const MaskIterT &iter, NodeT *parent)
Definition: InternalNode.h:160
void operator()(const tbb::blocked_range< Index > &r) const
Definition: InternalNode.h:2558
const OtherInternalNode * s
Definition: InternalNode.h:2526
Index64 onVoxelCount() const
Definition: InternalNode.h:1057
Coord & setY(Int32 y)
Definition: Coord.h:104
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition: InternalNode.h:1744
ChildOnCIter beginChildOn() const
Definition: InternalNode.h:252
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:1170
static bool lessThan(const Coord &a, const Coord &b)
Definition: Coord.h:232
const Coord & min() const
Definition: Coord.h:334
static Index getLevel()
Definition: InternalNode.h:278
void makeChildNodeEmpty(Index n, const ValueType &value)
Definition: InternalNode.h:3269
void setChildNode(Index i, ChildNodeType *child)
Definition: InternalNode.h:3242
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Definition: InternalNode.h:3108
void visit2Node(OtherNodeType &other, VisitorOp &)
Definition: InternalNode.h:2920
ChildT * getChild() const
Definition: NodeUnion.h:68
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
Definition: InternalNode.h:298
Definition: InternalNode.h:2543
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition: InternalNode.h:3123
void operator()(W &tV, const W &sV, const W &tC) const
Definition: InternalNode.h:2497
Definition: InternalNode.h:60
void setOff(Index32 n)
Set the nth bit off.
Definition: NodeMasks.h:457
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition: Coord.h:413
typename NodeMaskType::DenseIterator MaskDenseIterator
Definition: InternalNode.h:145
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:1806
void setOn(Index32 n)
Set the nth bit on.
Definition: NodeMasks.h:452
void writeBuffers(std::ostream &, bool toHalf=false) const
Definition: InternalNode.h:3032
Definition: InternalNode.h:156
boost::remove_const< UnsetItemT >::type NonConstValueType
Definition: Iterator.h:212
typename ChildNodeType::LeafNodeType LeafNodeType
Definition: InternalNode.h:64
void visitActiveBBox(BBoxOp &) const
Calls the templated functor BBoxOp with bounding box information for all active tiles and leaf nodes ...
Definition: InternalNode.h:2858
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition: InternalNode.h:296
InternalNode * t
Definition: InternalNode.h:998
Coord mOrigin
Global grid index coordinates (x,y,z) of the local origin of this node.
Definition: InternalNode.h:839
Base class for dense iterators over internal and leaf nodes.
Definition: Iterator.h:206
const ValueType & getValue(const Coord &xyz) const
Definition: InternalNode.h:1574
bool isChildMaskOff(Index n) const
Definition: InternalNode.h:782
Definition: InternalNode.h:56
const OtherInternalNode * s
Definition: InternalNode.h:915
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:1390