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>
173 const Coord&
origin()
const {
return mOrigin; }
186 #if OPENVDB_ABI_VERSION_NUMBER >= 9
188 Index32 transientData()
const {
return mTransientData; }
190 void setTransientData(
Index32 transientData) { mTransientData = transientData; }
198 template<
typename OtherType, Index OtherLog2Dim>
199 bool hasSameTopology(
const LeafNode<OtherType, OtherLog2Dim>* other)
const;
214 template<
typename MaskIterT,
typename NodeT,
typename ValueT,
typename TagT>
219 MaskIterT, ValueIter<MaskIterT, NodeT, ValueT, TagT>, NodeT, ValueT>
232 this->
parent().setValueOnly(pos, value);
237 this->
parent().setValueOnly(this->
pos(), value);
241 template<
typename ModifyOp>
244 template<
typename ModifyOp>
249 template<
typename MaskIterT,
typename NodeT,
typename TagT>
251 public SparseIteratorBase<MaskIterT, ChildIter<MaskIterT, NodeT, TagT>, NodeT, ValueType>
258 template<
typename NodeT,
typename ValueT,
typename TagT>
260 MaskDenseIterator, DenseIter<NodeT, ValueT, TagT>, NodeT, void, ValueT>
270 value = this->
parent().getValue(pos);
281 this->
parent().setValueOnly(pos, value);
356 void readTopology(std::istream& is,
bool fromHalf =
false);
360 void writeTopology(std::ostream& os,
bool toHalf =
false)
const;
365 void readBuffers(std::istream& is,
bool fromHalf =
false);
370 void readBuffers(std::istream& is,
const CoordBBox& bbox,
bool fromHalf =
false);
374 void writeBuffers(std::ostream& os,
bool toHalf =
false)
const;
431 mValueMask.
setOn(offset);
436 template<
typename ModifyOp>
439 mBuffer.loadValues();
440 if (!mBuffer.
empty()) {
444 mValueMask.
setOn(offset);
450 template<
typename ModifyOp>
457 template<
typename ModifyOp>
460 mBuffer.loadValues();
461 if (!mBuffer.
empty()) {
463 bool state = mValueMask.
isOn(offset);
467 mValueMask.
set(offset, state);
488 void fill(
const CoordBBox& bbox,
const ValueType&,
bool active =
true);
492 this->
fill(bbox, value, active);
511 template<
typename DenseT>
512 void copyToDense(
const CoordBBox& bbox, DenseT& dense)
const;
530 template<
typename DenseT>
531 void copyFromDense(
const CoordBBox& bbox,
const DenseT& dense,
536 template<
typename AccessorT>
544 template<
typename AccessorT>
549 template<
typename AccessorT>
558 template<
typename AccessorT>
567 template<
typename ModifyOp,
typename AccessorT>
575 template<
typename ModifyOp,
typename AccessorT>
583 template<
typename AccessorT>
592 template<
typename AccessorT>
601 template<
typename AccessorT>
610 template<
typename AccessorT>
614 state = mValueMask.
isOn(offset);
621 template<
typename AccessorT>
642 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive);
643 template<MergePolicy Policy>
652 template<
typename OtherType>
666 template<
typename OtherType>
680 template<
typename OtherType>
683 template<
typename CombineOp>
685 template<
typename CombineOp>
688 template<
typename CombineOp,
typename OtherType >
689 void combine2(
const LeafNode& other,
const OtherType&,
bool valueIsActive, CombineOp&);
690 template<
typename CombineOp,
typename OtherNodeT >
691 void combine2(
const ValueType&,
const OtherNodeT& other,
bool valueIsActive, CombineOp&);
692 template<
typename CombineOp,
typename OtherNodeT >
699 template<
typename AccessorT>
701 template<
typename NodeT>
703 template<
typename NodeT>
705 template<
typename NodeT>
707 template<
typename ArrayT>
void getNodes(ArrayT&)
const {}
713 template<
typename AccessorT>
719 template<
typename AccessorT>
721 template<
typename NodeT,
typename AccessorT>
726 return reinterpret_cast<NodeT*
>(
this);
730 template<
typename AccessorT>
736 template<
typename AccessorT>
738 template<
typename AccessorT>
741 template<
typename NodeT,
typename AccessorT>
746 return reinterpret_cast<const NodeT*
>(
this);
761 const ValueType& tolerance = zeroVal<ValueType>())
const;
775 bool& state,
const ValueType& tolerance = zeroVal<ValueType>())
const;
830 friend class ::TestLeaf;
831 template<
typename>
friend class ::TestLeafIO;
880 #if OPENVDB_ABI_VERSION_NUMBER >= 9
893 template<Index Dim1,
typename NodeT2>
896 template<Index Dim1,
typename T2>
904 template<
typename T, Index Log2Dim>
913 template<
typename T, Index Log2Dim>
918 mOrigin(xyz & (~(DIM - 1)))
923 template<
typename T, Index Log2Dim>
928 mOrigin(xyz & (~(DIM - 1)))
933 template<
typename T, Index Log2Dim>
936 : mBuffer(other.mBuffer)
937 , mValueMask(other.valueMask())
938 , mOrigin(other.mOrigin)
940 , mTransientData(other.mTransientData)
947 template<
typename T, Index Log2Dim>
948 template<
typename OtherValueType>
951 : mValueMask(other.valueMask())
952 , mOrigin(other.mOrigin)
954 , mTransientData(other.mTransientData)
963 mBuffer[i] = Local::convertValue(other.mBuffer[i]);
968 template<
typename T, Index Log2Dim>
969 template<
typename OtherValueType>
973 : mBuffer(background)
974 , mValueMask(other.valueMask())
975 , mOrigin(other.mOrigin)
977 , mTransientData(other.mTransientData)
983 template<
typename T, Index Log2Dim>
984 template<
typename OtherValueType>
988 : mValueMask(other.valueMask())
989 , mOrigin(other.mOrigin)
991 , mTransientData(other.mTransientData)
995 mBuffer[i] = (mValueMask.
isOn(i) ? onValue : offValue);
1000 template<
typename T, Index Log2Dim>
1007 template<
typename T, Index Log2Dim>
1011 std::ostringstream ostr;
1012 ostr <<
"LeafNode @" << mOrigin <<
": " << mBuffer;
1020 template<
typename T, Index Log2Dim>
1024 assert ((xyz[0] & (DIM-1u)) < DIM && (xyz[1] & (DIM-1u)) < DIM && (xyz[2] & (DIM-1u)) < DIM);
1025 return ((xyz[0] & (DIM-1u)) << 2*Log2Dim)
1026 + ((xyz[1] & (DIM-1u)) << Log2Dim)
1027 + (xyz[2] & (DIM-1u));
1030 template<
typename T, Index Log2Dim>
1034 assert(n<(1<< 3*Log2Dim));
1036 xyz.setX(n >> 2*Log2Dim);
1037 n &= ((1<<2*Log2Dim)-1);
1038 xyz.setY(n >> Log2Dim);
1039 xyz.setZ(n & ((1<<Log2Dim)-1));
1044 template<
typename T, Index Log2Dim>
1048 return (this->offsetToLocalCoord(n) + this->origin());
1055 template<
typename ValueT, Index Log2Dim>
1056 inline const ValueT&
1062 template<
typename ValueT, Index Log2Dim>
1063 inline const ValueT&
1066 assert(offset <
SIZE);
1071 template<
typename T, Index Log2Dim>
1078 template<
typename T, Index Log2Dim>
1082 assert(offset <
SIZE);
1084 return mValueMask.isOn(offset);
1088 template<
typename T, Index Log2Dim>
1095 template<
typename T, Index Log2Dim>
1099 assert(offset <
SIZE);
1100 mBuffer.setValue(offset, val);
1101 mValueMask.setOff(offset);
1105 template<
typename T, Index Log2Dim>
1109 mValueMask.set(this->coordToOffset(xyz), on);
1113 template<
typename T, Index Log2Dim>
1120 template<
typename T, Index Log2Dim>
1124 assert(offset<
SIZE); mBuffer.setValue(offset, val);
1131 template<
typename T, Index Log2Dim>
1135 CoordBBox nodeBBox = this->getNodeBoundingBox();
1136 if (!clipBBox.hasOverlap(nodeBBox)) {
1138 this->
fill(background,
false);
1139 }
else if (clipBBox.isInside(nodeBBox)) {
1149 nodeBBox.intersect(clipBBox);
1151 int &
x = xyz.x(), &
y = xyz.y(), &
z = xyz.z();
1152 for (x = nodeBBox.min().x(); x <= nodeBBox.max().x(); ++
x) {
1153 for (
y = nodeBBox.min().y();
y <= nodeBBox.max().y(); ++
y) {
1154 for (
z = nodeBBox.min().z();
z <= nodeBBox.max().z(); ++
z) {
1155 mask.
setOn(static_cast<Index32>(this->coordToOffset(xyz)));
1163 this->setValueOff(maskIter.pos(), background);
1171 template<
typename T, Index Log2Dim>
1175 if (!this->allocate())
return;
1177 auto clippedBBox = this->getNodeBoundingBox();
1178 clippedBBox.intersect(bbox);
1179 if (!clippedBBox)
return;
1181 for (
Int32 x = clippedBBox.min().x();
x <= clippedBBox.max().x(); ++
x) {
1182 const Index offsetX = (
x & (DIM-1u)) << 2*Log2Dim;
1183 for (
Int32 y = clippedBBox.min().y();
y <= clippedBBox.max().y(); ++
y) {
1184 const Index offsetXY = offsetX + ((
y & (DIM-1u)) << Log2Dim);
1185 for (
Int32 z = clippedBBox.min().z();
z <= clippedBBox.max().z(); ++
z) {
1188 mValueMask.set(offset, active);
1194 template<
typename T, Index Log2Dim>
1198 mBuffer.fill(value);
1201 template<
typename T, Index Log2Dim>
1205 mBuffer.fill(value);
1206 mValueMask.set(active);
1213 template<
typename T, Index Log2Dim>
1214 template<
typename DenseT>
1218 mBuffer.loadValues();
1220 using DenseValueType =
typename DenseT::ValueType;
1222 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1223 const Coord&
min = dense.bbox().min();
1224 DenseValueType* t0 = dense.data() + zStride * (bbox.min()[2] - min[2]);
1225 const T* s0 = &mBuffer[bbox.min()[2] & (DIM-1u)];
1226 for (
Int32 x = bbox.min()[0], ex = bbox.max()[0] + 1;
x < ex; ++
x) {
1227 DenseValueType* t1 = t0 + xStride * (
x - min[0]);
1228 const T* s1 = s0 + ((
x & (DIM-1u)) << 2*Log2Dim);
1229 for (
Int32 y = bbox.min()[1], ey = bbox.max()[1] + 1;
y < ey; ++
y) {
1230 DenseValueType* t2 = t1 + yStride * (
y - min[1]);
1231 const T* s2 = s1 + ((
y & (DIM-1u)) << Log2Dim);
1232 for (
Int32 z = bbox.min()[2], ez = bbox.max()[2] + 1;
z < ez; ++
z, t2 += zStride) {
1233 *t2 = DenseValueType(*s2++);
1240 template<
typename T, Index Log2Dim>
1241 template<
typename DenseT>
1246 if (!this->allocate())
return;
1248 using DenseValueType =
typename DenseT::ValueType;
1250 const size_t xStride = dense.xStride(), yStride = dense.yStride(), zStride = dense.zStride();
1251 const Coord&
min = dense.bbox().min();
1253 const DenseValueType* s0 = dense.data() + zStride * (bbox.min()[2] - min[2]);
1254 const Int32 n0 = bbox.min()[2] & (DIM-1u);
1255 for (
Int32 x = bbox.min()[0], ex = bbox.max()[0]+1;
x < ex; ++
x) {
1256 const DenseValueType* s1 = s0 + xStride * (
x - min[0]);
1257 const Int32 n1 = n0 + ((
x & (DIM-1u)) << 2*LOG2DIM);
1258 for (
Int32 y = bbox.min()[1], ey = bbox.max()[1]+1;
y < ey; ++
y) {
1259 const DenseValueType* s2 = s1 + yStride * (
y - min[1]);
1260 Int32 n2 = n1 + ((
y & (DIM-1u)) << LOG2DIM);
1261 for (
Int32 z = bbox.min()[2], ez = bbox.max()[2]+1;
z < ez; ++
z, ++n2, s2 += zStride) {
1263 mValueMask.setOff(n2);
1264 mBuffer[n2] = background;
1266 mValueMask.setOn(n2);
1278 template<
typename T, Index Log2Dim>
1282 mValueMask.load(is);
1286 template<
typename T, Index Log2Dim>
1290 mValueMask.save(os);
1298 template<
typename T, Index Log2Dim>
1304 io::readCompressedValues<ValueType, NodeMaskType>(
1305 is,
nullptr,
SIZE, mValueMask, fromHalf);
1314 template<
typename T, Index Log2Dim>
1318 this->readBuffers(is, CoordBBox::inf(), fromHalf);
1322 template<
typename T, Index Log2Dim>
1327 const bool seekable = meta && meta->seekable();
1329 #ifdef OPENVDB_USE_DELAYED_LOADING
1330 std::streamoff maskpos = is.tellg();
1335 mValueMask.seek(is);
1338 mValueMask.load(is);
1341 int8_t numBuffers = 1;
1344 is.read(reinterpret_cast<char*>(&mOrigin),
sizeof(Coord::ValueType) * 3);
1347 is.read(reinterpret_cast<char*>(&numBuffers),
sizeof(int8_t));
1350 CoordBBox nodeBBox = this->getNodeBoundingBox();
1351 if (!clipBBox.hasOverlap(nodeBBox)) {
1353 skipCompressedValues(seekable, is, fromHalf);
1354 mValueMask.setOff();
1355 mBuffer.setOutOfCore(
false);
1357 #ifdef OPENVDB_USE_DELAYED_LOADING
1362 io::MappedFile::Ptr mappedFile = io::getMappedFilePtr(is);
1363 const bool delayLoad = ((mappedFile.get() !=
nullptr) && clipBBox.isInside(nodeBBox));
1366 mBuffer.setOutOfCore(
true);
1367 mBuffer.mFileInfo =
new typename Buffer::FileInfo;
1368 mBuffer.mFileInfo->meta = meta;
1369 mBuffer.mFileInfo->bufpos = is.tellg();
1370 mBuffer.mFileInfo->mapping = mappedFile;
1373 mBuffer.mFileInfo->maskpos = maskpos;
1375 skipCompressedValues(seekable, is, fromHalf);
1380 mBuffer.setOutOfCore(
false);
1383 T background = zeroVal<T>();
1385 background = *
static_cast<const T*
>(bgPtr);
1387 this->
clip(clipBBox, background);
1388 #ifdef OPENVDB_USE_DELAYED_LOADING
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>
1455 return sizeof(*this) + mBuffer.memUsageIfLoaded() -
sizeof(mBuffer);
1459 template<
typename T, Index Log2Dim>
1463 CoordBBox this_bbox = this->getNodeBoundingBox();
1464 if (bbox.isInside(this_bbox))
return;
1468 for(; iter; ++iter) this_bbox.expand(
this->offsetToLocalCoord(iter.pos()));
1469 this_bbox.translate(this->origin());
1471 bbox.expand(this_bbox);
1476 template<
typename T, Index Log2Dim>
1477 template<
typename OtherType, Index OtherLog2Dim>
1482 return (Log2Dim == OtherLog2Dim && mValueMask == other->
getValueMask());
1485 template<
typename T, Index Log2Dim>
1491 if (!mValueMask.isConstant(state))
return false;
1492 firstValue = mBuffer[0];
1499 template<
typename T, Index Log2Dim>
1506 if (!mValueMask.isConstant(state))
return false;
1507 minValue = maxValue = mBuffer[0];
1509 const T&
v = mBuffer[i];
1511 if ((maxValue - v) > tolerance)
return false;
1513 }
else if (v > maxValue) {
1514 if ((v - minValue) > tolerance)
return false;
1521 template<
typename T, Index Log2Dim>
1525 std::unique_ptr<T[]>
data(
nullptr);
1526 if (tmp ==
nullptr) {
1527 data.reset(
new T[NUM_VALUES]);
1530 if (tmp != mBuffer.data()) {
1531 const T*
src = mBuffer.data();
1532 for (
T*
dst = tmp;
dst-tmp < NUM_VALUES;) *
dst++ = *src++;
1534 static const size_t midpoint = (NUM_VALUES - 1) >> 1;
1535 std::nth_element(tmp, tmp + midpoint, tmp + NUM_VALUES);
1536 return tmp[midpoint];
1539 template<
typename T, Index Log2Dim>
1544 if (count == NUM_VALUES) {
1545 value = this->medianAll(tmp);
1547 }
else if (count == 0) {
1550 std::unique_ptr<T[]>
data(
nullptr);
1551 if (tmp ==
nullptr) {
1552 data.reset(
new T[count]);
1555 for (
auto iter=this->cbeginValueOn(); iter; ++iter) *tmp++ = *iter;
1557 const size_t midpoint = (count - 1) >> 1;
1558 std::nth_element(begin, begin + midpoint, tmp);
1559 value = begin[midpoint];
1563 template<
typename T, Index Log2Dim>
1568 if (count == NUM_VALUES) {
1569 value = this->medianAll(tmp);
1571 }
else if (count == 0) {
1574 std::unique_ptr<T[]>
data(
nullptr);
1575 if (tmp ==
nullptr) {
1576 data.reset(
new T[count]);
1579 for (
auto iter=this->cbeginValueOff(); iter; ++iter) *tmp++ = *iter;
1581 const size_t midpoint = (count - 1) >> 1;
1582 std::nth_element(begin, begin + midpoint, tmp);
1583 value = begin[midpoint];
1590 template<
typename T, Index Log2Dim>
1594 this->addTile(this->coordToOffset(xyz), val, active);
1597 template<
typename T, Index Log2Dim>
1601 assert(offset <
SIZE);
1602 setValueOnly(offset, val);
1603 setActiveState(offset, active);
1606 template<
typename T, Index Log2Dim>
1607 template<
typename AccessorT>
1612 this->addTile(level, xyz, val, active);
1619 template<
typename T, Index Log2Dim>
1624 if (!this->allocate())
return;
1628 for (iter = this->mValueMask.beginOff(); iter; ++iter) {
1631 inactiveValue = newBackground;
1639 template<
typename T, Index Log2Dim>
1640 template<MergePolicy Policy>
1644 if (!this->allocate())
return;
1649 for (; iter; ++iter) {
1651 if (mValueMask.isOff(n)) {
1652 mBuffer[
n] = other.mBuffer[
n];
1653 mValueMask.setOn(n);
1659 template<
typename T, Index Log2Dim>
1660 template<MergePolicy Policy>
1665 this->
template merge<Policy>(other);
1668 template<
typename T, Index Log2Dim>
1669 template<MergePolicy Policy>
1673 if (!this->allocate())
return;
1677 if (!tileActive)
return;
1680 const Index n = iter.pos();
1681 mBuffer[
n] = tileValue;
1682 mValueMask.setOn(n);
1688 template<
typename T, Index Log2Dim>
1689 template<
typename OtherType>
1696 template<
typename T, Index Log2Dim>
1697 template<
typename OtherType>
1705 template<
typename T, Index Log2Dim>
1706 template<
typename OtherType>
1714 template<
typename T, Index Log2Dim>
1718 if (!this->allocate())
return;
1721 mBuffer[i] = -mBuffer[i];
1729 template<
typename T, Index Log2Dim>
1730 template<
typename CombineOp>
1734 if (!this->allocate())
return;
1739 .setAIsActive(mValueMask.isOn(i))
1740 .setBRef(other.mBuffer[i])
1742 .setResultRef(mBuffer[i]));
1748 template<
typename T, Index Log2Dim>
1749 template<
typename CombineOp>
1753 if (!this->allocate())
return;
1756 args.
setBRef(value).setBIsActive(valueIsActive);
1759 .setAIsActive(mValueMask.isOn(i))
1760 .setResultRef(mBuffer[i]));
1769 template<
typename T, Index Log2Dim>
1770 template<
typename CombineOp,
typename OtherType>
1773 bool valueIsActive, CombineOp& op)
1775 if (!this->allocate())
return;
1778 args.
setBRef(value).setBIsActive(valueIsActive);
1780 op(args.
setARef(other.mBuffer[i])
1782 .setResultRef(mBuffer[i]));
1788 template<
typename T, Index Log2Dim>
1789 template<
typename CombineOp,
typename OtherNodeT>
1792 bool valueIsActive, CombineOp& op)
1794 if (!this->allocate())
return;
1797 args.
setARef(value).setAIsActive(valueIsActive);
1799 op(args.
setBRef(other.mBuffer[i])
1800 .setBIsActive(other.valueMask().isOn(i))
1801 .setResultRef(mBuffer[i]));
1807 template<
typename T, Index Log2Dim>
1808 template<
typename CombineOp,
typename OtherNodeT>
1812 if (!this->allocate())
return;
1816 mValueMask.set(i, b0.
valueMask().
isOn(i) || b1.valueMask().isOn(i));
1817 op(args.
setARef(b0.mBuffer[i])
1819 .setBRef(b1.mBuffer[i])
1820 .setBIsActive(b1.valueMask().isOn(i))
1821 .setResultRef(mBuffer[i]));
1830 template<
typename T, Index Log2Dim>
1831 inline std::ostream&
1832 operator<<(std::ostream& os, const typename LeafNode<T, Log2Dim>::Buffer&
buf)
1834 for (
Index32 i = 0,
N =
buf.size(); i <
N; ++i) os <<
buf.mData[i] <<
", ";
1852 #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...
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 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.
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 GLchar *const * string
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)
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()
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 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.
#define OPENVDB_ABI_VERSION_NUMBER
The ABI version that OpenVDB was built with.
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
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...
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...
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 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.
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)
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.
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.