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>
1372 const bool seekable = meta && meta->seekable();
1374 #ifdef OPENVDB_USE_DELAYED_LOADING
1375 std::streamoff maskpos = is.tellg();
1386 int8_t numBuffers = 1;
1392 is.read(reinterpret_cast<char*>(&numBuffers),
sizeof(int8_t));
1395 CoordBBox nodeBBox = this->getNodeBoundingBox();
1396 if (!clipBBox.hasOverlap(nodeBBox)) {
1398 skipCompressedValues(seekable, is, fromHalf);
1400 mBuffer.setOutOfCore(
false);
1402 #ifdef OPENVDB_USE_DELAYED_LOADING
1407 io::MappedFile::Ptr mappedFile = io::getMappedFilePtr(is);
1408 const bool delayLoad = ((mappedFile.get() !=
nullptr) && clipBBox.isInside(nodeBBox));
1413 mBuffer.enableOutOfCore(meta, is.tellg(), mappedFile, maskpos);
1415 skipCompressedValues(seekable, is, fromHalf);
1420 mBuffer.setOutOfCore(
false);
1423 T background = zeroVal<T>();
1425 background = *
static_cast<const T*
>(bgPtr);
1427 this->
clip(clipBBox, background);
1428 #ifdef OPENVDB_USE_DELAYED_LOADING
1433 if (numBuffers > 1) {
1438 for (
int i = 1; i < numBuffers; ++i) {
1442 io::readData<T>(is, temp.mData,
SIZE, zipped);
1448 if (meta) meta->setLeaf(meta->leaf() + 1);
1452 template<
typename T, Index Log2Dim>
1459 mBuffer.loadValues();
1469 template<
typename T, Index Log2Dim>
1473 return mOrigin == other.mOrigin &&
1475 mBuffer == other.mBuffer;
1479 template<
typename T, Index Log2Dim>
1485 return sizeof(*this) + mBuffer.memUsage() -
sizeof(mBuffer);
1489 template<
typename T, Index Log2Dim>
1495 return sizeof(*this) + mBuffer.memUsageIfLoaded() -
sizeof(mBuffer);
1499 template<
typename T, Index Log2Dim>
1503 CoordBBox this_bbox = this->getNodeBoundingBox();
1504 if (bbox.isInside(this_bbox))
return;
1508 for(; iter; ++iter) this_bbox.expand(
this->offsetToLocalCoord(iter.pos()));
1509 this_bbox.translate(this->origin());
1511 bbox.expand(this_bbox);
1516 template<
typename T, Index Log2Dim>
1517 template<
typename OtherType, Index OtherLog2Dim>
1525 template<
typename T, Index Log2Dim>
1531 if (!
mValueMask.isConstant(state))
return false;
1532 firstValue = mBuffer[0];
1539 template<
typename T, Index Log2Dim>
1546 if (!
mValueMask.isConstant(state))
return false;
1547 minValue = maxValue = mBuffer[0];
1549 const T&
v = mBuffer[i];
1551 if ((maxValue - v) > tolerance)
return false;
1553 }
else if (v > maxValue) {
1554 if ((v - minValue) > tolerance)
return false;
1561 template<
typename T, Index Log2Dim>
1565 std::unique_ptr<T[]>
data(
nullptr);
1566 if (tmp ==
nullptr) {
1567 data.reset(
new T[NUM_VALUES]);
1570 if (tmp != mBuffer.data()) {
1571 const T*
src = mBuffer.data();
1572 for (
T*
dst = tmp;
dst-tmp < NUM_VALUES;) *
dst++ = *src++;
1574 static const size_t midpoint = (NUM_VALUES - 1) >> 1;
1575 std::nth_element(tmp, tmp + midpoint, tmp + NUM_VALUES);
1576 return tmp[midpoint];
1579 template<
typename T, Index Log2Dim>
1584 if (count == NUM_VALUES) {
1585 value = this->medianAll(tmp);
1587 }
else if (count == 0) {
1590 std::unique_ptr<T[]>
data(
nullptr);
1591 if (tmp ==
nullptr) {
1592 data.reset(
new T[count]);
1595 for (
auto iter=this->cbeginValueOn(); iter; ++iter) *tmp++ = *iter;
1597 const size_t midpoint = (count - 1) >> 1;
1598 std::nth_element(begin, begin + midpoint, tmp);
1599 value = begin[midpoint];
1603 template<
typename T, Index Log2Dim>
1608 if (count == NUM_VALUES) {
1609 value = this->medianAll(tmp);
1611 }
else if (count == 0) {
1614 std::unique_ptr<T[]>
data(
nullptr);
1615 if (tmp ==
nullptr) {
1616 data.reset(
new T[count]);
1619 for (
auto iter=this->cbeginValueOff(); iter; ++iter) *tmp++ = *iter;
1621 const size_t midpoint = (count - 1) >> 1;
1622 std::nth_element(begin, begin + midpoint, tmp);
1623 value = begin[midpoint];
1630 template<
typename T, Index Log2Dim>
1634 this->addTile(this->coordToOffset(xyz), val, active);
1637 template<
typename T, Index Log2Dim>
1643 setActiveState(offset, active);
1646 template<
typename T, Index Log2Dim>
1647 template<
typename AccessorT>
1652 this->addTile(level, xyz, val, active);
1659 template<
typename T, Index Log2Dim>
1664 if (!this->allocate())
return;
1669 for (iter = this->
mValueMask.beginOff(); iter; ++iter) {
1672 inactiveValue = newBackground;
1680 template<
typename T, Index Log2Dim>
1681 template<MergePolicy Policy>
1685 if (!this->allocate())
return;
1690 for (; iter; ++iter) {
1693 mBuffer[
n] = other.mBuffer[
n];
1700 template<
typename T, Index Log2Dim>
1701 template<MergePolicy Policy>
1706 this->
template merge<Policy>(other);
1709 template<
typename T, Index Log2Dim>
1710 template<MergePolicy Policy>
1714 if (!this->allocate())
return;
1718 if (!tileActive)
return;
1721 const Index n = iter.pos();
1722 mBuffer[
n] = tileValue;
1729 template<
typename T, Index Log2Dim>
1730 template<
typename OtherType>
1737 template<
typename T, Index Log2Dim>
1738 template<
typename OtherType>
1746 template<
typename T, Index Log2Dim>
1747 template<
typename OtherType>
1755 template<
typename T, Index Log2Dim>
1759 if (!this->allocate())
return;
1762 mBuffer[i] = -mBuffer[i];
1770 template<
typename T, Index Log2Dim>
1771 template<
typename CombineOp>
1775 if (!this->allocate())
return;
1781 .setBRef(other.mBuffer[i])
1783 .setResultRef(mBuffer[i]));
1789 template<
typename T, Index Log2Dim>
1790 template<
typename CombineOp>
1794 if (!this->allocate())
return;
1797 args.
setBRef(value).setBIsActive(valueIsActive);
1801 .setResultRef(mBuffer[i]));
1810 template<
typename T, Index Log2Dim>
1811 template<
typename CombineOp,
typename OtherType>
1814 bool valueIsActive, CombineOp&
op)
1816 if (!this->allocate())
return;
1819 args.
setBRef(value).setBIsActive(valueIsActive);
1823 .setResultRef(mBuffer[i]));
1829 template<
typename T, Index Log2Dim>
1830 template<
typename CombineOp,
typename OtherNodeT>
1833 bool valueIsActive, CombineOp&
op)
1835 if (!this->allocate())
return;
1838 args.
setARef(value).setAIsActive(valueIsActive);
1841 .setBIsActive(other.valueMask().isOn(i))
1842 .setResultRef(mBuffer[i]));
1848 template<
typename T, Index Log2Dim>
1849 template<
typename CombineOp,
typename OtherNodeT>
1853 if (!this->allocate())
return;
1860 .setBRef(b1.mBuffer[i])
1861 .setBIsActive(b1.valueMask().isOn(i))
1862 .setResultRef(mBuffer[i]));
1871 template<
typename T, Index Log2Dim>
1872 inline std::ostream&
1873 operator<<(std::ostream& os, const typename LeafNode<T, Log2Dim>::Buffer&
buf)
1875 for (
Index32 i = 0,
N =
buf.size(); i <
N; ++i) os <<
buf.mData[i] <<
", ";
1893 #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
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
OPENVDB_API void checkFormatVersion(std::ios_base &)
Throws an IoError if the file format version number is not supported.
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
void writeCompressedValues(std::ostream &os, const ValueT *srcBuf, Index srcCount, const MaskT &valueMask, const MaskT &childMask, bool toHalf)
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()
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
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.