4 #ifndef OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
5 #define OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
18 #include <type_traits>
30 template<Index,
typename>
struct SameLeafConfig;
37 template<
typename T, Index Log2Dim>
59 template<
typename OtherValueType>
64 template<
typename OtherNodeType>
98 template<
typename OtherValueType>
102 template<
typename OtherValueType>
107 template<
typename OtherValueType>
176 const Coord&
origin()
const {
return mOrigin; }
195 std::string
str()
const;
199 template<
typename OtherType, Index OtherLog2Dim>
215 template<
typename MaskIterT,
typename NodeT,
typename ValueT,
typename TagT>
220 MaskIterT, ValueIter<MaskIterT, NodeT, ValueT, TagT>, NodeT, ValueT>
222 using ValueType = std::conditional_t<std::is_const_v<NodeT>, ValueT,
223 std::remove_const_t<ValueT>>;
228 :
BaseT(iter, parent)
240 if constexpr (std::is_const_v<NodeT>) {
241 static_assert(!std::is_const_v<NodeT>,
242 "ValueIter::setItem cannot be called on const iterators");
252 template<
typename ModifyOp>
255 if constexpr (std::is_const_v<NodeT>) {
256 static_assert(!std::is_const_v<NodeT>,
257 "ValueIter::modifyItem cannot be called on const iterators");
261 this->
parent().setValueOn(n);
265 template<
typename ModifyOp>
275 template<
typename MaskIterT,
typename NodeT,
typename TagT>
277 public SparseIteratorBase<MaskIterT, ChildIter<MaskIterT, NodeT, TagT>, NodeT, ValueType>
284 template<
typename NodeT,
typename ValueT,
typename TagT>
286 MaskDenseIterator, DenseIter<NodeT, ValueT, TagT>, NodeT, void, ValueT>
296 value = this->
parent().getValue(pos);
307 this->
parent().setValueOnly(pos, value);
382 void readTopology(std::istream& is,
bool fromHalf =
false);
386 void writeTopology(std::ostream& os,
bool toHalf =
false)
const;
391 void readBuffers(std::istream& is,
bool fromHalf =
false);
400 void writeBuffers(std::ostream& os,
bool toHalf =
false)
const;
457 mValueMask.
setOn(offset);
462 template<
typename ModifyOp>
465 mBuffer.loadValues();
466 if (!mBuffer.
empty()) {
470 mValueMask.
setOn(offset);
476 template<
typename ModifyOp>
483 template<
typename ModifyOp>
486 mBuffer.loadValues();
487 if (!mBuffer.
empty()) {
493 mValueMask.
set(offset, state);
541 template<
typename DenseT>
560 template<
typename DenseT>
566 template<
typename AccessorT>
574 template<
typename AccessorT>
579 template<
typename AccessorT>
588 template<
typename AccessorT>
597 template<
typename ModifyOp,
typename AccessorT>
605 template<
typename ModifyOp,
typename AccessorT>
613 template<
typename AccessorT>
622 template<
typename AccessorT>
631 template<
typename AccessorT>
640 template<
typename AccessorT>
644 state = mValueMask.
isOn(offset);
651 template<
typename AccessorT>
672 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive);
673 template<MergePolicy Policy>
682 template<
typename OtherType>
696 template<
typename OtherType>
710 template<
typename OtherType>
713 template<
typename CombineOp>
715 template<
typename CombineOp>
718 template<
typename CombineOp,
typename OtherType >
719 void combine2(
const LeafNode& other,
const OtherType&,
bool valueIsActive, CombineOp&);
720 template<
typename CombineOp,
typename OtherNodeT >
721 void combine2(
const ValueType&,
const OtherNodeT& other,
bool valueIsActive, CombineOp&);
722 template<
typename CombineOp,
typename OtherNodeT >
729 template<
typename AccessorT>
731 template<
typename NodeT>
733 template<
typename NodeT>
735 template<
typename NodeT>
737 template<
typename ArrayT>
void getNodes(ArrayT&)
const {}
743 template<
typename AccessorT>
749 template<
typename AccessorT>
751 template<
typename NodeT,
typename AccessorT>
756 return reinterpret_cast<NodeT*
>(
this);
760 template<
typename AccessorT>
766 template<
typename AccessorT>
768 template<
typename AccessorT>
771 template<
typename NodeT,
typename AccessorT>
776 return reinterpret_cast<const NodeT*
>(
this);
791 const ValueType& tolerance = zeroVal<ValueType>())
const;
805 bool& state,
const ValueType& tolerance = zeroVal<ValueType>())
const;
883 friend class ::TestLeaf;
884 template<
typename>
friend class ::TestLeafIO;
944 template<Index Dim1,
typename NodeT2>
947 template<Index Dim1,
typename T2>
955 template<
typename T, Index Log2Dim>
964 template<
typename T, Index Log2Dim>
969 mOrigin(xyz & (~(DIM - 1)))
974 template<
typename T, Index Log2Dim>
979 mOrigin(xyz & (~(DIM - 1)))
984 template<
typename T, Index Log2Dim>
987 : mBuffer(other.mBuffer)
989 , mOrigin(other.mOrigin)
990 , mTransientData(other.mTransientData)
996 template<
typename T, Index Log2Dim>
997 template<
typename OtherValueType>
1001 , mOrigin(other.mOrigin)
1002 , mTransientData(other.mTransientData)
1010 mBuffer[i] = Local::convertValue(other.mBuffer[i]);
1015 template<
typename T, Index Log2Dim>
1016 template<
typename OtherValueType>
1020 : mBuffer(background)
1022 , mOrigin(other.mOrigin)
1023 , mTransientData(other.mTransientData)
1028 template<
typename T, Index Log2Dim>
1029 template<
typename OtherValueType>
1034 , mOrigin(other.mOrigin)
1035 , mTransientData(other.mTransientData)
1038 mBuffer[i] = (mValueMask.
isOn(i) ? onValue : offValue);
1043 template<
typename T, Index Log2Dim>
1050 template<
typename T, Index Log2Dim>
1054 std::ostringstream ostr;
1055 ostr <<
"LeafNode @" << mOrigin <<
": " << mBuffer;
1063 template<
typename T, Index Log2Dim>
1067 OPENVDB_ASSERT((xyz[0] & (DIM-1u)) < DIM && (xyz[1] & (DIM-1u)) < DIM && (xyz[2] & (DIM-1u)) < DIM);
1068 return ((xyz[0] & (DIM-1u)) << 2*Log2Dim)
1069 + ((xyz[1] & (DIM-1u)) << Log2Dim)
1070 + (xyz[2] & (DIM-1u));
1073 template<
typename T, Index Log2Dim>
1079 xyz.setX(n >> 2*Log2Dim);
1080 n &= ((1<<2*Log2Dim)-1);
1081 xyz.setY(n >> Log2Dim);
1082 xyz.setZ(n & ((1<<Log2Dim)-1));
1087 template<
typename T, Index Log2Dim>
1091 return (this->offsetToLocalCoord(n) + this->origin());
1098 template<
typename ValueT, Index Log2Dim>
1099 inline const ValueT&
1105 template<
typename ValueT, Index Log2Dim>
1106 inline const ValueT&
1114 template<
typename T, Index Log2Dim>
1121 template<
typename T, Index Log2Dim>
1131 template<
typename T, Index Log2Dim>
1138 template<
typename T, Index Log2Dim>
1143 mBuffer.setValue(offset, val);
1148 template<
typename T, Index Log2Dim>
1152 mValueMask.set(this->coordToOffset(xyz), on);
1156 template<
typename T, Index Log2Dim>
1163 template<
typename T, Index Log2Dim>
1174 template<
typename T, Index Log2Dim>
1178 CoordBBox nodeBBox = this->getNodeBoundingBox();
1179 if (!clipBBox.hasOverlap(nodeBBox)) {
1181 this->
fill(background,
false);
1182 }
else if (clipBBox.isInside(nodeBBox)) {
1192 nodeBBox.intersect(clipBBox);
1194 int &
x = xyz.x(), &
y = xyz.y(), &
z = xyz.z();
1195 for (x = nodeBBox.min().x(); x <= nodeBBox.max().x(); ++
x) {
1196 for (
y = nodeBBox.min().y();
y <= nodeBBox.max().y(); ++
y) {
1197 for (
z = nodeBBox.min().z();
z <= nodeBBox.max().z(); ++
z) {
1198 mask.
setOn(static_cast<Index32>(this->coordToOffset(xyz)));
1206 this->setValueOff(maskIter.pos(), background);
1214 template<
typename T, Index Log2Dim>
1218 if (!this->allocate())
return;
1220 auto clippedBBox = this->getNodeBoundingBox();
1221 clippedBBox.intersect(bbox);
1222 if (!clippedBBox)
return;
1224 for (
Int32 x = clippedBBox.min().x();
x <= clippedBBox.max().x(); ++
x) {
1225 const Index offsetX = (
x & (DIM-1u)) << 2*Log2Dim;
1226 for (
Int32 y = clippedBBox.min().y();
y <= clippedBBox.max().y(); ++
y) {
1227 const Index offsetXY = offsetX + ((
y & (DIM-1u)) << Log2Dim);
1228 for (
Int32 z = clippedBBox.min().z();
z <= clippedBBox.max().z(); ++
z) {
1237 template<
typename T, Index Log2Dim>
1241 mBuffer.fill(value);
1244 template<
typename T, Index Log2Dim>
1248 mBuffer.fill(value);
1256 template<
typename T, Index Log2Dim>
1257 template<
typename DenseT>
1261 mBuffer.loadValues();
1265 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1266 const Coord&
min = dense.bbox().min();
1267 DenseValueType* t0 = dense.data() + zStride * (bbox.min()[2] - min[2]);
1268 const T* s0 = &mBuffer[bbox.min()[2] & (DIM-1u)];
1269 for (
Int32 x = bbox.min()[0], ex = bbox.max()[0] + 1;
x < ex; ++
x) {
1270 DenseValueType* t1 = t0 + xStride * (
x - min[0]);
1271 const T* s1 = s0 + ((
x & (DIM-1u)) << 2*Log2Dim);
1272 for (
Int32 y = bbox.min()[1], ey = bbox.max()[1] + 1;
y < ey; ++
y) {
1273 DenseValueType* t2 = t1 + yStride * (
y - min[1]);
1274 const T* s2 = s1 + ((
y & (DIM-1u)) << Log2Dim);
1275 for (
Int32 z = bbox.min()[2], ez = bbox.max()[2] + 1;
z < ez; ++
z, t2 += zStride) {
1276 *t2 = DenseValueType(*s2++);
1283 template<
typename T, Index Log2Dim>
1284 template<
typename DenseT>
1289 if (!this->allocate())
return;
1293 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1294 const Coord&
min = dense.bbox().min();
1296 const DenseValueType* s0 = dense.data() + zStride * (bbox.min()[2] - min[2]);
1297 const Int32 n0 = bbox.min()[2] & (DIM-1u);
1298 for (
Int32 x = bbox.min()[0], ex = bbox.max()[0]+1;
x < ex; ++
x) {
1299 const DenseValueType* s1 = s0 + xStride * (
x - min[0]);
1300 const Int32 n1 = n0 + ((
x & (DIM-1u)) << 2*LOG2DIM);
1301 for (
Int32 y = bbox.min()[1], ey = bbox.max()[1]+1;
y < ey; ++
y) {
1302 const DenseValueType* s2 = s1 + yStride * (
y - min[1]);
1303 Int32 n2 = n1 + ((
y & (DIM-1u)) << LOG2DIM);
1304 for (
Int32 z = bbox.min()[2], ez = bbox.max()[2]+1;
z < ez; ++
z, ++n2, s2 += zStride) {
1307 mBuffer[n2] = background;
1321 template<
typename T, Index Log2Dim>
1329 template<
typename T, Index Log2Dim>
1341 template<
typename T, Index Log2Dim>
1347 io::readCompressedValues<ValueType, NodeMaskType>(
1357 template<
typename T, Index Log2Dim>
1361 this->readBuffers(is, CoordBBox::inf(), fromHalf);
1365 template<
typename T, Index Log2Dim>
1370 const bool seekable = meta && meta->seekable();
1372 #ifdef OPENVDB_USE_DELAYED_LOADING
1373 std::streamoff maskpos = is.tellg();
1384 int8_t numBuffers = 1;
1390 is.read(reinterpret_cast<char*>(&numBuffers),
sizeof(int8_t));
1393 CoordBBox nodeBBox = this->getNodeBoundingBox();
1394 if (!clipBBox.hasOverlap(nodeBBox)) {
1396 skipCompressedValues(seekable, is, fromHalf);
1398 mBuffer.setOutOfCore(
false);
1400 #ifdef OPENVDB_USE_DELAYED_LOADING
1405 io::MappedFile::Ptr mappedFile = io::getMappedFilePtr(is);
1406 const bool delayLoad = ((mappedFile.get() !=
nullptr) && clipBBox.isInside(nodeBBox));
1409 mBuffer.setOutOfCore(
true);
1410 mBuffer.mFileInfo =
new typename Buffer::FileInfo;
1411 mBuffer.mFileInfo->meta = meta;
1412 mBuffer.mFileInfo->bufpos = is.tellg();
1413 mBuffer.mFileInfo->mapping = mappedFile;
1416 mBuffer.mFileInfo->maskpos = maskpos;
1418 skipCompressedValues(seekable, is, fromHalf);
1423 mBuffer.setOutOfCore(
false);
1426 T background = zeroVal<T>();
1428 background = *
static_cast<const T*
>(bgPtr);
1430 this->
clip(clipBBox, background);
1431 #ifdef OPENVDB_USE_DELAYED_LOADING
1436 if (numBuffers > 1) {
1441 for (
int i = 1; i < numBuffers; ++i) {
1445 io::readData<T>(is, temp.mData,
SIZE, zipped);
1451 if (meta) meta->setLeaf(meta->leaf() + 1);
1455 template<
typename T, Index Log2Dim>
1462 mBuffer.loadValues();
1472 template<
typename T, Index Log2Dim>
1476 return mOrigin == other.mOrigin &&
1478 mBuffer == other.mBuffer;
1482 template<
typename T, Index Log2Dim>
1488 return sizeof(*this) + mBuffer.memUsage() -
sizeof(mBuffer);
1492 template<
typename T, Index Log2Dim>
1498 return sizeof(*this) + mBuffer.memUsageIfLoaded() -
sizeof(mBuffer);
1502 template<
typename T, Index Log2Dim>
1506 CoordBBox this_bbox = this->getNodeBoundingBox();
1507 if (bbox.isInside(this_bbox))
return;
1511 for(; iter; ++iter) this_bbox.expand(
this->offsetToLocalCoord(iter.pos()));
1512 this_bbox.translate(this->origin());
1514 bbox.expand(this_bbox);
1519 template<
typename T, Index Log2Dim>
1520 template<
typename OtherType, Index OtherLog2Dim>
1528 template<
typename T, Index Log2Dim>
1534 if (!
mValueMask.isConstant(state))
return false;
1535 firstValue = mBuffer[0];
1542 template<
typename T, Index Log2Dim>
1549 if (!
mValueMask.isConstant(state))
return false;
1550 minValue = maxValue = mBuffer[0];
1552 const T&
v = mBuffer[i];
1554 if ((maxValue - v) > tolerance)
return false;
1556 }
else if (v > maxValue) {
1557 if ((v - minValue) > tolerance)
return false;
1564 template<
typename T, Index Log2Dim>
1568 std::unique_ptr<T[]>
data(
nullptr);
1569 if (tmp ==
nullptr) {
1570 data.reset(
new T[NUM_VALUES]);
1573 if (tmp != mBuffer.data()) {
1574 const T*
src = mBuffer.data();
1575 for (
T*
dst = tmp;
dst-tmp < NUM_VALUES;) *
dst++ = *src++;
1577 static const size_t midpoint = (NUM_VALUES - 1) >> 1;
1578 std::nth_element(tmp, tmp + midpoint, tmp + NUM_VALUES);
1579 return tmp[midpoint];
1582 template<
typename T, Index Log2Dim>
1587 if (count == NUM_VALUES) {
1588 value = this->medianAll(tmp);
1590 }
else if (count == 0) {
1593 std::unique_ptr<T[]>
data(
nullptr);
1594 if (tmp ==
nullptr) {
1595 data.reset(
new T[count]);
1598 for (
auto iter=this->cbeginValueOn(); iter; ++iter) *tmp++ = *iter;
1600 const size_t midpoint = (count - 1) >> 1;
1601 std::nth_element(begin, begin + midpoint, tmp);
1602 value = begin[midpoint];
1606 template<
typename T, Index Log2Dim>
1611 if (count == NUM_VALUES) {
1612 value = this->medianAll(tmp);
1614 }
else if (count == 0) {
1617 std::unique_ptr<T[]>
data(
nullptr);
1618 if (tmp ==
nullptr) {
1619 data.reset(
new T[count]);
1622 for (
auto iter=this->cbeginValueOff(); iter; ++iter) *tmp++ = *iter;
1624 const size_t midpoint = (count - 1) >> 1;
1625 std::nth_element(begin, begin + midpoint, tmp);
1626 value = begin[midpoint];
1633 template<
typename T, Index Log2Dim>
1637 this->addTile(this->coordToOffset(xyz), val, active);
1640 template<
typename T, Index Log2Dim>
1646 setActiveState(offset, active);
1649 template<
typename T, Index Log2Dim>
1650 template<
typename AccessorT>
1655 this->addTile(level, xyz, val, active);
1662 template<
typename T, Index Log2Dim>
1667 if (!this->allocate())
return;
1672 for (iter = this->
mValueMask.beginOff(); iter; ++iter) {
1675 inactiveValue = newBackground;
1683 template<
typename T, Index Log2Dim>
1684 template<MergePolicy Policy>
1688 if (!this->allocate())
return;
1693 for (; iter; ++iter) {
1696 mBuffer[
n] = other.mBuffer[
n];
1703 template<
typename T, Index Log2Dim>
1704 template<MergePolicy Policy>
1709 this->
template merge<Policy>(other);
1712 template<
typename T, Index Log2Dim>
1713 template<MergePolicy Policy>
1717 if (!this->allocate())
return;
1721 if (!tileActive)
return;
1724 const Index n = iter.pos();
1725 mBuffer[
n] = tileValue;
1732 template<
typename T, Index Log2Dim>
1733 template<
typename OtherType>
1740 template<
typename T, Index Log2Dim>
1741 template<
typename OtherType>
1749 template<
typename T, Index Log2Dim>
1750 template<
typename OtherType>
1758 template<
typename T, Index Log2Dim>
1762 if (!this->allocate())
return;
1765 mBuffer[i] = -mBuffer[i];
1773 template<
typename T, Index Log2Dim>
1774 template<
typename CombineOp>
1778 if (!this->allocate())
return;
1784 .setBRef(other.mBuffer[i])
1786 .setResultRef(mBuffer[i]));
1792 template<
typename T, Index Log2Dim>
1793 template<
typename CombineOp>
1797 if (!this->allocate())
return;
1800 args.
setBRef(value).setBIsActive(valueIsActive);
1804 .setResultRef(mBuffer[i]));
1813 template<
typename T, Index Log2Dim>
1814 template<
typename CombineOp,
typename OtherType>
1817 bool valueIsActive, CombineOp&
op)
1819 if (!this->allocate())
return;
1822 args.
setBRef(value).setBIsActive(valueIsActive);
1826 .setResultRef(mBuffer[i]));
1832 template<
typename T, Index Log2Dim>
1833 template<
typename CombineOp,
typename OtherNodeT>
1836 bool valueIsActive, CombineOp&
op)
1838 if (!this->allocate())
return;
1841 args.
setARef(value).setAIsActive(valueIsActive);
1844 .setBIsActive(other.valueMask().isOn(i))
1845 .setResultRef(mBuffer[i]));
1851 template<
typename T, Index Log2Dim>
1852 template<
typename CombineOp,
typename OtherNodeT>
1856 if (!this->allocate())
return;
1863 .setBRef(b1.mBuffer[i])
1864 .setBIsActive(b1.valueMask().isOn(i))
1865 .setResultRef(mBuffer[i]));
1874 template<
typename T, Index Log2Dim>
1875 inline std::ostream&
1876 operator<<(std::ostream& os, const typename LeafNode<T, Log2Dim>::Buffer&
buf)
1878 for (
Index32 i = 0,
N =
buf.size(); i <
N; ++i) os <<
buf.mData[i] <<
", ";
1896 #endif // OPENVDB_TREE_LEAFNODE_HAS_BEEN_INCLUDED
static Index64 nonLeafCount()
Return the non-leaf count for this node, which is zero.
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...
Index64 memUsageIfLoaded() const
void merge(const LeafNode &)
GLenum GLuint GLenum GLsizei const GLchar * buf
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.
void topologyUnion(const LeafNode< OtherType, Log2Dim > &other, const bool preserveTiles=false)
Union this node's set of active values with the active values of the other node, whose ValueType may ...
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 getValueUnsafe(Index offset, ValueType &value) const
Return true if the voxel at the given offset is active and set value.
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.
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
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.
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
GLsizei const GLfloat * value
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
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.
GLdouble GLdouble GLdouble z
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)
const ValueType & getValueUnsafe(Index offset) const
Return the value of the voxel at the given offset.
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()
void setValueOffUnsafe(Index offset)
Mark the voxel at the given offset as inactive but don't change its value.
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
ChildIter< MaskOnIterator, const LeafNode, ChildOn > ChildOnCIter
**But if you need a or simply need to know when the task has note that the like this
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
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.
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 setTransientData(Index32 transientData)
Set the transient data value.
__hostdev__ void setValueOnly(uint32_t offset, uint16_t value)
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
std::conditional_t< std::is_const_v< NodeT >, ValueT, std::remove_const_t< ValueT >> ValueType
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.
__hostdev__ float getValue(uint32_t i) const
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.
#define OPENVDB_ASSERT(X)
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 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
bool isValueMaskOff(Index n) const
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...
bool isValueOff(Index offset) const
Return true if the voxel at the given offset is inactive.
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
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
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...
void setValueOnUnsafe(Index offset, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
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 setValueOnUnsafe(Index offset)
Mark the voxel at the given offset as active but don't change its value.
void setActiveStateUnsafe(Index offset, bool on)
Set the active state of the voxel at the given offset but don't change its value. ...
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 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.
that also have some descendant prim *whose name begins with which in turn has a child named baz where *the predicate active
MaskT< LOG2DIM > mValueMask
static Index dim()
Return the number of voxels in each coordinate dimension.
bool isValueOff(const Coord &xyz) const
Return true if the voxel at the given coordinates is inactive.
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.
Base class for dense iterators over internal and leaf nodes.
OffIterator endOff() const
void modifyValueAndActiveStateAndCache(const Coord &xyz, const ModifyOp &op, AccessorT &)
void prune(const ValueType &=zeroVal< ValueType >())
This function exists only to enable template instantiation.
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.
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.
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)
**If you just want to fire and args
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
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.
void setValuesOff()
Mark all voxels as inactive but don't change their values.
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
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
typename NodeMaskType::OffIterator MaskOffIterator
bool allocate()
Allocate memory for this node's buffer if it has not already been allocated.
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T clip(const T &p, const Box< T > &box) IMATH_NOEXCEPT
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
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()
LeafNode * probeLeaf(const Coord &)
Return a pointer to this node.
void setValueMaskOn(Index n)
static Index64 leafCount()
Return the leaf count for this node, which is one.
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.
void nodeCount(std::vector< Index64 > &) const
no-op
bool isOff(Index32 n) const
Return true if the nth bit is off.
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.
Index32 transientData() const
Return the transient data value.
void setValueOnlyUnsafe(Index offset, const ValueType &value)
Set the value of the voxel at the given coordinates but don't change its active state.
void setValueOffUnsafe(Index offset, const ValueType &value)
Set the value of the voxel at the given coordinates and mark the voxel as active. ...
LeafNode * touchLeafAndCache(const Coord &, AccessorT &)
Return a pointer to this node.
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.