8#ifndef OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
9#define OPENVDB_TREE_INTERNALNODE_HAS_BEEN_INCLUDED
15#include <openvdb/version.h>
19#include <tbb/parallel_for.h>
29template<
typename, Index,
typename>
struct SameInternalConfig;
32template<
typename _ChildNodeType, Index Log2Dim>
38 using ValueType =
typename ChildNodeType::ValueType;
39 using BuildType =
typename ChildNodeType::BuildType;
45 TOTAL = Log2Dim + ChildNodeType::TOTAL,
47 NUM_VALUES = 1 << (3 * Log2Dim),
48 LEVEL = 1 + ChildNodeType::LEVEL;
50 NUM_VOXELS = uint64_t(1) << (3 * TOTAL);
54 template<
typename OtherValueType>
57 OtherValueType>::Type, Log2Dim>;
63 template<
typename OtherNodeType>
65 static const bool value =
82 InternalNode(
const Coord& origin,
const ValueType& fillValue,
bool active =
false);
94 template<
typename OtherChildNodeType>
100 template<
typename OtherChildNodeType>
107 template<
typename OtherChildNodeType>
109 const ValueType& offValue,
const ValueType& onValue,
TopologyCopy);
126 template<
typename NodeT,
typename ChildT,
typename MaskIterT,
typename TagT>
128 MaskIterT, ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>
132 MaskIterT,
ChildIter<NodeT, ChildT, MaskIterT, TagT>, NodeT, ChildT>(iter, parent) {}
136 assert(this->parent().isChildMaskOn(pos));
137 return *(this->parent().getChildNode(pos));
141 void setItem(
Index pos,
const ChildT& c)
const { this->parent().resetChildNode(pos, &c); }
147 template<
typename NodeT,
typename ValueT,
typename MaskIterT,
typename TagT>
149 MaskIterT, ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>
153 MaskIterT,
ValueIter<NodeT, ValueT, MaskIterT, TagT>, NodeT, ValueT>(iter, parent) {}
155 const ValueT&
getItem(
Index pos)
const {
return this->parent().mNodes[pos].getValue(); }
158 void setItem(
Index pos,
const ValueT& v)
const { this->parent().mNodes[pos].setValue(v); }
161 template<
typename ModifyOp>
164 op(this->parent().mNodes[pos].getValue());
169 template<
typename NodeT,
typename ChildT,
typename ValueT,
typename TagT>
171 MaskDenseIterator, DenseIter<NodeT, ChildT, ValueT, TagT>, NodeT, ChildT, ValueT>
182 if (this->parent().isChildMaskOn(pos)) {
183 child = this->parent().getChildNode(pos);
187 value = this->parent().mNodes[pos].getValue();
194 this->parent().resetChildNode(pos, child);
200 this->parent().unsetChildNode(pos, value);
252 static void getNodeLog2Dims(std::vector<Index>& dims);
262 static void offsetToLocalCoord(
Index n,
Coord& xyz);
277 void nodeCount(std::vector<Index32> &vec)
const;
282 Index64 onLeafVoxelCount()
const;
283 Index64 offLeafVoxelCount()
const;
293 void evalActiveBoundingBox(
CoordBBox& bbox,
bool visitVoxels =
true)
const;
300 bool isEmpty()
const {
return mChildMask.isOff(); }
307 bool isConstant(ValueType& firstValue,
bool& state,
308 const ValueType& tolerance = zeroVal<ValueType>())
const;
324 bool isConstant(ValueType& minValue, ValueType& maxValue,
325 bool& state,
const ValueType& tolerance = zeroVal<ValueType>())
const;
328 bool isInactive()
const {
return this->isChildMaskOff() && this->isValueMaskOff(); }
331 bool isValueOn(
const Coord& xyz)
const;
336 bool hasActiveTiles()
const;
338 const ValueType& getValue(
const Coord& xyz)
const;
339 bool probeValue(
const Coord& xyz, ValueType& value)
const;
347 const ValueType& getFirstValue()
const;
350 const ValueType& getLastValue()
const;
353 void setActiveState(
const Coord& xyz,
bool on);
355 void setValueOnly(
const Coord& xyz,
const ValueType& value);
357 void setValueOn(
const Coord& xyz);
359 void setValueOn(
const Coord& xyz,
const ValueType& value);
361 void setValueOff(
const Coord& xyz);
363 void setValueOff(
const Coord& xyz,
const ValueType& value);
367 template<
typename ModifyOp>
368 void modifyValue(
const Coord& xyz,
const ModifyOp& op);
370 template<
typename ModifyOp>
371 void modifyValueAndActiveState(
const Coord& xyz,
const ModifyOp& op);
377 template<
typename AccessorT>
384 template<
typename AccessorT>
385 bool isValueOnAndCache(
const Coord& xyz, AccessorT&)
const;
391 template<
typename AccessorT>
392 void setValueAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
398 template<
typename AccessorT>
399 void setValueOnlyAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
406 template<
typename ModifyOp,
typename AccessorT>
407 void modifyValueAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
413 template<
typename ModifyOp,
typename AccessorT>
414 void modifyValueAndActiveStateAndCache(
const Coord& xyz,
const ModifyOp& op, AccessorT&);
420 template<
typename AccessorT>
421 void setValueOffAndCache(
const Coord& xyz,
const ValueType& value, AccessorT&);
427 template<
typename AccessorT>
428 void setActiveStateAndCache(
const Coord& xyz,
bool on, AccessorT&);
435 template<
typename AccessorT>
436 bool probeValueAndCache(
const Coord& xyz,
ValueType& value, AccessorT&)
const;
444 template<
typename AccessorT>
445 Index getValueLevelAndCache(
const Coord& xyz, AccessorT&)
const;
453 void writeTopology(std::ostream&,
bool toHalf =
false)
const;
454 void readTopology(std::istream&,
bool fromHalf =
false);
455 void writeBuffers(std::ostream&,
bool toHalf =
false)
const;
456 void readBuffers(std::istream&,
bool fromHalf =
false);
457 void readBuffers(std::istream&,
const CoordBBox&,
bool fromHalf =
false);
489 void voxelizeActiveTiles(
bool threaded =
true);
498 template<
typename DenseT>
499 void copyToDense(
const CoordBBox& bbox, DenseT& dense)
const;
503 template<MergePolicy Policy>
508 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive);
522 template<
typename OtherChildNodeType>
538 template<
typename OtherChildNodeType>
553 template<
typename OtherChildNodeType>
557 template<
typename CombineOp>
559 template<
typename CombineOp>
560 void combine(
const ValueType& value,
bool valueIsActive, CombineOp&);
562 template<
typename CombineOp,
typename OtherNodeType >
563 void combine2(
const InternalNode& other0,
const OtherNodeType& other1, CombineOp&);
564 template<
typename CombineOp,
typename OtherNodeType >
565 void combine2(
const ValueType& value,
const OtherNodeType& other,
bool valIsActive, CombineOp&);
566 template<
typename CombineOp,
typename OtherValueType>
567 void combine2(
const InternalNode& other,
const OtherValueType&,
bool valIsActive, CombineOp&);
575 void prune(
const ValueType& tolerance = zeroVal<ValueType>());
583 template<
typename AccessorT>
594 template<
typename NodeT>
595 NodeT* stealNode(
const Coord& xyz,
const ValueType& value,
bool state);
614 template<
typename AccessorT>
615 void addTileAndCache(
Index level,
const Coord& xyz,
const ValueType&,
bool state, AccessorT&);
627 template<
typename NodeType,
typename AccessorT>
629 template<
typename NodeType,
typename AccessorT>
644 template<
typename AccessorT>
646 template<
typename AccessorT>
648 template<
typename AccessorT>
662 template<
typename AccessorT>
688 template<
typename ArrayT>
689 void getNodes(ArrayT& array);
690 template<
typename ArrayT>
691 void getNodes(ArrayT& array)
const;
717 template<
typename ArrayT>
718 void stealNodes(ArrayT& array,
const ValueType& value,
bool state);
726 template<
typename OtherChildNodeType, Index OtherLog2Dim>
768 void makeChildNodeEmpty(
Index n,
const ValueType& value);
769 void setChildNode(
Index i, ChildNodeType* child);
770 void resetChildNode(
Index i, ChildNodeType* child);
771 ChildNodeType* unsetChildNode(
Index i,
const ValueType& value);
777 ChildNodeType* getChildNode(
Index n);
778 const ChildNodeType* getChildNode(
Index n)
const;
783 struct VoxelizeActiveTiles;
784 template<
typename OtherInternalNode>
struct DeepCopy;
785 template<
typename OtherInternalNode>
struct TopologyCopy1;
786 template<
typename OtherInternalNode>
struct TopologyCopy2;
787 template<
typename OtherInternalNode>
struct TopologyUnion;
788 template<
typename OtherInternalNode>
struct TopologyDifference;
789 template<
typename OtherInternalNode>
struct TopologyIntersection;
807template<
typename ChildT1, Index Dim1,
typename NodeT2>
809 static const bool value =
false;
812template<
typename ChildT1, Index Dim1,
typename ChildT2>
814 static const bool value = ChildT1::template SameConfiguration<ChildT2>::value;
822template<
typename ChildT, Index Log2Dim>
826 for (
Index i = 0; i < NUM_VALUES; ++i) mNodes[i].setValue(background);
830template<
typename ChildT, Index Log2Dim>
833 mOrigin(origin[0] & ~(DIM - 1),
834 origin[1] & ~(DIM - 1),
835 origin[2] & ~(DIM - 1))
844template<
typename ChildT, Index Log2Dim>
848 : mOrigin(origin[0] & ~(DIM-1), origin[1] & ~(DIM-1), origin[2] & ~(DIM-1))
854template<
typename ChildT, Index Log2Dim>
855template<
typename OtherInternalNode>
859 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
863 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
864 if (s->mChildMask.isOff(i)) {
865 t->mNodes[i].setValue(
ValueType(s->mNodes[i].getValue()));
867 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild())));
871 const OtherInternalNode*
s;
875template<
typename ChildT, Index Log2Dim>
878 : mChildMask(other.mChildMask)
879 , mValueMask(other.mValueMask)
880 , mOrigin(other.mOrigin)
881 , mTransientData(other.mTransientData)
888template<
typename ChildT, Index Log2Dim>
889template<
typename OtherChildNodeType>
892 : mChildMask(other.mChildMask)
893 , mValueMask(other.mValueMask)
894 , mOrigin(other.mOrigin)
895 , mTransientData(other.mTransientData)
900template<
typename ChildT, Index Log2Dim>
901template<
typename OtherInternalNode>
905 const ValueType& background) : s(source), t(target), b(background) {
906 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
910 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
911 if (s->isChildMaskOn(i)) {
912 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild()),
915 t->mNodes[i].setValue(b);
919 const OtherInternalNode*
s;
924template<
typename ChildT, Index Log2Dim>
925template<
typename OtherChildNodeType>
929 : mChildMask(other.mChildMask)
930 , mValueMask(other.mValueMask)
931 , mOrigin(other.mOrigin)
932 , mTransientData(other.mTransientData)
937template<
typename ChildT, Index Log2Dim>
938template<
typename OtherInternalNode>
943 : s(source), t(target), offV(offValue), onV(onValue) {
944 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
947 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
948 if (s->isChildMaskOn(i)) {
949 t->mNodes[i].setChild(
new ChildNodeType(*(s->mNodes[i].getChild()),
952 t->mNodes[i].setValue(s->isValueMaskOn(i) ? onV : offV);
956 const OtherInternalNode*
s;
961template<
typename ChildT, Index Log2Dim>
962template<
typename OtherChildNodeType>
967 : mChildMask(other.mChildMask)
968 , mValueMask(other.mValueMask)
969 , mOrigin(other.mOrigin)
970 , mTransientData(other.mTransientData)
976template<
typename ChildT, Index Log2Dim>
980 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
981 delete mNodes[iter.pos()].getChild();
989template<
typename ChildT, Index Log2Dim>
993 if (ChildNodeType::getLevel() == 0)
return mChildMask.countOn();
995 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
996 sum += iter->leafCount();
1001template<
typename ChildT, Index Log2Dim>
1005 assert(vec.size() > ChildNodeType::LEVEL);
1006 const auto count = mChildMask.countOn();
1007 if (ChildNodeType::LEVEL > 0 && count > 0) {
1008 for (
auto iter = this->cbeginChildOn(); iter; ++iter) iter->nodeCount(vec);
1010 vec[ChildNodeType::LEVEL] += count;
1014template<
typename ChildT, Index Log2Dim>
1019 if (ChildNodeType::getLevel() == 0)
return sum;
1020 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1021 sum += iter->nonLeafCount();
1027template<
typename ChildT, Index Log2Dim>
1031 return this->getChildMask().countOn();
1035template<
typename ChildT, Index Log2Dim>
1039 Index64 sum = ChildT::NUM_VOXELS * mValueMask.countOn();
1040 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1041 sum += iter->onVoxelCount();
1047template<
typename ChildT, Index Log2Dim>
1051 Index64 sum = ChildT::NUM_VOXELS * (NUM_VALUES-mValueMask.countOn()-mChildMask.countOn());
1052 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1053 sum += iter->offVoxelCount();
1059template<
typename ChildT, Index Log2Dim>
1064 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1065 sum += mNodes[iter.pos()].getChild()->onLeafVoxelCount();
1071template<
typename ChildT, Index Log2Dim>
1076 for (
ChildOnCIter iter = this->beginChildOn(); iter; ++iter) {
1077 sum += mNodes[iter.pos()].getChild()->offLeafVoxelCount();
1082template<
typename ChildT, Index Log2Dim>
1086 Index64 sum = mValueMask.countOn();
1087 for (
ChildOnCIter iter = this->cbeginChildOn(); LEVEL>1 && iter; ++iter) {
1088 sum += iter->onTileCount();
1093template<
typename ChildT, Index Log2Dim>
1098 + mValueMask.memUsage() +
sizeof(mOrigin);
1099 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1100 sum += iter->memUsage();
1106template<
typename ChildT, Index Log2Dim>
1110 if (bbox.
isInside(this->getNodeBoundingBox()))
return;
1113 bbox.
expand(i.getCoord(), ChildT::DIM);
1116 i->evalActiveBoundingBox(bbox, visitVoxels);
1124template<
typename ChildT, Index Log2Dim>
1130 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1131 const Index i = iter.pos();
1132 ChildT* child = mNodes[i].getChild();
1133 child->prune(tolerance);
1134 if (child->isConstant(value, state, tolerance)) {
1136 mChildMask.setOff(i);
1137 mValueMask.set(i, state);
1138 mNodes[i].setValue(value);
1147template<
typename ChildT, Index Log2Dim>
1148template<
typename NodeT>
1152 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1153 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1155 const Index n = this->coordToOffset(xyz);
1156 if (mChildMask.isOff(n))
return nullptr;
1157 ChildT* child = mNodes[n].getChild();
1158 if (std::is_same<NodeT, ChildT>::value) {
1159 mChildMask.setOff(n);
1160 mValueMask.set(n, state);
1161 mNodes[n].setValue(value);
1163 return (std::is_same<NodeT, ChildT>::value)
1164 ?
reinterpret_cast<NodeT*
>(child)
1165 : child->template stealNode<NodeT>(xyz, value, state);
1173template<
typename ChildT, Index Log2Dim>
1174template<
typename NodeT>
1178 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1179 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1181 const Index n = this->coordToOffset(xyz);
1182 if (mChildMask.isOff(n))
return nullptr;
1183 ChildT* child = mNodes[n].getChild();
1184 return (std::is_same<NodeT, ChildT>::value)
1185 ?
reinterpret_cast<NodeT*
>(child)
1186 : child->template probeNode<NodeT>(xyz);
1191template<
typename ChildT, Index Log2Dim>
1192template<
typename NodeT,
typename AccessorT>
1196 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1197 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1199 const Index n = this->coordToOffset(xyz);
1200 if (mChildMask.isOff(n))
return nullptr;
1201 ChildT* child = mNodes[n].getChild();
1202 acc.insert(xyz, child);
1203 return (std::is_same<NodeT, ChildT>::value)
1204 ?
reinterpret_cast<NodeT*
>(child)
1205 : child->template probeNodeAndCache<NodeT>(xyz, acc);
1210template<
typename ChildT, Index Log2Dim>
1211template<
typename NodeT>
1215 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1216 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1218 const Index n = this->coordToOffset(xyz);
1219 if (mChildMask.isOff(n))
return nullptr;
1220 const ChildT* child = mNodes[n].getChild();
1221 return (std::is_same<NodeT, ChildT>::value)
1222 ?
reinterpret_cast<const NodeT*
>(child)
1223 : child->template probeConstNode<NodeT>(xyz);
1228template<
typename ChildT, Index Log2Dim>
1229template<
typename NodeT,
typename AccessorT>
1233 if ((NodeT::LEVEL == ChildT::LEVEL && !(std::is_same<NodeT, ChildT>::value)) ||
1234 NodeT::LEVEL > ChildT::LEVEL)
return nullptr;
1236 const Index n = this->coordToOffset(xyz);
1237 if (mChildMask.isOff(n))
return nullptr;
1238 const ChildT* child = mNodes[n].getChild();
1239 acc.insert(xyz, child);
1240 return (std::is_same<NodeT, ChildT>::value)
1241 ?
reinterpret_cast<const NodeT*
>(child)
1242 : child->template probeConstNodeAndCache<NodeT>(xyz, acc);
1250template<
typename ChildT, Index Log2Dim>
1251inline typename ChildT::LeafNodeType*
1254 return this->
template probeNode<LeafNodeType>(xyz);
1258template<
typename ChildT, Index Log2Dim>
1259template<
typename AccessorT>
1260inline typename ChildT::LeafNodeType*
1263 return this->
template probeNodeAndCache<LeafNodeType>(xyz, acc);
1267template<
typename ChildT, Index Log2Dim>
1268template<
typename AccessorT>
1269inline const typename ChildT::LeafNodeType*
1272 return this->probeConstLeafAndCache(xyz, acc);
1276template<
typename ChildT, Index Log2Dim>
1277inline const typename ChildT::LeafNodeType*
1280 return this->
template probeConstNode<LeafNodeType>(xyz);
1284template<
typename ChildT, Index Log2Dim>
1285template<
typename AccessorT>
1286inline const typename ChildT::LeafNodeType*
1289 return this->
template probeConstNodeAndCache<LeafNodeType>(xyz, acc);
1296template<
typename ChildT, Index Log2Dim>
1300 assert(leaf !=
nullptr);
1301 const Coord& xyz = leaf->origin();
1302 const Index n = this->coordToOffset(xyz);
1303 ChildT* child =
nullptr;
1304 if (mChildMask.isOff(n)) {
1305 if (ChildT::LEVEL>0) {
1306 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1308 child =
reinterpret_cast<ChildT*
>(leaf);
1310 this->setChildNode(n, child);
1312 if (ChildT::LEVEL>0) {
1313 child = mNodes[n].getChild();
1315 delete mNodes[n].getChild();
1316 child =
reinterpret_cast<ChildT*
>(leaf);
1317 mNodes[n].setChild(child);
1320 child->addLeaf(leaf);
1324template<
typename ChildT, Index Log2Dim>
1325template<
typename AccessorT>
1329 assert(leaf !=
nullptr);
1330 const Coord& xyz = leaf->origin();
1331 const Index n = this->coordToOffset(xyz);
1332 ChildT* child =
nullptr;
1333 if (mChildMask.isOff(n)) {
1334 if (ChildT::LEVEL>0) {
1335 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1336 acc.insert(xyz, child);
1338 child =
reinterpret_cast<ChildT*
>(leaf);
1340 this->setChildNode(n, child);
1342 if (ChildT::LEVEL>0) {
1343 child = mNodes[n].getChild();
1344 acc.insert(xyz, child);
1346 delete mNodes[n].getChild();
1347 child =
reinterpret_cast<ChildT*
>(leaf);
1348 mNodes[n].setChild(child);
1351 child->addLeafAndCache(leaf, acc);
1358template<
typename ChildT, Index Log2Dim>
1363 const Coord& xyz = child->origin();
1365 if (
Coord((xyz & ~(DIM-1))) != this->origin())
return false;
1367 const Index n = this->coordToOffset(xyz);
1369 this->resetChildNode(n, child);
1374template<
typename ChildT, Index Log2Dim>
1378 assert(n < NUM_VALUES);
1379 this->makeChildNodeEmpty(n, value);
1380 mValueMask.set(n, state);
1384template<
typename ChildT, Index Log2Dim>
1389 if (LEVEL >= level) {
1390 const Index n = this->coordToOffset(xyz);
1391 if (mChildMask.isOff(n)) {
1392 if (LEVEL > level) {
1393 ChildT* child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1394 this->setChildNode(n, child);
1395 child->addTile(level, xyz, value, state);
1397 mValueMask.set(n, state);
1398 mNodes[n].setValue(value);
1401 ChildT* child = mNodes[n].getChild();
1402 if (LEVEL > level) {
1403 child->addTile(level, xyz, value, state);
1406 mChildMask.setOff(n);
1407 mValueMask.set(n, state);
1408 mNodes[n].setValue(value);
1415template<
typename ChildT, Index Log2Dim>
1416template<
typename AccessorT>
1419 const ValueType& value,
bool state, AccessorT& acc)
1421 if (LEVEL >= level) {
1422 const Index n = this->coordToOffset(xyz);
1423 if (mChildMask.isOff(n)) {
1424 if (LEVEL > level) {
1425 ChildT* child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1426 this->setChildNode(n, child);
1427 acc.insert(xyz, child);
1428 child->addTileAndCache(level, xyz, value, state, acc);
1430 mValueMask.set(n, state);
1431 mNodes[n].setValue(value);
1434 ChildT* child = mNodes[n].getChild();
1435 if (LEVEL > level) {
1436 acc.insert(xyz, child);
1437 child->addTileAndCache(level, xyz, value, state, acc);
1440 mChildMask.setOff(n);
1441 mValueMask.set(n, state);
1442 mNodes[n].setValue(value);
1452template<
typename ChildT, Index Log2Dim>
1453inline typename ChildT::LeafNodeType*
1456 const Index n = this->coordToOffset(xyz);
1457 ChildT* child =
nullptr;
1458 if (mChildMask.isOff(n)) {
1459 child =
new ChildT(xyz, mNodes[n].getValue(), mValueMask.isOn(n));
1460 this->setChildNode(n, child);
1462 child = mNodes[n].getChild();
1464 return child->touchLeaf(xyz);
1468template<
typename ChildT, Index Log2Dim>
1469template<
typename AccessorT>
1470inline typename ChildT::LeafNodeType*
1473 const Index n = this->coordToOffset(xyz);
1474 if (mChildMask.isOff(n)) {
1475 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), mValueMask.isOn(n)));
1477 acc.insert(xyz, mNodes[n].getChild());
1478 return mNodes[n].getChild()->touchLeafAndCache(xyz, acc);
1485template<
typename ChildT, Index Log2Dim>
1490 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1492 firstValue = mNodes[0].getValue();
1493 for (
Index i = 1; i < NUM_VALUES; ++i) {
1505template<
typename ChildT, Index Log2Dim>
1513 if (!mChildMask.isOff() || !mValueMask.isConstant(state))
return false;
1514 minValue = maxValue = mNodes[0].getValue();
1515 for (
Index i = 1; i < NUM_VALUES; ++i) {
1516 const ValueType& v = mNodes[i].getValue();
1518 if ((maxValue - v) > tolerance)
return false;
1520 }
else if (v > maxValue) {
1521 if ((v - minValue) > tolerance)
return false;
1532template<
typename ChildT, Index Log2Dim>
1537 const bool anyActiveTiles = !mValueMask.isOff();
1538 if (LEVEL==1 || anyActiveTiles)
return anyActiveTiles;
1539 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
1540 if (iter->hasActiveTiles())
return true;
1547template<
typename ChildT, Index Log2Dim>
1551 const Index n = this->coordToOffset(xyz);
1552 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1553 return mNodes[n].getChild()->isValueOn(xyz);
1556template<
typename ChildT, Index Log2Dim>
1557template<
typename AccessorT>
1561 const Index n = this->coordToOffset(xyz);
1562 if (this->isChildMaskOff(n))
return this->isValueMaskOn(n);
1563 acc.insert(xyz, mNodes[n].getChild());
1564 return mNodes[n].getChild()->isValueOnAndCache(xyz, acc);
1568template<
typename ChildT, Index Log2Dim>
1569inline const typename ChildT::ValueType&
1572 const Index n = this->coordToOffset(xyz);
1573 return this->isChildMaskOff(n) ? mNodes[n].getValue()
1574 : mNodes[n].getChild()->getValue(xyz);
1577template<
typename ChildT, Index Log2Dim>
1578template<
typename AccessorT>
1579inline const typename ChildT::ValueType&
1582 const Index n = this->coordToOffset(xyz);
1583 if (this->isChildMaskOn(n)) {
1584 acc.insert(xyz, mNodes[n].getChild());
1585 return mNodes[n].getChild()->getValueAndCache(xyz, acc);
1587 return mNodes[n].getValue();
1591template<
typename ChildT, Index Log2Dim>
1595 const Index n = this->coordToOffset(xyz);
1596 return this->isChildMaskOff(n) ? LEVEL : mNodes[n].getChild()->getValueLevel(xyz);
1599template<
typename ChildT, Index Log2Dim>
1600template<
typename AccessorT>
1604 const Index n = this->coordToOffset(xyz);
1605 if (this->isChildMaskOn(n)) {
1606 acc.insert(xyz, mNodes[n].getChild());
1607 return mNodes[n].getChild()->getValueLevelAndCache(xyz, acc);
1613template<
typename ChildT, Index Log2Dim>
1617 const Index n = this->coordToOffset(xyz);
1618 if (this->isChildMaskOff(n)) {
1619 value = mNodes[n].getValue();
1620 return this->isValueMaskOn(n);
1622 return mNodes[n].getChild()->probeValue(xyz, value);
1625template<
typename ChildT, Index Log2Dim>
1626template<
typename AccessorT>
1631 const Index n = this->coordToOffset(xyz);
1632 if (this->isChildMaskOn(n)) {
1633 acc.insert(xyz, mNodes[n].getChild());
1634 return mNodes[n].getChild()->probeValueAndCache(xyz, value, acc);
1636 value = mNodes[n].getValue();
1637 return this->isValueMaskOn(n);
1641template<
typename ChildT, Index Log2Dim>
1645 const Index n = this->coordToOffset(xyz);
1646 bool hasChild = this->isChildMaskOn(n);
1647 if (!hasChild && this->isValueMaskOn(n)) {
1651 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
true));
1653 if (hasChild) mNodes[n].getChild()->setValueOff(xyz);
1657template<
typename ChildT, Index Log2Dim>
1661 const Index n = this->coordToOffset(xyz);
1662 bool hasChild = this->isChildMaskOn(n);
1663 if (!hasChild && !this->isValueMaskOn(n)) {
1667 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(),
false));
1669 if (hasChild) mNodes[n].getChild()->setValueOn(xyz);
1673template<
typename ChildT, Index Log2Dim>
1678 bool hasChild = this->isChildMaskOn(n);
1680 const bool active = this->isValueMaskOn(n);
1686 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1689 if (hasChild) mNodes[n].getChild()->setValueOff(xyz, value);
1692template<
typename ChildT, Index Log2Dim>
1693template<
typename AccessorT>
1699 bool hasChild = this->isChildMaskOn(n);
1701 const bool active = this->isValueMaskOn(n);
1707 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1711 ChildT* child = mNodes[n].getChild();
1712 acc.insert(xyz, child);
1713 child->setValueOffAndCache(xyz, value, acc);
1718template<
typename ChildT, Index Log2Dim>
1722 const Index n = this->coordToOffset(xyz);
1723 bool hasChild = this->isChildMaskOn(n);
1725 const bool active = this->isValueMaskOn(n);
1731 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1734 if (hasChild) mNodes[n].getChild()->setValueOn(xyz, value);
1737template<
typename ChildT, Index Log2Dim>
1738template<
typename AccessorT>
1743 const Index n = this->coordToOffset(xyz);
1744 bool hasChild = this->isChildMaskOn(n);
1746 const bool active = this->isValueMaskOn(n);
1752 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1756 acc.insert(xyz, mNodes[n].getChild());
1757 mNodes[n].getChild()->setValueAndCache(xyz, value, acc);
1762template<
typename ChildT, Index Log2Dim>
1766 const Index n = this->coordToOffset(xyz);
1767 bool hasChild = this->isChildMaskOn(n);
1771 const bool active = this->isValueMaskOn(n);
1773 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1775 if (hasChild) mNodes[n].getChild()->setValueOnly(xyz, value);
1778template<
typename ChildT, Index Log2Dim>
1779template<
typename AccessorT>
1784 const Index n = this->coordToOffset(xyz);
1785 bool hasChild = this->isChildMaskOn(n);
1789 const bool active = this->isValueMaskOn(n);
1791 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1794 acc.insert(xyz, mNodes[n].getChild());
1795 mNodes[n].getChild()->setValueOnlyAndCache(xyz, value, acc);
1800template<
typename ChildT, Index Log2Dim>
1804 const Index n = this->coordToOffset(xyz);
1805 bool hasChild = this->isChildMaskOn(n);
1807 if (on != this->isValueMaskOn(n)) {
1812 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1815 if (hasChild) mNodes[n].getChild()->setActiveState(xyz, on);
1818template<
typename ChildT, Index Log2Dim>
1819template<
typename AccessorT>
1823 const Index n = this->coordToOffset(xyz);
1824 bool hasChild = this->isChildMaskOn(n);
1826 if (on != this->isValueMaskOn(n)) {
1831 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), !on));
1835 ChildT* child = mNodes[n].getChild();
1836 acc.insert(xyz, child);
1837 child->setActiveStateAndCache(xyz, on, acc);
1842template<
typename ChildT, Index Log2Dim>
1846 mValueMask = !mChildMask;
1847 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
1848 mNodes[iter.pos()].getChild()->setValuesOn();
1853template<
typename ChildT, Index Log2Dim>
1854template<
typename ModifyOp>
1859 bool hasChild = this->isChildMaskOn(n);
1863 const bool active = this->isValueMaskOn(n);
1864 bool createChild = !active;
1868 const ValueType& tileVal = mNodes[n].getValue();
1875 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1878 if (hasChild) mNodes[n].getChild()->modifyValue(xyz, op);
1881template<
typename ChildT, Index Log2Dim>
1882template<
typename ModifyOp,
typename AccessorT>
1888 bool hasChild = this->isChildMaskOn(n);
1892 const bool active = this->isValueMaskOn(n);
1893 bool createChild = !active;
1897 const ValueType& tileVal = mNodes[n].getValue();
1904 this->setChildNode(n,
new ChildNodeType(xyz, mNodes[n].getValue(), active));
1909 acc.insert(xyz, child);
1910 child->modifyValueAndCache(xyz, op, acc);
1915template<
typename ChildT, Index Log2Dim>
1916template<
typename ModifyOp>
1921 bool hasChild = this->isChildMaskOn(n);
1923 const bool tileState = this->isValueMaskOn(n);
1924 const ValueType& tileVal = mNodes[n].getValue();
1925 bool modifiedState = !tileState;
1927 op(modifiedVal, modifiedState);
1932 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
1935 if (hasChild) mNodes[n].getChild()->modifyValueAndActiveState(xyz, op);
1938template<
typename ChildT, Index Log2Dim>
1939template<
typename ModifyOp,
typename AccessorT>
1942 const Coord& xyz,
const ModifyOp& op, AccessorT& acc)
1945 bool hasChild = this->isChildMaskOn(n);
1947 const bool tileState = this->isValueMaskOn(n);
1948 const ValueType& tileVal = mNodes[n].getValue();
1949 bool modifiedState = !tileState;
1951 op(modifiedVal, modifiedState);
1956 this->setChildNode(n,
new ChildNodeType(xyz, tileVal, tileState));
1961 acc.insert(xyz, child);
1962 child->modifyValueAndActiveStateAndCache(xyz, op, acc);
1970template<
typename ChildT, Index Log2Dim>
1974 CoordBBox nodeBBox = this->getNodeBoundingBox();
1977 this->fill(nodeBBox, background,
false);
1978 }
else if (clipBBox.
isInside(nodeBBox)) {
1987 for (
Index pos = 0; pos < NUM_VALUES; ++pos) {
1988 const Coord xyz = this->offsetToGlobalCoord(pos);
1993 this->makeChildNodeEmpty(pos, background);
1994 mValueMask.setOff(pos);
1995 }
else if (!clipBBox.
isInside(tileBBox)) {
1998 if (this->isChildMaskOn(pos)) {
1999 mNodes[pos].getChild()->clip(clipBBox, background);
2004 const ValueType val = mNodes[pos].getValue();
2005 const bool on = this->isValueMaskOn(pos);
2006 mNodes[pos].setValue(background);
2007 mValueMask.setOff(pos);
2008 this->fill(tileBBox, val, on);
2020template<
typename ChildT, Index Log2Dim>
2024 auto clippedBBox = this->getNodeBoundingBox();
2025 clippedBBox.intersect(bbox);
2026 if (!clippedBBox)
return;
2030 Coord xyz, tileMin, tileMax;
2031 for (
int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.
x() + 1) {
2033 for (
int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.
y() + 1) {
2035 for (
int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.
z() + 1) {
2039 const Index n = this->coordToOffset(xyz);
2040 tileMin = this->offsetToGlobalCoord(n);
2041 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2047 ChildT* child =
nullptr;
2048 if (this->isChildMaskOff(n)) {
2051 child =
new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)};
2052 this->setChildNode(n, child);
2054 child = mNodes[n].getChild();
2060 child->fill(
CoordBBox(xyz, tmp), value, active);
2067 this->makeChildNodeEmpty(n, value);
2068 mValueMask.set(n, active);
2076template<
typename ChildT, Index Log2Dim>
2080 auto clippedBBox = this->getNodeBoundingBox();
2081 clippedBBox.intersect(bbox);
2082 if (!clippedBBox)
return;
2086 Coord xyz, tileMin, tileMax;
2087 for (
int x = clippedBBox.min().x(); x <= clippedBBox.max().x(); x = tileMax.
x() + 1) {
2089 for (
int y = clippedBBox.min().y(); y <= clippedBBox.max().y(); y = tileMax.
y() + 1) {
2091 for (
int z = clippedBBox.min().z(); z <= clippedBBox.max().z(); z = tileMax.
z() + 1) {
2095 const auto n = this->coordToOffset(xyz);
2098 ChildT* child =
nullptr;
2099 if (this->isChildMaskOn(n)) {
2100 child = mNodes[n].getChild();
2104 child =
new ChildT{xyz, mNodes[n].getValue(), this->isValueMaskOn(n)};
2105 this->setChildNode(n, child);
2109 tileMin = this->offsetToGlobalCoord(n);
2110 tileMax = tileMin.
offsetBy(ChildT::DIM - 1);
2113 child->denseFill(
CoordBBox{xyz, clippedBBox.
max()}, value, active);
2123template<
typename ChildT, Index Log2Dim>
2124template<
typename DenseT>
2128 using DenseValueType =
typename DenseT::ValueType;
2130 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
2131 const Coord& min = dense.bbox().min();
2132 for (
Coord xyz = bbox.
min(), max; xyz[0] <= bbox.
max()[0]; xyz[0] = max[0] + 1) {
2133 for (xyz[1] = bbox.
min()[1]; xyz[1] <= bbox.
max()[1]; xyz[1] = max[1] + 1) {
2134 for (xyz[2] = bbox.
min()[2]; xyz[2] <= bbox.
max()[2]; xyz[2] = max[2] + 1) {
2135 const Index n = this->coordToOffset(xyz);
2137 max = this->offsetToGlobalCoord(n).offsetBy(ChildT::DIM-1);
2142 if (this->isChildMaskOn(n)) {
2143 mNodes[n].getChild()->copyToDense(sub, dense);
2145 const ValueType value = mNodes[n].getValue();
2147 DenseValueType* a0 = dense.data() + zStride*sub.
min()[2];
2148 for (
Int32 x=sub.
min()[0], ex=sub.
max()[0]+1; x<ex; ++x) {
2149 DenseValueType* a1 = a0 + x*xStride;
2150 for (
Int32 y=sub.
min()[1], ey=sub.
max()[1]+1; y<ey; ++y) {
2151 DenseValueType* a2 = a1 + y*yStride;
2153 z < ez; ++z, a2 += zStride)
2155 *a2 = DenseValueType(value);
2169template<
typename ChildT, Index Log2Dim>
2173 mChildMask.save(os);
2174 mValueMask.save(os);
2178 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[NUM_VALUES]);
2180 const ValueType zero = zeroVal<ValueType>();
2181 for (
Index i = 0; i < NUM_VALUES; ++i) {
2182 values[i] = (mChildMask.isOff(i) ? mNodes[i].getValue() : zero);
2188 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2189 iter->writeTopology(os, toHalf);
2194template<
typename ChildT, Index Log2Dim>
2201 mChildMask.load(is);
2202 mValueMask.load(is);
2205 for (
Index i = 0; i < NUM_VALUES; ++i) {
2206 if (this->isChildMaskOn(i)) {
2209 mNodes[i].setChild(child);
2210 child->readTopology(is);
2213 is.read(
reinterpret_cast<char*
>(&value),
sizeof(
ValueType));
2214 mNodes[i].setValue(value);
2218 const bool oldVersion =
2220 const Index numValues = (oldVersion ? mChildMask.countOff() : NUM_VALUES);
2224 std::unique_ptr<ValueType[]> valuePtr(
new ValueType[numValues]);
2231 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2232 mNodes[iter.pos()].setValue(values[n++]);
2234 assert(n == numValues);
2236 for (
ValueAllIter iter = this->beginValueAll(); iter; ++iter) {
2237 mNodes[iter.pos()].setValue(values[iter.pos()]);
2242 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2244 mNodes[iter.pos()].setChild(child);
2245 child->readTopology(is, fromHalf);
2254template<
typename ChildT, Index Log2Dim>
2255inline const typename ChildT::ValueType&
2258 return (this->isChildMaskOn(0) ? mNodes[0].getChild()->getFirstValue() : mNodes[0].getValue());
2262template<
typename ChildT, Index Log2Dim>
2263inline const typename ChildT::ValueType&
2266 const Index n = NUM_VALUES - 1;
2267 return (this->isChildMaskOn(n) ? mNodes[n].getChild()->getLastValue() : mNodes[n].getValue());
2274template<
typename ChildT, Index Log2Dim>
2278 for (
Index i = 0; i < NUM_VALUES; ++i) {
2279 if (this->isChildMaskOn(i)) {
2280 mNodes[i].getChild()->negate();
2292template<
typename ChildT, Index Log2Dim>
2297 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2304 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2305 if (mNode->mChildMask.isOn(i)) {
2306 mNode->mNodes[i].getChild()->voxelizeActiveTiles(
true);
2307 }
else if (mNode->mValueMask.isOn(i)) {
2308 const Coord &ijk = mNode->offsetToGlobalCoord(i);
2310 child->voxelizeActiveTiles(
true);
2311 mNode->mNodes[i].setChild(child);
2318template<
typename ChildT, Index Log2Dim>
2325 for (
ValueOnIter iter = this->beginValueOn(); iter; ++iter) {
2326 this->setChildNode(iter.pos(),
2329 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter)
2330 iter->voxelizeActiveTiles(
false);
2338template<
typename ChildT, Index Log2Dim>
2339template<MergePolicy Policy>
2352 const Index n = iter.pos();
2353 if (mChildMask.isOn(n)) {
2355 mNodes[n].getChild()->template merge<MERGE_ACTIVE_STATES>(*iter,
2356 background, otherBackground);
2357 }
else if (mValueMask.isOff(n)) {
2364 child->resetBackground(otherBackground, background);
2365 this->setChildNode(n, child);
2371 const Index n = iter.pos();
2372 if (mValueMask.isOff(n)) {
2374 this->makeChildNodeEmpty(n, iter.getValue());
2375 mValueMask.setOn(n);
2384 const Index n = iter.pos();
2385 if (mChildMask.isOn(n)) {
2387 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2395 child->resetBackground(otherBackground, background);
2396 this->setChildNode(n, child);
2406 const Index n = iter.pos();
2407 if (mChildMask.isOn(n)) {
2409 mNodes[n].getChild()->template merge<Policy>(*iter, background, otherBackground);
2416 child->resetBackground(otherBackground, background);
2417 if (mValueMask.isOn(n)) {
2419 child->template merge<Policy>(mNodes[n].getValue(),
true);
2420 mValueMask.setOff(n);
2422 mChildMask.setOn(n);
2423 mNodes[n].setChild(child);
2429 const Index n = iter.pos();
2430 if (mChildMask.isOn(n)) {
2432 mNodes[n].getChild()->template merge<Policy>(iter.getValue(),
true);
2433 }
else if (mValueMask.isOff(n)) {
2435 mNodes[n].setValue(iter.getValue());
2436 mValueMask.setOn(n);
2447template<
typename ChildT, Index Log2Dim>
2448template<MergePolicy Policy>
2457 if (!tileActive)
return;
2460 for (
ValueOffIter iter = this->beginValueOff(); iter; ++iter) {
2461 const Index n = iter.pos();
2462 if (mChildMask.isOn(n)) {
2464 mNodes[n].getChild()->template merge<Policy>(tileValue,
true);
2467 iter.setValue(tileValue);
2468 mValueMask.setOn(n);
2478template<
typename ChildT, Index Log2Dim>
2479template<
typename OtherInternalNode>
2484 { tV = (tV | sV) & ~tC; }
2487 : s(source), t(target), mPreserveTiles(preserveTiles) {
2489 tbb::parallel_for(tbb::blocked_range<Index>(0, NUM_VALUES), *
this);
2492 if (!mPreserveTiles) t->mChildMask |= s->mChildMask;
2493 else t->mChildMask |= (s->mChildMask & !t->mValueMask);
2496 t->mValueMask.foreach(s->mValueMask, t->mChildMask, op);
2497 assert((t->mValueMask & t->mChildMask).isOff());
2500 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2501 if (s->mChildMask.isOn(i)) {
2502 const typename OtherInternalNode::ChildNodeType& other = *(s->mNodes[i].getChild());
2503 if (t->mChildMask.isOn(i)) {
2504 t->mNodes[i].getChild()->topologyUnion(other, mPreserveTiles);
2506 if (!mPreserveTiles || t->mValueMask.isOff(i)) {
2507 ChildT* child =
new ChildT(other, t->mNodes[i].getValue(),
TopologyCopy());
2508 if (t->mValueMask.isOn(i)) child->setValuesOn();
2509 t->mNodes[i].setChild(child);
2512 }
else if (s->mValueMask.isOn(i) && t->mChildMask.isOn(i)) {
2513 t->mNodes[i].getChild()->setValuesOn();
2517 const OtherInternalNode*
s;
2522template<
typename ChildT, Index Log2Dim>
2523template<
typename OtherChildT>
2530template<
typename ChildT, Index Log2Dim>
2531template<
typename OtherInternalNode>
2536 { tC = (tC & (sC | sV)) | (tV & sC); }
2539 const ValueType& background) : s(source), t(target), b(background) {
2541 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
2545 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op);
2547 t->mValueMask &= s->mValueMask;
2548 assert((t->mValueMask & t->mChildMask).isOff());
2551 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2552 if (t->mChildMask.isOn(i)) {
2553 ChildT* child = t->mNodes[i].getChild();
2554 if (s->mChildMask.isOn(i)) {
2555 child->topologyIntersection(*(s->mNodes[i].getChild()), b);
2556 }
else if (s->mValueMask.isOff(i)) {
2558 t->mNodes[i].setValue(b);
2560 }
else if (t->mValueMask.isOn(i) && s->mChildMask.isOn(i)) {
2561 t->mNodes[i].setChild(
new ChildT(*(s->mNodes[i].getChild()),
2566 const OtherInternalNode*
s;
2571template<
typename ChildT, Index Log2Dim>
2572template<
typename OtherChildT>
2580template<
typename ChildT, Index Log2Dim>
2581template<
typename OtherInternalNode>
2586 { tC = (tC & (sC | ~sV)) | (tV & sC); }
2589 { tV &= ~((tC & sV) | (sC | sV)); }
2592 const ValueType& background) : s(source), t(target), b(background) {
2594 tbb::parallel_for(tbb::blocked_range<Index>(0,
NUM_VALUES), *
this);
2599 t->mChildMask.foreach(s->mChildMask, s->mValueMask, t->mValueMask, op1);
2602 t->mValueMask.foreach(t->mChildMask, s->mValueMask, oldChildMask, op2);
2603 assert((t->mValueMask & t->mChildMask).isOff());
2606 for (
Index i = r.begin(), end=r.end(); i!=end; ++i) {
2607 if (t->mChildMask.isOn(i)) {
2608 ChildT* child = t->mNodes[i].getChild();
2609 if (s->mChildMask.isOn(i)) {
2610 child->topologyDifference(*(s->mNodes[i].getChild()), b);
2611 }
else if (s->mValueMask.isOn(i)) {
2613 t->mNodes[i].setValue(b);
2615 }
else if (t->mValueMask.isOn(i)) {
2616 if (s->mChildMask.isOn(i)) {
2617 const typename OtherInternalNode::ChildNodeType& other =
2618 *(s->mNodes[i].getChild());
2619 ChildT* child =
new ChildT(other.origin(), t->mNodes[i].getValue(),
true);
2620 child->topologyDifference(other, b);
2621 t->mNodes[i].setChild(child);
2626 const OtherInternalNode*
s;
2631template<
typename ChildT, Index Log2Dim>
2632template<
typename OtherChildT>
2644template<
typename ChildT, Index Log2Dim>
2645template<
typename CombineOp>
2649 const ValueType zero = zeroVal<ValueType>();
2653 for (
Index i = 0; i < NUM_VALUES; ++i) {
2657 op(args.
setARef(mNodes[i].getValue())
2661 mNodes[i].setValue(args.
result());
2670 }
else if (this->isChildMaskOff(i) && other.
isChildMaskOn(i)) {
2679 child->combine(mNodes[i].getValue(), isValueMaskOn(i), swappedOp);
2684 this->setChildNode(i, child);
2690 *child = mNodes[i].getChild(),
2694 if (child && otherChild) {
2695 child->combine(*otherChild, op);
2702template<
typename ChildT, Index Log2Dim>
2703template<
typename CombineOp>
2709 for (
Index i = 0; i < NUM_VALUES; ++i) {
2710 if (this->isChildMaskOff(i)) {
2712 op(args.
setARef(mNodes[i].getValue())
2715 .setBIsActive(valueIsActive));
2716 mNodes[i].setValue(args.
result());
2722 if (child) child->combine(value, valueIsActive, op);
2731template<
typename ChildT, Index Log2Dim>
2732template<
typename CombineOp,
typename OtherNodeType>
2739 for (
Index i = 0; i < NUM_VALUES; ++i) {
2743 .
setBRef(other1.mNodes[i].getValue())
2746 this->makeChildNodeEmpty(i, args.
result());
2749 if (this->isChildMaskOff(i)) {
2753 : other1.mNodes[i].getChild()->origin();
2754 this->setChildNode(i,
new ChildNodeType(childOrigin, mNodes[i].getValue()));
2762 }
else if (other1.isChildMaskOff(i)) {
2766 other1.mNodes[i].getValue(), other1.isValueMaskOn(i), op);
2771 *other1.mNodes[i].getChild(), op);
2778template<
typename ChildT, Index Log2Dim>
2779template<
typename CombineOp,
typename OtherNodeType>
2782 bool valueIsActive, CombineOp& op)
2786 for (
Index i = 0; i < NUM_VALUES; ++i) {
2787 if (other.isChildMaskOff(i)) {
2790 .
setBRef(other.mNodes[i].getValue())
2793 this->makeChildNodeEmpty(i, args.
result());
2796 typename OtherNodeType::ChildNodeType* otherChild = other.mNodes[i].getChild();
2798 if (this->isChildMaskOff(i)) {
2805 mNodes[i].getChild()->combine2(value, *otherChild, valueIsActive, op);
2811template<
typename ChildT, Index Log2Dim>
2812template<
typename CombineOp,
typename OtherValueType>
2815 bool valueIsActive, CombineOp& op)
2819 for (
Index i = 0; i < NUM_VALUES; ++i) {
2826 this->makeChildNodeEmpty(i, args.
result());
2831 if (this->isChildMaskOff(i)) {
2833 this->setChildNode(i,
2834 new ChildNodeType(otherChild->origin(), mNodes[i].getValue()));
2838 mNodes[i].getChild()->combine2(*otherChild, value, valueIsActive, op);
2847template<
typename ChildT, Index Log2Dim>
2851 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2852 iter->writeBuffers(os, toHalf);
2857template<
typename ChildT, Index Log2Dim>
2861 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2862 iter->readBuffers(is, fromHalf);
2867template<
typename ChildT, Index Log2Dim>
2870 const CoordBBox& clipBBox,
bool fromHalf)
2872 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2877 iter->readBuffers(is, clipBBox, fromHalf);
2881 ValueType background = zeroVal<ValueType>();
2883 background = *
static_cast<const ValueType*
>(bgPtr);
2885 this->clip(clipBBox, background);
2892template<
typename ChildT, Index Log2Dim>
2896 dims.push_back(Log2Dim);
2897 ChildNodeType::getNodeLog2Dims(dims);
2901template<
typename ChildT, Index Log2Dim>
2905 assert(n<(1<<3*Log2Dim));
2906 xyz.
setX(n >> 2*Log2Dim);
2907 n &= ((1<<2*Log2Dim)-1);
2908 xyz.
setY(n >> Log2Dim);
2909 xyz.
setZ(n & ((1<<Log2Dim)-1));
2913template<
typename ChildT, Index Log2Dim>
2917 return (((xyz[0] & (DIM-1u)) >> ChildNodeType::TOTAL) << 2*Log2Dim)
2918 + (((xyz[1] & (DIM-1u)) >> ChildNodeType::TOTAL) << Log2Dim)
2919 + ((xyz[2] & (DIM-1u)) >> ChildNodeType::TOTAL);
2923template<
typename ChildT, Index Log2Dim>
2928 this->offsetToLocalCoord(n, local);
2929 local <<= ChildT::TOTAL;
2930 return local + this->origin();
2937template<
typename ChildT, Index Log2Dim>
2938template<
typename ArrayT>
2942 using T =
typename ArrayT::value_type;
2943 static_assert(std::is_pointer<T>::value,
"argument to getNodes() must be a pointer array");
2944 using ArrayChildT =
typename std::conditional<
2945 std::is_const<typename std::remove_pointer<T>::type>::value,
const ChildT, ChildT>::type;
2946 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2948 if (std::is_same<T, ArrayChildT*>::value) {
2949 array.push_back(
reinterpret_cast<T
>(mNodes[iter.pos()].getChild()));
2951 iter->getNodes(array);
2957template<
typename ChildT, Index Log2Dim>
2958template<
typename ArrayT>
2962 using T =
typename ArrayT::value_type;
2963 static_assert(std::is_pointer<T>::value,
"argument to getNodes() must be a pointer array");
2964 static_assert(std::is_const<typename std::remove_pointer<T>::type>::value,
2965 "argument to getNodes() must be an array of const node pointers");
2966 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
2968 if (std::is_same<T, const ChildT*>::value) {
2969 array.push_back(
reinterpret_cast<T
>(mNodes[iter.pos()].getChild()));
2971 iter->getNodes(array);
2981template<
typename ChildT, Index Log2Dim>
2982template<
typename ArrayT>
2986 using T =
typename ArrayT::value_type;
2987 static_assert(std::is_pointer<T>::value,
"argument to stealNodes() must be a pointer array");
2988 using ArrayChildT =
typename std::conditional<
2989 std::is_const<typename std::remove_pointer<T>::type>::value,
const ChildT, ChildT>::type;
2991 for (
ChildOnIter iter = this->beginChildOn(); iter; ++iter) {
2992 const Index n = iter.pos();
2993 if (std::is_same<T, ArrayChildT*>::value) {
2994 array.push_back(
reinterpret_cast<T
>(mNodes[n].getChild()));
2995 mValueMask.set(n, state);
2996 mNodes[n].setValue(value);
2998 iter->stealNodes(array, value, state);
3001 if (std::is_same<T, ArrayChildT*>::value) mChildMask.setOff();
3009template<
typename ChildT, Index Log2Dim>
3015 for (
Index i = 0; i < NUM_VALUES; ++i) {
3016 if (this->isChildMaskOn(i)) {
3017 mNodes[i].getChild()->resetBackground(oldBackground, newBackground);
3018 }
else if (this->isValueMaskOff(i)) {
3020 mNodes[i].setValue(newBackground);
3028template<
typename ChildT, Index Log2Dim>
3029template<
typename OtherChildNodeType, Index OtherLog2Dim>
3034 if (Log2Dim != OtherLog2Dim || mChildMask != other->
mChildMask ||
3035 mValueMask != other->
mValueMask)
return false;
3036 for (
ChildOnCIter iter = this->cbeginChildOn(); iter; ++iter) {
3037 if (!iter->hasSameTopology(other->
mNodes[iter.pos()].
getChild()))
return false;
3043template<
typename ChildT, Index Log2Dim>
3048 if (this->isChildMaskOn(i)) {
3049 delete mNodes[i].getChild();
3051 mChildMask.setOn(i);
3052 mValueMask.setOff(i);
3054 mNodes[i].setChild(child);
3057template<
typename ChildT, Index Log2Dim>
3062 assert(mChildMask.isOff(i));
3063 mChildMask.setOn(i);
3064 mValueMask.setOff(i);
3065 mNodes[i].setChild(child);
3069template<
typename ChildT, Index Log2Dim>
3073 if (this->isChildMaskOff(i)) {
3074 mNodes[i].setValue(value);
3078 mChildMask.setOff(i);
3079 mNodes[i].setValue(value);
3084template<
typename ChildT, Index Log2Dim>
3088 delete this->unsetChildNode(n, value);
3091template<
typename ChildT, Index Log2Dim>
3095 assert(this->isChildMaskOn(n));
3096 return mNodes[n].getChild();
3100template<
typename ChildT, Index Log2Dim>
3104 assert(this->isChildMaskOn(n));
3105 return mNodes[n].getChild();
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
Definition Types.h:569
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
Definition Types.h:621
const AValueType & result() const
Get the output value.
Definition Types.h:613
CombineArgs & setBIsActive(bool b)
Set the active state of the B value.
Definition Types.h:637
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
Definition Types.h:623
bool resultIsActive() const
Definition Types.h:632
CombineArgs & setAIsActive(bool b)
Set the active state of the A value.
Definition Types.h:635
Tag dispatch class that distinguishes constructors that deep copy.
Definition Types.h:685
Tag dispatch class that distinguishes constructors during file input.
Definition Types.h:689
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition Types.h:683
Axis-aligned bounding box of signed integer coordinates.
Definition Coord.h:251
void translate(const Coord &t)
Translate this bounding box by (tx, ty, tz).
Definition Coord.h:460
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition Coord.h:420
const Coord & min() const
Definition Coord.h:323
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition Coord.h:414
const Coord & max() const
Definition Coord.h:324
bool isInside(const Coord &xyz) const
Return true if point (x, y, z) is inside this bounding box.
Definition Coord.h:402
void intersect(const CoordBBox &bbox)
Intersect this bounding box with the given bounding box.
Definition Coord.h:446
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:25
Int32 y() const
Definition Coord.h:131
Coord offsetBy(Int32 dx, Int32 dy, Int32 dz) const
Definition Coord.h:91
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition Coord.h:175
Int32 x() const
Definition Coord.h:130
Coord & setZ(Int32 z)
Definition Coord.h:81
Coord & setY(Int32 y)
Definition Coord.h:80
static Coord max()
Return the largest possible coordinate.
Definition Coord.h:46
static bool lessThan(const Coord &a, const Coord &b)
Definition Coord.h:208
Int32 z() const
Definition Coord.h:132
Coord & setX(Int32 x)
Definition Coord.h:79
Definition InternalNode.h:34
void setValueAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition InternalNode.h:1740
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Definition InternalNode.h:333
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:2341
ChildOnCIter cbeginChildOn() const
Definition InternalNode.h:220
const ValueType & getFirstValue() const
If the first entry in this node's table is a tile, return the tile's value. Otherwise,...
Definition InternalNode.h:2256
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:297
ChildOnCIter beginChildOn() const
Definition InternalNode.h:223
ChildOnIter beginChildOn()
Definition InternalNode.h:226
NodeType * probeNode(const Coord &xyz)
Return a pointer to the node that contains voxel (x, y, z). If no such node exists,...
bool isChildMaskOff(Index n) const
Definition InternalNode.h:749
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
Definition InternalNode.h:1549
void writeTopology(std::ostream &, bool toHalf=false) const
Definition InternalNode.h:2171
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:2126
void setChildNode(Index i, ChildNodeType *child)
Definition InternalNode.h:3059
bool isChildMaskOff() const
Definition InternalNode.h:750
ValueOffCIter cbeginValueOff() const
Definition InternalNode.h:232
LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc)
Same as probeLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
Index32 transientData() const
Return the transient data value.
Definition InternalNode.h:272
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:1327
static Index getChildDim()
Definition InternalNode.h:256
const NodeMaskType & getChildMask() const
Definition InternalNode.h:752
Index32 nonLeafCount() const
Definition InternalNode.h:1016
void topologyIntersection(const InternalNode< OtherChildNodeType, Log2Dim > &other, const ValueType &background)
Intersects this tree's set of active values with the active values of the other tree,...
NodeMaskType mChildMask
Definition InternalNode.h:793
bool isValueMaskOff() const
Definition InternalNode.h:747
void getNodes(ArrayT &array)
Adds all nodes of a certain type to a container with the following API:
Definition InternalNode.h:2940
bool isValueMaskOn() const
Definition InternalNode.h:745
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:1150
void voxelizeActiveTiles(bool threaded=true)
Densify active tiles, i.e., replace them with leaf-level active voxels.
Definition InternalNode.h:2320
NodeMaskType mValueMask
Definition InternalNode.h:793
InternalNode()
Default constructor.
Definition InternalNode.h:72
bool isChildMaskOn(Index n) const
Definition InternalNode.h:748
~InternalNode()
Definition InternalNode.h:978
Index64 onLeafVoxelCount() const
Definition InternalNode.h:1061
const LeafNodeType * probeConstLeafAndCache(const Coord &xyz, AccessorT &acc) const
NodeMaskType getValueOffMask() const
Definition InternalNode.h:753
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:1252
ValueAllCIter cbeginValueAll() const
Definition InternalNode.h:233
void prune(const ValueType &tolerance=zeroVal< ValueType >())
Reduce the memory footprint of this tree by replacing with tiles any nodes whose values are all the s...
Definition InternalNode.h:1126
ValueOnCIter beginValueOn() const
Definition InternalNode.h:234
Index64 offLeafVoxelCount() const
Definition InternalNode.h:1073
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:3011
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:1386
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
Definition InternalNode.h:269
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
Definition InternalNode.h:267
bool isInactive() const
Return true if this node has no children and only contains inactive values.
Definition InternalNode.h:328
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
Definition InternalNode.h:1918
void setValueOnlyAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition InternalNode.h:1781
void combine2(const InternalNode &other0, const OtherNodeType &other1, CombineOp &)
Definition InternalNode.h:2734
friend class InternalNode
During topology-only construction, access is needed to protected/private members of other template in...
Definition InternalNode.h:740
bool isValueMaskOff(Index n) const
Definition InternalNode.h:746
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:1764
const LeafNodeType * probeConstLeaf(const Coord &xyz) const
Definition InternalNode.h:1278
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:1602
const NodeType * probeConstNodeAndCache(const Coord &xyz, AccessorT &) const
void fill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within a given axis-aligned box to a constant value.
Definition InternalNode.h:2022
ValueOffCIter beginValueOff() const
Definition InternalNode.h:236
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Definition InternalNode.h:1695
void addLeaf(LeafNodeType *leaf)
Add the specified leaf to this node, possibly creating a child branch in the process....
Definition InternalNode.h:1298
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
ChildAllCIter cbeginChildAll() const
Definition InternalNode.h:222
void clip(const CoordBBox &, const ValueType &background)
Set all voxels that lie outside the given axis-aligned box to the background.
Definition InternalNode.h:1972
ChildAllIter beginChildAll()
Definition InternalNode.h:228
static Index getLevel()
Definition InternalNode.h:249
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Definition InternalNode.h:1559
void topologyDifference(const InternalNode< OtherChildNodeType, Log2Dim > &other, const ValueType &background)
Difference this node's set of active values with the active values of the other node,...
bool probeValue(const Coord &xyz, ValueType &value) const
Definition InternalNode.h:1615
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:1802
ValueOnIter beginValueOn()
Definition InternalNode.h:238
void modifyValueAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Apply a functor to the value of the voxel at the given coordinates and mark the voxel as active....
Definition InternalNode.h:1884
void topologyUnion(const InternalNode< OtherChildNodeType, Log2Dim > &other, const bool preserveTiles=false)
Union this branch's set of active values with the other branch's active values. The value type of the...
ChildOffCIter cbeginChildOff() const
Definition InternalNode.h:221
ChildOffIter beginChildOff()
Definition InternalNode.h:227
Index64 onVoxelCount() const
Definition InternalNode.h:1037
ChildOffCIter beginChildOff() const
Definition InternalNode.h:224
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
Definition InternalNode.h:2915
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:1418
typename ChildNodeType::LeafNodeType LeafNodeType
Definition InternalNode.h:37
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
Definition InternalNode.h:1643
NodeType * probeNodeAndCache(const Coord &xyz, AccessorT &)
Same as probeNode() except, if necessary, update the accessor with pointers to the nodes along the pa...
void writeBuffers(std::ostream &, bool toHalf=false) const
Definition InternalNode.h:2849
ValueOnCIter cbeginValueOn() const
Definition InternalNode.h:230
typename ChildNodeType::ValueType ValueType
Definition InternalNode.h:38
Index32 leafCount() const
Definition InternalNode.h:991
const LeafNodeType * probeLeaf(const Coord &xyz) const
void resetChildNode(Index i, ChildNodeType *child)
Definition InternalNode.h:3045
Index32 childCount() const
Definition InternalNode.h:1029
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:1593
Index64 onTileCount() const
Definition InternalNode.h:1084
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:1856
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:3031
void setValueMask(Index n, bool on)
Definition InternalNode.h:765
Index64 offVoxelCount() const
Definition InternalNode.h:1049
typename NodeMaskType::OffIterator MaskOffIterator
Definition InternalNode.h:115
bool isConstant(ValueType &firstValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
Definition InternalNode.h:1487
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:1454
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:2078
static const Index NUM_VALUES
Definition InternalNode.h:47
UnionType mNodes[NUM_VALUES]
Definition InternalNode.h:792
void negate()
Change the sign of all the values represented in this node and its child nodes.
Definition InternalNode.h:2276
void readTopology(std::istream &, bool fromHalf=false)
Definition InternalNode.h:2196
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Definition InternalNode.h:2925
ChildAllCIter beginChildAll() const
Definition InternalNode.h:225
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Definition InternalNode.h:1821
void setValuesOn()
Mark all values (both tiles and voxels) as active.
Definition InternalNode.h:1844
void makeChildNodeEmpty(Index n, const ValueType &value)
Definition InternalNode.h:3086
void setTransientData(Index32 transientData)
Set the transient data value.
Definition InternalNode.h:274
typename ChildNodeType::BuildType BuildType
Definition InternalNode.h:39
LeafNodeType * touchLeafAndCache(const Coord &xyz, AccessorT &)
Same as touchLeaf() except, if necessary, update the accessor with pointers to the nodes along the pa...
void stealNodes(ArrayT &array, const ValueType &value, bool state)
Steals all nodes of a certain type from the tree and adds them to a container with the following API:
Definition InternalNode.h:2984
ChildNodeType * getChildNode(Index n)
Returns a pointer to the child node at the linear offset n.
Definition InternalNode.h:3093
typename NodeMaskType::OnIterator MaskOnIterator
Definition InternalNode.h:114
const LeafNodeType * probeLeafAndCache(const Coord &xyz, AccessorT &acc) const
bool probeValueAndCache(const Coord &xyz, ValueType &value, AccessorT &) const
Definition InternalNode.h:1628
bool addChild(ChildNodeType *child)
Add the given child node at this level deducing the offset from it's origin. If a child node with thi...
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:1108
bool isEmpty() const
Definition InternalNode.h:300
const UnionType * getTable() const
Definition InternalNode.h:760
static void getNodeLog2Dims(std::vector< Index > &dims)
Populated an std::vector with the dimension of all the nodes in the branch starting with this node.
Definition InternalNode.h:2894
ValueOffIter beginValueOff()
Definition InternalNode.h:240
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
Definition InternalNode.h:1659
_ChildNodeType ChildNodeType
Definition InternalNode.h:36
static void offsetToLocalCoord(Index n, Coord &xyz)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0,...
Definition InternalNode.h:2903
const NodeMaskType & getValueMask() const
Definition InternalNode.h:751
const NodeType * probeConstNode(const Coord &xyz) const
bool hasActiveTiles() const
Return true if this node or any of its child nodes have any active tiles.
Definition InternalNode.h:1534
void combine(InternalNode &other, CombineOp &)
Definition InternalNode.h:2647
const ValueType & getValue(const Coord &xyz) const
Definition InternalNode.h:1570
void nodeCount(std::vector< Index32 > &vec) const
Definition InternalNode.h:1003
Index64 memUsage() const
Return the total amount of memory in bytes occupied by this node and its children.
Definition InternalNode.h:1095
ChildNodeType * unsetChildNode(Index i, const ValueType &value)
Definition InternalNode.h:3071
void readBuffers(std::istream &, bool fromHalf=false)
Definition InternalNode.h:2859
typename NodeMaskType::DenseIterator MaskDenseIterator
Definition InternalNode.h:116
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Definition InternalNode.h:1941
ValueAllCIter beginValueAll() const
Definition InternalNode.h:237
Coord mOrigin
Global grid index coordinates (x,y,z) of the local origin of this node.
Definition InternalNode.h:795
static Index dim()
Definition InternalNode.h:246
bool isValueMaskOn(Index n) const
Definition InternalNode.h:744
ValueAllIter beginValueAll()
Definition InternalNode.h:241
const ValueType & getLastValue() const
If the last entry in this node's table is a tile, return the tile's value. Otherwise,...
Definition InternalNode.h:2264
Base class for iterators over internal and leaf nodes.
Definition Iterator.h:30
const ValueT & getValue() const
Definition NodeUnion.h:43
ChildT * getChild() const
Definition NodeUnion.h:40
void setValue(const ValueT &val)
Definition NodeUnion.h:45
Definition NodeMasks.h:271
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation.
Definition NodeMasks.h:308
Index64 Word
Definition NodeMasks.h:316
void toggle(Index32 n)
Toggle the state of the nth bit.
Definition NodeMasks.h:483
void setOff(Index32 n)
Set the nth bit off.
Definition NodeMasks.h:457
void setOn(Index32 n)
Set the nth bit on.
Definition NodeMasks.h:452
Definition NodeMasks.h:240
Definition NodeMasks.h:209
void writeCompressedValues(std::ostream &os, ValueT *srcBuf, Index srcCount, const MaskT &valueMask, const MaskT &childMask, bool toHalf)
Definition Compression.h:645
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
void readCompressedValues(std::istream &is, ValueT *destBuf, Index destCount, const MaskT &valueMask, bool fromHalf)
Definition Compression.h:465
OPENVDB_API const void * getGridBackgroundValuePtr(std::ios_base &)
Return a pointer to the background value of the grid currently being read from or written to the give...
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
Definition Math.h:406
T negative(const T &val)
Return the unary negation of the given value.
Definition Math.h:128
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition Math.h:443
Index32 Index
Definition Types.h:54
uint32_t Index32
Definition Types.h:52
@ OPENVDB_FILE_VERSION_NODE_MASK_COMPRESSION
Definition version.h.in:256
@ OPENVDB_FILE_VERSION_INTERNALNODE_COMPRESSION
Definition version.h.in:247
int32_t Int32
Definition Types.h:56
uint64_t Index64
Definition Types.h:53
@ MERGE_ACTIVE_STATES
Definition Types.h:507
@ MERGE_NODES
Definition Types.h:508
@ MERGE_ACTIVE_STATES_AND_NODES
Definition Types.h:509
Definition Exceptions.h:13
Base class for dense iterators over internal and leaf nodes.
Definition Iterator.h:179
typename std::remove_const< UnsetItemT >::type NonConstValueType
Definition Iterator.h:184
Definition InternalNode.h:129
ChildIter(const MaskIterT &iter, NodeT *parent)
Definition InternalNode.h:131
ChildIter()
Definition InternalNode.h:130
ChildT & getItem(Index pos) const
Definition InternalNode.h:134
void setItem(Index pos, const ChildT &c) const
Definition InternalNode.h:141
Definition InternalNode.h:120
Definition InternalNode.h:120
Definition InternalNode.h:857
DeepCopy(const OtherInternalNode *source, InternalNode *target)
Definition InternalNode.h:858
InternalNode * t
Definition InternalNode.h:872
const OtherInternalNode * s
Definition InternalNode.h:871
void operator()(const tbb::blocked_range< Index > &r) const
Definition InternalNode.h:862
Definition InternalNode.h:172
DenseIter(const MaskDenseIterator &iter, NodeT *parent)
Definition InternalNode.h:177
void unsetItem(Index pos, const ValueT &value) const
Definition InternalNode.h:198
void setItem(Index pos, ChildT *child) const
Definition InternalNode.h:192
DenseIter()
Definition InternalNode.h:176
bool getItem(Index pos, ChildT *&child, NonConstValueT &value) const
Definition InternalNode.h:180
typename BaseT::NonConstValueType NonConstValueT
Definition InternalNode.h:174
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of an Intern...
Definition InternalNode.h:64
Definition InternalNode.h:903
TopologyCopy1(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition InternalNode.h:904
InternalNode * t
Definition InternalNode.h:920
const OtherInternalNode * s
Definition InternalNode.h:919
const ValueType & b
Definition InternalNode.h:921
void operator()(const tbb::blocked_range< Index > &r) const
Definition InternalNode.h:909
Definition InternalNode.h:940
const ValueType & offV
Definition InternalNode.h:958
TopologyCopy2(const OtherInternalNode *source, InternalNode *target, const ValueType &offValue, const ValueType &onValue)
Definition InternalNode.h:941
InternalNode * t
Definition InternalNode.h:957
const OtherInternalNode * s
Definition InternalNode.h:956
void operator()(const tbb::blocked_range< Index > &r) const
Definition InternalNode.h:946
Definition InternalNode.h:2585
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
Definition InternalNode.h:2585
Definition InternalNode.h:2588
void operator()(W &tV, const W &sC, const W &sV, const W &tC) const
Definition InternalNode.h:2588
Definition InternalNode.h:2583
TopologyDifference(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition InternalNode.h:2591
typename NodeMaskType::Word W
Definition InternalNode.h:2584
InternalNode * t
Definition InternalNode.h:2627
const OtherInternalNode * s
Definition InternalNode.h:2626
const ValueType & b
Definition InternalNode.h:2628
void operator()(const tbb::blocked_range< Index > &r) const
Definition InternalNode.h:2605
Definition InternalNode.h:2535
void operator()(W &tC, const W &sC, const W &sV, const W &tV) const
Definition InternalNode.h:2535
Definition InternalNode.h:2533
TopologyIntersection(const OtherInternalNode *source, InternalNode *target, const ValueType &background)
Definition InternalNode.h:2538
typename NodeMaskType::Word W
Definition InternalNode.h:2534
InternalNode * t
Definition InternalNode.h:2567
const OtherInternalNode * s
Definition InternalNode.h:2566
const ValueType & b
Definition InternalNode.h:2568
void operator()(const tbb::blocked_range< Index > &r) const
Definition InternalNode.h:2550
Definition InternalNode.h:2483
void operator()(W &tV, const W &sV, const W &tC) const
Definition InternalNode.h:2483
Definition InternalNode.h:2481
typename NodeMaskType::Word W
Definition InternalNode.h:2482
InternalNode * t
Definition InternalNode.h:2518
const bool mPreserveTiles
Definition InternalNode.h:2519
const OtherInternalNode * s
Definition InternalNode.h:2517
void operator()(const tbb::blocked_range< Index > &r) const
Definition InternalNode.h:2499
TopologyUnion(const OtherInternalNode *source, InternalNode *target, const bool preserveTiles)
Definition InternalNode.h:2486
ValueConverter<T>::Type is the type of an InternalNode having the same child hierarchy and dimensions...
Definition InternalNode.h:55
Definition InternalNode.h:150
void modifyItem(Index pos, const ModifyOp &op) const
Definition InternalNode.h:162
ValueIter(const MaskIterT &iter, NodeT *parent)
Definition InternalNode.h:152
const ValueT & getItem(Index pos) const
Definition InternalNode.h:155
ValueIter()
Definition InternalNode.h:151
void setItem(Index pos, const ValueT &v) const
Definition InternalNode.h:158
Definition InternalNode.h:119
Definition InternalNode.h:119
Definition InternalNode.h:2294
InternalNode * mNode
Definition InternalNode.h:2315
void operator()(const tbb::blocked_range< Index > &r) const
Definition InternalNode.h:2302
VoxelizeActiveTiles(InternalNode &node)
Definition InternalNode.h:2295
Definition InternalNode.h:808
Base class for sparse iterators over internal and leaf nodes.
Definition Iterator.h:115
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:212