4 #ifndef OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
5 #define OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
17 #include <type_traits>
29 template<Index,
typename>
struct SameLeafConfig;
36 template<
typename T, Index Log2Dim>
58 template<
typename OtherValueType>
63 template<
typename OtherNodeType>
97 template<
typename OtherValueType>
101 template<
typename OtherValueType>
106 template<
typename OtherValueType>
172 const Coord&
origin()
const {
return mOrigin; }
190 template<
typename OtherType, Index OtherLog2Dim>
206 template<
typename MaskIterT,
typename NodeT,
typename ValueT,
typename TagT>
211 MaskIterT, ValueIter<MaskIterT, NodeT, ValueT, TagT>, NodeT, ValueT>
224 this->
parent().setValueOnly(pos, value);
229 this->
parent().setValueOnly(this->
pos(), value);
233 template<
typename ModifyOp>
236 template<
typename ModifyOp>
241 template<
typename MaskIterT,
typename NodeT,
typename TagT>
243 public SparseIteratorBase<MaskIterT, ChildIter<MaskIterT, NodeT, TagT>, NodeT, ValueType>
250 template<
typename NodeT,
typename ValueT,
typename TagT>
252 MaskDenseIterator, DenseIter<NodeT, ValueT, TagT>, NodeT, void, ValueT>
262 value = this->
parent().getValue(pos);
273 this->
parent().setValueOnly(pos, value);
348 void readTopology(std::istream& is,
bool fromHalf =
false);
352 void writeTopology(std::ostream& os,
bool toHalf =
false)
const;
357 void readBuffers(std::istream& is,
bool fromHalf =
false);
362 void readBuffers(std::istream& is,
const CoordBBox& bbox,
bool fromHalf =
false);
366 void writeBuffers(std::ostream& os,
bool toHalf =
false)
const;
423 mValueMask.
setOn(offset);
428 template<
typename ModifyOp>
431 mBuffer.loadValues();
432 if (!mBuffer.
empty()) {
436 mValueMask.
setOn(offset);
442 template<
typename ModifyOp>
449 template<
typename ModifyOp>
452 mBuffer.loadValues();
453 if (!mBuffer.
empty()) {
455 bool state = mValueMask.
isOn(offset);
459 mValueMask.
set(offset, state);
480 void fill(
const CoordBBox& bbox,
const ValueType&,
bool active =
true);
484 this->
fill(bbox, value, active);
503 template<
typename DenseT>
504 void copyToDense(
const CoordBBox& bbox, DenseT& dense)
const;
522 template<
typename DenseT>
523 void copyFromDense(
const CoordBBox& bbox,
const DenseT& dense,
528 template<
typename AccessorT>
536 template<
typename AccessorT>
541 template<
typename AccessorT>
550 template<
typename AccessorT>
559 template<
typename ModifyOp,
typename AccessorT>
567 template<
typename ModifyOp,
typename AccessorT>
575 template<
typename AccessorT>
584 template<
typename AccessorT>
593 template<
typename AccessorT>
602 template<
typename AccessorT>
606 state = mValueMask.
isOn(offset);
613 template<
typename AccessorT>
634 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive);
635 template<MergePolicy Policy>
644 template<
typename OtherType>
658 template<
typename OtherType>
672 template<
typename OtherType>
675 template<
typename CombineOp>
677 template<
typename CombineOp>
680 template<
typename CombineOp,
typename OtherType >
681 void combine2(
const LeafNode& other,
const OtherType&,
bool valueIsActive, CombineOp&);
682 template<
typename CombineOp,
typename OtherNodeT >
683 void combine2(
const ValueType&,
const OtherNodeT& other,
bool valueIsActive, CombineOp&);
684 template<
typename CombineOp,
typename OtherNodeT >
694 template<
typename VisitorOp>
void visit(VisitorOp&);
695 template<
typename VisitorOp>
void visit(VisitorOp&)
const;
697 template<
typename OtherLeafNodeType,
typename VisitorOp>
698 void visit2Node(OtherLeafNodeType& other, VisitorOp&);
699 template<
typename OtherLeafNodeType,
typename VisitorOp>
700 void visit2Node(OtherLeafNodeType& other, VisitorOp&)
const;
701 template<
typename IterT,
typename VisitorOp>
702 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false);
703 template<
typename IterT,
typename VisitorOp>
704 void visit2(IterT& otherIter, VisitorOp&,
bool otherIsLHS =
false)
const;
710 template<
typename AccessorT>
712 template<
typename NodeT>
714 template<
typename NodeT>
716 template<
typename NodeT>
718 template<
typename ArrayT>
void getNodes(ArrayT&)
const {}
724 template<
typename AccessorT>
730 template<
typename AccessorT>
732 template<
typename NodeT,
typename AccessorT>
737 return reinterpret_cast<NodeT*
>(
this);
741 template<
typename AccessorT>
747 template<
typename AccessorT>
749 template<
typename AccessorT>
752 template<
typename NodeT,
typename AccessorT>
757 return reinterpret_cast<const NodeT*
>(
this);
772 const ValueType& tolerance = zeroVal<ValueType>())
const;
786 bool& state,
const ValueType& tolerance = zeroVal<ValueType>())
const;
841 friend class ::TestLeaf;
842 template<
typename>
friend class ::TestLeafIO;
884 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
885 static inline void doVisit(NodeT&, VisitorOp&);
887 template<
typename NodeT,
typename OtherNodeT,
typename VisitorOp,
888 typename ChildAllIterT,
typename OtherChildAllIterT>
889 static inline void doVisit2Node(NodeT&
self, OtherNodeT& other, VisitorOp&);
891 template<
typename NodeT,
typename VisitorOp,
892 typename ChildAllIterT,
typename OtherChildAllIterT>
893 static inline void doVisit2(NodeT&
self, OtherChildAllIterT&, VisitorOp&,
bool otherIsLHS);
911 template<Index Dim1,
typename NodeT2>
914 template<Index Dim1,
typename T2>
922 template<
typename T, Index Log2Dim>
931 template<
typename T, Index Log2Dim>
936 mOrigin(xyz & (~(DIM - 1)))
941 template<
typename T, Index Log2Dim>
946 mOrigin(xyz & (~(DIM - 1)))
951 template<
typename T, Index Log2Dim>
954 mBuffer(other.mBuffer),
955 mValueMask(other.valueMask()),
956 mOrigin(other.mOrigin)
962 template<
typename T, Index Log2Dim>
963 template<
typename OtherValueType>
966 mValueMask(other.valueMask()),
967 mOrigin(other.mOrigin)
975 mBuffer[i] = Local::convertValue(other.mBuffer[i]);
980 template<
typename T, Index Log2Dim>
981 template<
typename OtherValueType>
986 mValueMask(other.valueMask()),
987 mOrigin(other.mOrigin)
992 template<
typename T, Index Log2Dim>
993 template<
typename OtherValueType>
997 mValueMask(other.valueMask()),
998 mOrigin(other.mOrigin)
1001 mBuffer[i] = (mValueMask.
isOn(i) ? onValue : offValue);
1006 template<
typename T, Index Log2Dim>
1013 template<
typename T, Index Log2Dim>
1017 std::ostringstream ostr;
1018 ostr <<
"LeafNode @" << mOrigin <<
": " << mBuffer;
1026 template<
typename T, Index Log2Dim>
1030 assert ((xyz[0] & (DIM-1u)) < DIM && (xyz[1] & (DIM-1u)) < DIM && (xyz[2] & (DIM-1u)) < DIM);
1031 return ((xyz[0] & (DIM-1u)) << 2*Log2Dim)
1032 + ((xyz[1] & (DIM-1u)) << Log2Dim)
1033 + (xyz[2] & (DIM-1u));
1036 template<
typename T, Index Log2Dim>
1040 assert(n<(1<< 3*Log2Dim));
1042 xyz.setX(n >> 2*Log2Dim);
1043 n &= ((1<<2*Log2Dim)-1);
1044 xyz.setY(n >> Log2Dim);
1045 xyz.setZ(n & ((1<<Log2Dim)-1));
1050 template<
typename T, Index Log2Dim>
1054 return (this->offsetToLocalCoord(n) + this->origin());
1061 template<
typename ValueT, Index Log2Dim>
1062 inline const ValueT&
1068 template<
typename ValueT, Index Log2Dim>
1069 inline const ValueT&
1072 assert(offset <
SIZE);
1077 template<
typename T, Index Log2Dim>
1084 template<
typename T, Index Log2Dim>
1088 assert(offset <
SIZE);
1090 return mValueMask.isOn(offset);
1094 template<
typename T, Index Log2Dim>
1101 template<
typename T, Index Log2Dim>
1105 assert(offset <
SIZE);
1106 mBuffer.setValue(offset, val);
1107 mValueMask.setOff(offset);
1111 template<
typename T, Index Log2Dim>
1115 mValueMask.set(this->coordToOffset(xyz), on);
1119 template<
typename T, Index Log2Dim>
1126 template<
typename T, Index Log2Dim>
1130 assert(offset<
SIZE); mBuffer.setValue(offset, val);
1137 template<
typename T, Index Log2Dim>
1141 CoordBBox nodeBBox = this->getNodeBoundingBox();
1142 if (!clipBBox.hasOverlap(nodeBBox)) {
1144 this->
fill(background,
false);
1145 }
else if (clipBBox.isInside(nodeBBox)) {
1155 nodeBBox.intersect(clipBBox);
1157 int &
x = xyz.x(), &
y = xyz.y(), &
z = xyz.z();
1158 for (x = nodeBBox.min().x(); x <= nodeBBox.max().x(); ++
x) {
1159 for (
y = nodeBBox.min().y();
y <= nodeBBox.max().y(); ++
y) {
1160 for (
z = nodeBBox.min().z();
z <= nodeBBox.max().z(); ++
z) {
1161 mask.
setOn(static_cast<Index32>(this->coordToOffset(xyz)));
1169 this->setValueOff(maskIter.pos(), background);
1177 template<
typename T, Index Log2Dim>
1183 auto clippedBBox = this->getNodeBoundingBox();
1184 clippedBBox.intersect(bbox);
1185 if (!clippedBBox)
return;
1187 for (
Int32 x = clippedBBox.min().x();
x <= clippedBBox.max().x(); ++
x) {
1188 const Index offsetX = (
x & (DIM-1u)) << 2*Log2Dim;
1189 for (
Int32 y = clippedBBox.min().y();
y <= clippedBBox.max().y(); ++
y) {
1190 const Index offsetXY = offsetX + ((
y & (DIM-1u)) << Log2Dim);
1191 for (
Int32 z = clippedBBox.min().z();
z <= clippedBBox.max().z(); ++
z) {
1194 mValueMask.set(offset, active);
1200 template<
typename T, Index Log2Dim>
1204 mBuffer.fill(value);
1207 template<
typename T, Index Log2Dim>
1211 mBuffer.fill(value);
1212 mValueMask.set(active);
1219 template<
typename T, Index Log2Dim>
1220 template<
typename DenseT>
1224 mBuffer.loadValues();
1226 using DenseValueType =
typename DenseT::ValueType;
1228 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1229 const Coord&
min = dense.bbox().min();
1230 DenseValueType*
t0 = dense.
data() + zStride * (bbox.min()[2] - min[2]);
1231 const T*
s0 = &mBuffer[bbox.min()[2] & (DIM-1u)];
1232 for (
Int32 x = bbox.min()[0], ex = bbox.max()[0] + 1;
x < ex; ++
x) {
1233 DenseValueType*
t1 = t0 + xStride * (
x - min[0]);
1234 const T*
s1 = s0 + ((
x & (DIM-1u)) << 2*Log2Dim);
1235 for (
Int32 y = bbox.min()[1], ey = bbox.max()[1] + 1;
y < ey; ++
y) {
1236 DenseValueType* t2 = t1 + yStride * (
y - min[1]);
1237 const T* s2 = s1 + ((
y & (DIM-1u)) << Log2Dim);
1238 for (
Int32 z = bbox.min()[2], ez = bbox.max()[2] + 1;
z < ez; ++
z, t2 += zStride) {
1239 *t2 = DenseValueType(*s2++);
1246 template<
typename T, Index Log2Dim>
1247 template<
typename DenseT>
1254 using DenseValueType =
typename DenseT::ValueType;
1256 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1257 const Coord&
min = dense.bbox().min();
1259 const DenseValueType*
s0 = dense.
data() + zStride * (bbox.min()[2] - min[2]);
1260 const Int32 n0 = bbox.min()[2] & (DIM-1u);
1261 for (
Int32 x = bbox.min()[0], ex = bbox.max()[0]+1;
x < ex; ++
x) {
1262 const DenseValueType*
s1 = s0 + xStride * (
x - min[0]);
1263 const Int32 n1 = n0 + ((
x & (DIM-1u)) << 2*LOG2DIM);
1264 for (
Int32 y = bbox.min()[1], ey = bbox.max()[1]+1;
y < ey; ++
y) {
1265 const DenseValueType* s2 = s1 + yStride * (
y - min[1]);
1266 Int32 n2 = n1 + ((
y & (DIM-1u)) << LOG2DIM);
1267 for (
Int32 z = bbox.min()[2], ez = bbox.max()[2]+1;
z < ez; ++
z, ++n2, s2 += zStride) {
1269 mValueMask.setOff(n2);
1270 mBuffer[n2] = background;
1272 mValueMask.setOn(n2);
1284 template<
typename T, Index Log2Dim>
1288 mValueMask.load(is);
1292 template<
typename T, Index Log2Dim>
1296 mValueMask.save(os);
1304 template<
typename T, Index Log2Dim>
1310 io::readCompressedValues<ValueType, NodeMaskType>(
1311 is,
nullptr,
SIZE, mValueMask, fromHalf);
1320 template<
typename T, Index Log2Dim>
1324 this->readBuffers(is, CoordBBox::inf(), fromHalf);
1328 template<
typename T, Index Log2Dim>
1333 const bool seekable = meta && meta->seekable();
1335 std::streamoff maskpos = is.tellg();
1339 mValueMask.seek(is);
1342 mValueMask.load(is);
1345 int8_t numBuffers = 1;
1348 is.read(reinterpret_cast<char*>(&mOrigin),
sizeof(Coord::ValueType) * 3);
1351 is.read(reinterpret_cast<char*>(&numBuffers),
sizeof(int8_t));
1354 CoordBBox nodeBBox = this->getNodeBoundingBox();
1355 if (!clipBBox.hasOverlap(nodeBBox)) {
1357 skipCompressedValues(seekable, is, fromHalf);
1358 mValueMask.setOff();
1359 mBuffer.setOutOfCore(
false);
1366 const bool delayLoad = ((mappedFile.get() !=
nullptr) && clipBBox.isInside(nodeBBox));
1369 mBuffer.setOutOfCore(
true);
1370 mBuffer.mFileInfo =
new typename Buffer::FileInfo;
1371 mBuffer.mFileInfo->meta = meta;
1372 mBuffer.mFileInfo->bufpos = is.tellg();
1373 mBuffer.mFileInfo->mapping = mappedFile;
1376 mBuffer.mFileInfo->maskpos = maskpos;
1378 skipCompressedValues(seekable, is, fromHalf);
1382 mBuffer.setOutOfCore(
false);
1385 T background = zeroVal<T>();
1387 background = *
static_cast<const T*
>(bgPtr);
1389 this->
clip(clipBBox, background);
1393 if (numBuffers > 1) {
1398 for (
int i = 1; i < numBuffers; ++i) {
1402 io::readData<T>(is, temp.
mData,
SIZE, zipped);
1408 if (meta) meta->setLeaf(meta->leaf() + 1);
1412 template<
typename T, Index Log2Dim>
1417 mValueMask.save(os);
1419 mBuffer.loadValues();
1429 template<
typename T, Index Log2Dim>
1433 return mOrigin == other.mOrigin &&
1435 mBuffer == other.mBuffer;
1439 template<
typename T, Index Log2Dim>
1445 return sizeof(*this) + mBuffer.memUsage() -
sizeof(mBuffer);
1449 template<
typename T, Index Log2Dim>
1453 CoordBBox this_bbox = this->getNodeBoundingBox();
1454 if (bbox.isInside(this_bbox))
return;
1458 for(; iter; ++iter) this_bbox.expand(
this->offsetToLocalCoord(iter.pos()));
1459 this_bbox.translate(this->origin());
1461 bbox.expand(this_bbox);
1466 template<
typename T, Index Log2Dim>
1467 template<
typename OtherType, Index OtherLog2Dim>
1472 return (Log2Dim == OtherLog2Dim && mValueMask == other->
getValueMask());
1475 template<
typename T, Index Log2Dim>
1481 if (!mValueMask.isConstant(state))
return false;
1482 firstValue = mBuffer[0];
1489 template<
typename T, Index Log2Dim>
1496 if (!mValueMask.isConstant(state))
return false;
1497 minValue = maxValue = mBuffer[0];
1499 const T&
v = mBuffer[i];
1501 if ((maxValue - v) > tolerance)
return false;
1503 }
else if (v > maxValue) {
1504 if ((v - minValue) > tolerance)
return false;
1511 template<
typename T, Index Log2Dim>
1515 std::unique_ptr<T[]>
data(
nullptr);
1516 if (tmp ==
nullptr) {
1517 data.reset(
new T[NUM_VALUES]);
1520 if (tmp != mBuffer.data()) {
1521 const T*
src = mBuffer.data();
1522 for (
T*
dst = tmp;
dst-tmp < NUM_VALUES;) *
dst++ = *src++;
1524 static const size_t midpoint = (NUM_VALUES - 1) >> 1;
1525 std::nth_element(tmp, tmp + midpoint, tmp + NUM_VALUES);
1526 return tmp[midpoint];
1529 template<
typename T, Index Log2Dim>
1534 if (count == NUM_VALUES) {
1535 value = this->medianAll(tmp);
1537 }
else if (count == 0) {
1540 std::unique_ptr<T[]>
data(
nullptr);
1541 if (tmp ==
nullptr) {
1542 data.reset(
new T[count]);
1545 for (
auto iter=this->cbeginValueOn(); iter; ++iter) *tmp++ = *iter;
1547 const size_t midpoint = (count - 1) >> 1;
1548 std::nth_element(begin, begin + midpoint, tmp);
1549 value = begin[midpoint];
1553 template<
typename T, Index Log2Dim>
1558 if (count == NUM_VALUES) {
1559 value = this->medianAll(tmp);
1561 }
else if (count == 0) {
1564 std::unique_ptr<T[]>
data(
nullptr);
1565 if (tmp ==
nullptr) {
1566 data.reset(
new T[count]);
1569 for (
auto iter=this->cbeginValueOff(); iter; ++iter) *tmp++ = *iter;
1571 const size_t midpoint = (count - 1) >> 1;
1572 std::nth_element(begin, begin + midpoint, tmp);
1573 value = begin[midpoint];
1580 template<
typename T, Index Log2Dim>
1584 this->addTile(this->coordToOffset(xyz), val, active);
1587 template<
typename T, Index Log2Dim>
1591 assert(offset <
SIZE);
1592 setValueOnly(offset, val);
1593 setActiveState(offset, active);
1596 template<
typename T, Index Log2Dim>
1597 template<
typename AccessorT>
1602 this->addTile(level, xyz, val, active);
1609 template<
typename T, Index Log2Dim>
1618 for (iter = this->mValueMask.beginOff(); iter; ++iter) {
1621 inactiveValue = newBackground;
1629 template<
typename T, Index Log2Dim>
1630 template<MergePolicy Policy>
1639 for (; iter; ++iter) {
1641 if (mValueMask.isOff(n)) {
1642 mBuffer[
n] = other.mBuffer[
n];
1643 mValueMask.setOn(n);
1649 template<
typename T, Index Log2Dim>
1650 template<MergePolicy Policy>
1655 this->
template merge<Policy>(other);
1658 template<
typename T, Index Log2Dim>
1659 template<MergePolicy Policy>
1667 if (!tileActive)
return;
1670 const Index n = iter.pos();
1671 mBuffer[
n] = tileValue;
1672 mValueMask.setOn(n);
1678 template<
typename T, Index Log2Dim>
1679 template<
typename OtherType>
1686 template<
typename T, Index Log2Dim>
1687 template<
typename OtherType>
1695 template<
typename T, Index Log2Dim>
1696 template<
typename OtherType>
1704 template<
typename T, Index Log2Dim>
1711 mBuffer[i] = -mBuffer[i];
1719 template<
typename T, Index Log2Dim>
1720 template<
typename CombineOp>
1729 .setAIsActive(mValueMask.isOn(i))
1730 .setBRef(other.mBuffer[i])
1732 .setResultRef(mBuffer[i]));
1738 template<
typename T, Index Log2Dim>
1739 template<
typename CombineOp>
1746 args.
setBRef(value).setBIsActive(valueIsActive);
1749 .setAIsActive(mValueMask.isOn(i))
1750 .setResultRef(mBuffer[i]));
1759 template<
typename T, Index Log2Dim>
1760 template<
typename CombineOp,
typename OtherType>
1763 bool valueIsActive, CombineOp& op)
1768 args.
setBRef(value).setBIsActive(valueIsActive);
1770 op(args.
setARef(other.mBuffer[i])
1772 .setResultRef(mBuffer[i]));
1778 template<
typename T, Index Log2Dim>
1779 template<
typename CombineOp,
typename OtherNodeT>
1782 bool valueIsActive, CombineOp& op)
1787 args.
setARef(value).setAIsActive(valueIsActive);
1789 op(args.
setBRef(other.mBuffer[i])
1790 .setBIsActive(other.valueMask().isOn(i))
1791 .setResultRef(mBuffer[i]));
1797 template<
typename T, Index Log2Dim>
1798 template<
typename CombineOp,
typename OtherNodeT>
1806 mValueMask.set(i, b0.
valueMask().
isOn(i) || b1.valueMask().isOn(i));
1807 op(args.
setARef(b0.mBuffer[i])
1809 .setBRef(b1.mBuffer[i])
1810 .setBIsActive(b1.valueMask().isOn(i))
1811 .setResultRef(mBuffer[i]));
1820 template<
typename T, Index Log2Dim>
1821 template<
typename BBoxOp>
1825 if (op.template descent<LEVEL>()) {
1827 op.template operator()<LEVEL>(CoordBBox::createCube(i.getCoord(), 1));
1830 op.template operator()<LEVEL>(this->getNodeBoundingBox());
1835 template<
typename T, Index Log2Dim>
1836 template<
typename VisitorOp>
1840 doVisit<LeafNode, VisitorOp, ChildAllIter>(*
this, op);
1844 template<
typename T, Index Log2Dim>
1845 template<
typename VisitorOp>
1849 doVisit<const LeafNode, VisitorOp, ChildAllCIter>(*
this, op);
1853 template<
typename T, Index Log2Dim>
1854 template<
typename NodeT,
typename VisitorOp,
typename ChildAllIterT>
1858 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
1867 template<
typename T, Index Log2Dim>
1868 template<
typename OtherLeafNodeType,
typename VisitorOp>
1873 typename OtherLeafNodeType::ChildAllIter>(*
this, other, op);
1877 template<
typename T, Index Log2Dim>
1878 template<
typename OtherLeafNodeType,
typename VisitorOp>
1883 typename OtherLeafNodeType::ChildAllCIter>(*
this, other, op);
1887 template<
typename T, Index Log2Dim>
1890 typename OtherNodeT,
1892 typename ChildAllIterT,
1893 typename OtherChildAllIterT>
1899 "can't visit nodes of different sizes simultaneously");
1900 static_assert(OtherNodeT::LEVEL == NodeT::LEVEL,
1901 "can't visit nodes at different tree levels simultaneously");
1903 ChildAllIterT iter =
self.beginChildAll();
1904 OtherChildAllIterT otherIter = other.beginChildAll();
1906 for ( ; iter && otherIter; ++iter, ++otherIter) {
1907 op(iter, otherIter);
1915 template<
typename T, Index Log2Dim>
1916 template<
typename IterT,
typename VisitorOp>
1920 doVisit2<LeafNode, VisitorOp, ChildAllIter, IterT>(
1921 *
this, otherIter, op, otherIsLHS);
1925 template<
typename T, Index Log2Dim>
1926 template<
typename IterT,
typename VisitorOp>
1930 doVisit2<const LeafNode, VisitorOp, ChildAllCIter, IterT>(
1931 *
this, otherIter, op, otherIsLHS);
1935 template<
typename T, Index Log2Dim>
1939 typename ChildAllIterT,
1940 typename OtherChildAllIterT>
1943 VisitorOp& op,
bool otherIsLHS)
1945 if (!otherIter)
return;
1948 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
1949 op(otherIter, iter);
1952 for (ChildAllIterT iter =
self.beginChildAll(); iter; ++iter) {
1953 op(iter, otherIter);
1962 template<
typename T, Index Log2Dim>
1963 inline std::ostream&
1964 operator<<(std::ostream& os, const typename LeafNode<T, Log2Dim>::Buffer&
buf)
1966 for (
Index32 i = 0,
N =
buf.size(); i <
N; ++i) os <<
buf.mData[i] <<
", ";
1984 #endif // OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
typename NodeMaskType::OnIterator MaskOnIterator
NodeT * stealNode(const Coord &, const ValueType &, bool)
This function exists only to enable template instantiation.
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...
void merge(const LeafNode &)
OPENVDB_API SharedPtr< MappedFile > getMappedFilePtr(std::ios_base &)
Return a shared pointer to the memory-mapped file with which the given stream is associated, or a null pointer if the stream is not associated with a memory-mapped file.
Leaf nodes have no children, so their child iterators have no get/set accessors.
void stealNodes(ArrayT &, const ValueType &, bool)
This function exists only to enable template instantiation.
static const Index NUM_VOXELS
This struct collects both input and output arguments to "grid combiner" functors used with the tree::...
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...
ValueAllCIter cbeginValueAll() const
void setValueOff(Index offset)
Mark the voxel at the given offset as inactive but don't change its value.
const NodeMaskType & valueMask() const
const ValueType & getFirstValue() const
Return a const reference to the first value in the buffer.
ChildOffCIter cendChildOff() const
ValueOffCIter beginValueOff() const
Index32 countOn() const
Return the total number of on bits.
void readBuffers(std::istream &is, bool fromHalf=false)
Read buffers from a stream.
bool isChildMaskOff() const
NodeMaskType & getValueMask()
bool isValueMaskOn() const
bool isValueOnAndCache(const Coord &xyz, AccessorT &) const
Return true if the voxel at the given coordinates is active.
ChildAllCIter endChildAll() const
ChildIter< MaskOffIterator, LeafNode, ChildOff > ChildOffIter
void setValueOnly(const Coord &xyz, const ValueType &val)
Set the value of the voxel at the given coordinates but don't change its active state.
void readTopology(std::istream &is, bool fromHalf=false)
Read in just the topology.
void setValueAndCache(const Coord &xyz, const ValueType &val, AccessorT &)
Change the value of the voxel at the given coordinates and mark it as active.
void setActiveState(Index offset, bool on)
Set the active state of the voxel at the given offset but don't change its value. ...
ChildOnIter beginChildOn()
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
ChildAllIter beginChildAll()
static bool hasActiveTiles()
Return false since leaf nodes never contain tiles.
FMT_CONSTEXPR auto begin(const C &c) -> decltype(c.begin())
ChildAllCIter cendChildAll() const
void setValueOn(const Coord &xyz)
Mark the voxel at the given coordinates as active but don't change its value.
T negative(const T &val)
Return the unary negation of the given value.
bool isDense() const
Return true if this node contains only active voxels.
bool isConstant(ValueType &firstValue, bool &state, const ValueType &tolerance=zeroVal< ValueType >()) const
LeafNode * probeLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
ValueOffCIter cbeginValueOff() const
ImageBuf OIIO_API fill(cspan< float > values, ROI roi, int nthreads=0)
GLuint const GLfloat * val
ChildOnCIter cbeginChildOn() const
void writeCompressedValues(std::ostream &os, ValueT *srcBuf, Index srcCount, const MaskT &valueMask, const MaskT &childMask, bool toHalf)
static const Index NUM_VALUES
static void doVisit(NodeT &, VisitorOp &)
void setValueOn(Index offset)
Mark the voxel at the given offset as active but don't change its value.
ValueAllCIter cendValueAll() const
OPENVDB_API uint32_t getDataCompression(std::ios_base &)
Return a bitwise OR of compression option flags (COMPRESS_ZIP, COMPRESS_ACTIVE_MASK, etc.) specifying whether and how input data is compressed or output data should be compressed.
static Index32 childCount()
Return the child count for this node, which is zero.
void setOff(Index32 n)
Set the nth bit off.
Index pos() const
Identical to offset.
const LeafNode * probeConstLeafAndCache(const Coord &, AccessorT &) const
Return a pointer to this node.
bool getItem(Index pos, void *&child, NonConstValueT &value) const
DenseIterator endDense() const
Index64 memUsage() const
Return the memory in bytes occupied by this node.
static Index size()
Return the total number of voxels represented by this LeafNode.
ValueIter(const MaskIterT &iter, NodeT *parent)
util::NodeMask< Log2Dim > NodeMaskType
#define OPENVDB_USE_VERSION_NAMESPACE
SameConfiguration<OtherNodeType>::value is true if and only if OtherNodeType is the type of a LeafNod...
ChildOffCIter cbeginChildOff() const
ChildOffCIter endChildOff() const
bool isValueOn(Index offset) const
Return true if the voxel at the given offset is active.
Base class for iterators over internal and leaf nodes.
ValueOffIter endValueOff()
ChildIter< MaskOnIterator, const LeafNode, ChildOn > ChildOnCIter
ValueOffCIter endValueOff() const
const NodeT * probeConstNodeAndCache(const Coord &, AccessorT &) const
Return a pointer to this node.
ValueT & getItem(Index pos) const
ChildIter< MaskOnIterator, LeafNode, ChildOn > ChildOnIter
DenseIterator beginDense() const
SharedPtr< MappedFile > Ptr
void clip(const CoordBBox &, const ValueType &background)
Set all voxels that lie outside the given axis-aligned box to the background.
bool empty() const
Return true if memory for this buffer has not yet been allocated.
void topologyUnion(const LeafNode< OtherType, Log2Dim > &other)
Union this node's set of active values with the active values of the other node, whose ValueType may ...
NodeT & parent() const
Return a reference to the node over which this iterator is iterating.
void modifyValue(const ModifyOp &op) const
ValueOnCIter endValueOn() const
void topologyIntersection(const LeafNode< OtherType, Log2Dim > &other, const ValueType &)
Intersect 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 both of the original voxels were active.
void read(T &in, bool &v)
LeafBuffer< ValueType, Log2Dim > Buffer
bool probeValueAndCache(const Coord &xyz, ValueType &val, AccessorT &) const
Return true if the voxel at the given coordinates is active and return the voxel value in val...
bool isEmpty() const
Return true if this node has no active voxels.
ValueAllCIter endValueAll() const
Index64 offLeafVoxelCount() const
NodeT * probeNode(const Coord &)
This function exists only to enable template instantiation.
Tag dispatch class that distinguishes constructors during file input.
ValueOnCIter cbeginValueOn() const
ChildAllCIter cbeginChildAll() const
void setActiveState(const Coord &xyz, bool on)
Set the active state of the voxel at the given coordinates but don't change its value.
void setValuesOn()
Mark all voxels as active but don't change their values.
ValueIter< MaskOffIterator, const LeafNode, const ValueType, ValueOff > ValueOffCIter
Index64 onLeafVoxelCount() const
void setValueOffAndCache(const Coord &xyz, const ValueType &value, AccessorT &)
Change the value of the voxel at the given coordinates and mark it as inactive.
static Index getLevel()
Return the level of this node, which by definition is zero for LeafNodes.
static Coord offsetToLocalCoord(Index n)
Return the local coordinates for a linear table offset, where offset 0 has coordinates (0...
bool isChildMaskOn(Index) const
static Index numValues()
Return the total number of voxels represented by this LeafNode.
Index32 countOff() const
Return the total number of on bits.
static void evalNodeOrigin(Coord &xyz)
Compute the origin of the leaf node that contains the voxel with the given coordinates.
void writeBuffers(std::ostream &os, bool toHalf=false) const
Write buffers to a stream.
ValueIter< MaskDenseIterator, LeafNode, const ValueType, ValueAll > ValueAllIter
ValueAllIter endValueAll()
void denseFill(const CoordBBox &bbox, const ValueType &value, bool active=true)
Set all voxels within an axis-aligned box to the specified value and active state.
void readCompressedValues(std::istream &is, ValueT *destBuf, Index destCount, const MaskT &valueMask, bool fromHalf)
void getOrigin(Int32 &x, Int32 &y, Int32 &z) const
Return the grid index coordinates of this node's local origin.
std::shared_ptr< T > SharedPtr
const LeafNode * probeConstLeaf(const Coord &) const
Return a pointer to this node.
bool isValueOn(const Coord &xyz) const
Return true if the voxel at the given coordinates is active.
const ValueType & getLastValue() const
Return a const reference to the last value in the buffer.
bool isChildMaskOff(Index) const
static Index64 onTileCount()
void addLeaf(LeafNode *)
This function exists only to enable template instantiation.
void modifyValue(Index offset, const ModifyOp &op)
Apply a functor to the value of the voxel at the given offset and mark the voxel as active...
ValueOnCIter cendValueOn() const
void nodeCount(std::vector< Index32 > &) const
no-op
void addLeafAndCache(LeafNode *, AccessorT &)
This function exists only to enable template instantiation.
void setOrigin(const Coord &origin)
Set the grid index coordinates of this node's local origin.
OffMaskIterator< NodeMask > OffIterator
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
static Index log2dim()
Return log2 of the dimension of this LeafNode, e.g. 3 if dimensions are 8^3.
ChildOffCIter beginChildOff() const
GLint GLint GLint GLint GLint x
bool isValueMaskOff(Index n) const
GLint GLint GLint GLint GLint GLint y
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...
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &)
Set the active state of the voxel at the given coordinates without changing its value.
NodeT * probeNodeAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
bool isValueMaskOn(Index n) const
bool isOn(Index32 n) const
Return true if the nth bit is on.
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation. ...
void swap(LeafBuffer &)
Exchange this buffer's values with the other buffer's values.
ChildOnCIter endChildOn() const
*But if you need a or simply need to know when the task has note that the like this
void addTile(Index level, const Coord &, const ValueType &, bool)
Index64 onVoxelCount() const
Return the number of voxels marked On.
void setValue(const ValueT &value) const
bool resultIsActive() const
bool isValueMaskOff() const
GLint GLenum GLsizei GLint GLsizei const void * data
ValueT & getValue() const
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim...
LeafNode * touchLeaf(const Coord &)
Return a pointer to this node.
void topologyDifference(const LeafNode< OtherType, Log2Dim > &other, const ValueType &)
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 LeafNode and inactive in the other LeafNode.
ChildOnCIter beginChildOn() const
bool allocate()
Allocate memory for this buffer if it has not already been allocated.
ValueIter< MaskOnIterator, LeafNode, const ValueType, ValueOn > ValueOnIter
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.
void modifyItem(Index n, const ModifyOp &op) const
ValueOffIter beginValueOff()
DenseIter(const MaskDenseIterator &iter, NodeT *parent)
const NodeMaskType & getValueMask() const
bool operator!=(const LeafNode &other) const
ChildOnCIter cendChildOn() const
std::string str() const
Return a string representation of this node.
void set(Index32 n, bool On)
Set the nth bit to the specified state.
OnIterator beginOn() const
typename std::remove_const< UnsetItemT >::type NonConstValueType
ChildOffIter endChildOff()
ValueOnIter beginValueOn()
void resetBackground(const ValueType &oldBackground, const ValueType &newBackground)
Replace inactive occurrences of oldBackground with newBackground, and inactive occurrences of -oldBac...
ValueType medianAll(ValueType *tmp=nullptr) const
Computes the median value of all the active AND inactive voxels in this node.
static const Index LOG2DIM
static Index getChildDim()
Return the dimension of child nodes of this LeafNode, which is one for voxels.
void setOn(Index32 n)
Set the nth bit on.
void setValueOff(const Coord &xyz)
Mark the voxel at the given coordinates as inactive but don't change its value.
ChildAllIter endChildAll()
typename BaseT::NonConstValueType NonConstValueT
Index64 offVoxelCount() const
Return the number of voxels marked Off.
typename NodeMaskType::DenseIterator MaskDenseIterator
static Index getValueLevelAndCache(const Coord &, AccessorT &)
Return the LEVEL (=0) at which leaf node values reside.
static Index getValueLevel(const Coord &)
Return the level (i.e., 0) at which leaf node values reside.
const value_t * data() const
Return a pointer to the underlying scalar type.
const Coord & origin() const
Return the grid index coordinates of this node's local origin.
void modifyValueAndActiveState(const Coord &xyz, const ModifyOp &op)
Apply a functor to the voxel at the given coordinates.
OffIterator beginOff() const
void getOrigin(Coord &origin) const
Return the grid index coordinates of this node's local origin.
static Index dim()
Return the number of voxels in each coordinate dimension.
static Index32 leafCount()
Return the leaf count for this node, which is one.
void setValueMask(Index n, bool on)
Coord offsetToGlobalCoord(Index n) const
Return the global coordinates for a linear table offset.
Base class for sparse iterators over internal and leaf nodes.
void combine2(const LeafNode &other, const OtherType &, bool valueIsActive, CombineOp &)
Index medianOn(ValueType &value, ValueType *tmp=nullptr) const
Computes the median value of all the active voxels in this node.
void setValueOnlyAndCache(const Coord &xyz, const ValueType &val, AccessorT &)
Change the value of the voxel at the given coordinates but preserve its state.
CoordBBox getNodeBoundingBox() const
Return the bounding box of this node, i.e., the full index space spanned by this leaf node...
LeafNode()
Default constructor.
void visit2Node(OtherLeafNodeType &other, VisitorOp &)
Base class for dense iterators over internal and leaf nodes.
GLsizei const GLchar *const * string
OffIterator endOff() const
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
Allocator::value_type * allocate(Allocator &alloc, std::size_t n)
void prune(const ValueType &=zeroVal< ValueType >())
This function exists only to enable template instantiation.
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER T clip(const T &p, const Box< T > &box)
DenseMaskIterator< NodeMask > DenseIterator
ValueIter< MaskOnIterator, const LeafNode, const ValueType, ValueOn > ValueOnCIter
void setItem(Index pos, const ValueT &value) const
const ValueType & getValueAndCache(const Coord &xyz, AccessorT &) const
Return the value of the voxel at the given coordinates.
ValueAllIter beginValueAll()
bool probeValue(const Coord &xyz, ValueType &val) const
Return true if the voxel at the given coordinates is active.
CombineArgs & setBRef(const BValueType &b)
Redirect the B value to a new external source.
void combine(const LeafNode &other, CombineOp &op)
void setValueOn(const Coord &xyz, const ValueType &val)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
Index medianOff(ValueType &value, ValueType *tmp=nullptr) const
Computes the median value of all the inactive voxels in this node.
void addTileAndCache(Index, const Coord &, const ValueType &, bool, AccessorT &)
bool isOutOfCore() const
Return true if this buffer's values have not yet been read from disk.
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
ValueIter< MaskDenseIterator, const LeafNode, const ValueType, ValueAll > ValueAllCIter
OnMaskIterator< NodeMask > OnIterator
const NodeT * probeConstNode(const Coord &) const
This function exists only to enable template instantiation.
GLuint GLuint GLsizei count
ValueOffCIter cendValueOff() const
const LeafNode * probeLeafAndCache(const Coord &, AccessorT &) const
Return a pointer to this node.
const ValueType & getValue(const Coord &xyz, bool &state, int &level, AccessorT &) const
Return the value of the voxel at the given coordinates and return its active state and level (i...
void setValueMask(const NodeMaskType &mask)
GA_API const UT_StringHolder N
void skipCompressedValues(bool seekable, std::istream &, bool fromHalf)
bool isInactive() const
Return true if all of this node's values are inactive.
static void getNodeLog2Dims(std::vector< Index > &dims)
Append the Log2Dim of this LeafNode to the specified vector.
void setValueMaskOff(Index n)
void setValueOn(Index offset, const ValueType &val)
Set the value of the voxel at the given offset and mark the voxel as active.
ValueConverter<T>::Type is the type of a LeafNode having the same dimensions as this node but a diffe...
LeafNode & operator=(const LeafNode &)=default
Deep assignment operator.
CombineArgs & setARef(const AValueType &a)
Redirect the A value to a new external source.
OPENVDB_API SharedPtr< StreamMetadata > getStreamMetadataPtr(std::ios_base &)
Return a shared pointer to an object that stores metadata (file format, compression scheme...
void setValue(const Coord &xyz, const ValueType &val)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
void unsetItem(Index pos, const ValueT &value) const
void copyFromDense(const CoordBBox &bbox, const DenseT &dense, const ValueType &background, const ValueType &tolerance)
Copy from a dense grid into this node the values of the voxels that lie within a given bounding box...
size_t streamingSize(bool toHalf=false) const
void visit2(IterT &otherIter, VisitorOp &, bool otherIsLHS=false)
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
bool isAllocated() const
Return true if memory for this node's buffer has been allocated.
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s0
void visitActiveBBox(BBoxOp &) const
Calls the templated functor BBoxOp with bounding box information. An additional level argument is pro...
void setValuesOff()
Mark all voxels as inactive but don't change their values.
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
void voxelizeActiveTiles(bool=true)
No-op.
ChildIter(const MaskIterT &iter, NodeT *parent)
SharedPtr< LeafNode > Ptr
void setValue(Index i, const ValueType &)
Set the i'th value of this buffer to the specified value.
DenseIter< const LeafNode, const ValueType, ChildAll > ChildAllCIter
vint4 min(const vint4 &a, const vint4 &b)
bool hasSameTopology(const LeafNode< OtherType, OtherLog2Dim > *other) const
Return true if the given node (which may have a different ValueType than this node) has the same acti...
ChildOffIter beginChildOff()
bool operator==(const LeafNode &other) const
Check for buffer, state and origin equivalence.
ValueOnCIter beginValueOn() const
const Buffer & buffer() const
GLenum GLuint GLsizei const GLchar * buf
typename NodeMaskType::OffIterator MaskOffIterator
bool allocate()
Allocate memory for this node's buffer if it has not already been allocated.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
GLsizei const GLfloat * value
void evalActiveBoundingBox(CoordBBox &bbox, bool visitVoxels=true) const
static Index coordToOffset(const Coord &xyz)
Return the linear table offset of the given global or local coordinates.
ValueAllCIter beginValueAll() const
void getNodes(ArrayT &) const
This function exists only to enable template instantiation.
OPENVDB_API uint32_t getFormatVersion(std::ios_base &)
Return the file format version number associated with the given input stream.
static Index64 offTileCount()
static void doVisit2(NodeT &self, OtherChildAllIterT &, VisitorOp &, bool otherIsLHS)
LeafNode * probeLeaf(const Coord &)
Return a pointer to this node.
void setValueMaskOn(Index n)
ChildIter< MaskOffIterator, const LeafNode, ChildOff > ChildOffCIter
const LeafNode * probeLeaf(const Coord &) const
Return a pointer to this node.
ChildAllCIter beginChildAll() const
void writeTopology(std::ostream &os, bool toHalf=false) const
Write out just the topology.
bool isOff(Index32 n) const
Return true if the nth bit is off.
static Index32 nonLeafCount()
Return the non-leaf count for this node, which is zero.
DenseIter< LeafNode, ValueType, ChildAll > ChildAllIter
ValueIter< MaskOffIterator, LeafNode, const ValueType, ValueOff > ValueOffIter
void swap(Buffer &other)
Exchange this node's data buffer with the given data buffer without changing the active states of the...
void fill(const CoordBBox &bbox, const ValueType &, bool active=true)
Set all voxels within an axis-aligned box to the specified value and active state.
static void doVisit2Node(NodeT &self, OtherNodeT &other, VisitorOp &)
LeafNode * touchLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.