16 #ifndef OPENVDB_TOOLS_POINT_INDEX_GRID_HAS_BEEN_INCLUDED
17 #define OPENVDB_TOOLS_POINT_INDEX_GRID_HAS_BEEN_INCLUDED
30 #include <tbb/atomic.h>
31 #include <tbb/blocked_range.h>
32 #include <tbb/parallel_for.h>
37 #include <type_traits>
47 template<Index,
typename>
struct SameLeafConfig;
52 template<
typename T, Index Log2Dim>
struct PointIndexLeafNode;
91 template<
typename Gr
idT,
typename Po
intArrayT>
92 inline typename GridT::Ptr
101 template<
typename Gr
idT,
typename Po
intArrayT>
102 inline typename GridT::Ptr
111 template<
typename Po
intArrayT,
typename Gr
idT>
117 template<
typename Gr
idT,
typename Po
intArrayT>
118 inline typename GridT::ConstPtr
122 template<
typename Gr
idT,
typename Po
intArrayT>
123 inline typename GridT::Ptr
131 template<
typename TreeType = Po
intIndexTree>
179 template<
typename Po
intArray>
194 template<
typename Po
intArray>
205 template<
typename Po
intArray>
220 template<
typename Po
intArray>
233 bool test()
const {
return mRange.first < mRange.second || mIter != mRangeList.end(); }
234 operator bool()
const {
return this->test(); }
257 using Range = std::pair<const ValueType*, const ValueType*>;
258 using RangeDeque = std::deque<Range>;
259 using RangeDequeCIter =
typename RangeDeque::const_iterator;
260 using IndexArray = std::unique_ptr<ValueType[]>;
266 RangeDeque mRangeList;
267 RangeDequeCIter mIter;
270 size_t mIndexArraySize;
303 template<
typename Po
intArray,
typename TreeType = Po
intIndexTree>
324 template<
typename FilterType>
341 namespace point_index_grid_internal {
343 template<
typename Po
intArrayT>
350 , mHasChanged(&hasChanged)
354 template <
typename LeafT>
357 if ((*mHasChanged)) {
358 tbb::task::self().cancel_group_execution();
363 using IndexT =
typename IndexArrayT::value_type;
364 using PosType =
typename PointArrayT::PosType;
366 typename LeafT::ValueOnCIter iter;
371 *begin =
static_cast<IndexT*
>(
nullptr),
372 *end =
static_cast<IndexT*
>(
nullptr);
374 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
376 if ((*mHasChanged))
break;
378 voxelCoord = iter.getCoord();
379 leaf.getIndices(iter.pos(), begin, end);
381 while (begin < end) {
383 mPoints->getPos(*begin, point);
384 if (voxelCoord != mTransform->worldToIndexCellCentered(point)) {
385 mHasChanged->fetch_and_store(
true);
395 PointArrayT
const *
const mPoints;
397 tbb::atomic<bool> *
const mHasChanged;
401 template<
typename LeafNodeT>
409 : mLeafNodes(leafNodes.get())
410 , mPartitioner(&partitioner)
414 void operator()(
const tbb::blocked_range<size_t>& range)
const {
418 size_t maxPointCount = 0;
419 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
420 maxPointCount =
std::max(maxPointCount, mPartitioner->indices(n).size());
423 const IndexT voxelCount = LeafNodeT::SIZE;
426 std::unique_ptr<VoxelOffsetT[]> offsets{
new VoxelOffsetT[maxPointCount]};
429 VoxelOffsetT
const *
const voxelOffsets = mPartitioner->voxelOffsets().get();
431 for (
size_t n = range.begin(), N = range.end(); n != N; ++n) {
433 LeafNodeT* node =
new LeafNodeT();
434 node->setOrigin(mPartitioner->origin(n));
439 IndexT const *
const indices = &*it;
443 offsets[i] = voxelOffsets[ indices[i] ];
452 typename LeafNodeT::NodeMaskType& mask = node->getValueMask();
453 typename LeafNodeT::Buffer& buffer = node->buffer();
456 IndexT count = 0, startOffset;
457 for (
int i = 0; i < int(voxelCount); ++i) {
464 buffer.setValue(i, count);
469 typename LeafNodeT::ValueType *
const orderedIndices = node->indices().data();
473 orderedIndices[
histogram[ offsets[i] ]++ ] = indices[i];
476 mLeafNodes[n] = node;
488 template<
typename TreeType,
typename Po
intArray>
492 using LeafType =
typename TreeType::LeafNodeType;
494 std::unique_ptr<LeafType*[]> leafNodes;
495 size_t leafNodeCount = 0;
502 partitioner.
construct(points, xform,
false,
true);
506 "cell-centered transform.");
509 leafNodeCount = partitioner.
size();
510 leafNodes.reset(
new LeafType*[leafNodeCount]);
512 const tbb::blocked_range<size_t> range(0, leafNodeCount);
517 for (
size_t n = 0; n < leafNodeCount; ++n) {
528 dequeToArray(
const std::deque<T>& d, std::unique_ptr<T[]>& a,
size_t& size)
531 a.reset(
new T[size]);
532 typename std::deque<T>::const_iterator it = d.begin(), itEnd = d.end();
534 for ( ; it != itEnd; ++it, ++item) *item = *it;
548 regions.push_back(bbox);
549 regions.back().
max().
z() = cmin.
z();
552 regions.push_back(bbox);
553 regions.back().min().z() = cmax.
z();
559 regions.push_back(bbox);
561 lastRegion->
min().
z() = cmin.
z();
562 lastRegion->
max().
z() = cmax.
z();
563 lastRegion->
max().
x() = cmin.
x();
566 regions.push_back(*lastRegion);
567 lastRegion = ®ions.back();
568 lastRegion->
min().
x() = cmax.
x();
569 lastRegion->
max().
x() = bbox.
max().
x();
575 regions.push_back(*lastRegion);
576 lastRegion = ®ions.back();
577 lastRegion->
min().
x() = cmin.
x();
578 lastRegion->
max().
x() = cmax.
x();
579 lastRegion->
max().
y() = cmin.
y();
582 regions.push_back(*lastRegion);
583 lastRegion = ®ions.back();
584 lastRegion->
min().
y() = cmax.
y();
585 lastRegion->
max().
y() = bbox.
max().
y();
589 template<
typename Po
intArray,
typename IndexT>
594 using Range = std::pair<const IndexT*, const IndexT*>;
604 , mMap(*xform.baseMap())
608 template <
typename LeafNodeType>
611 typename LeafNodeType::ValueOnCIter iter;
613 *begin =
static_cast<IndexT*
>(
nullptr),
614 *end =
static_cast<IndexT*
>(
nullptr);
615 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
616 leaf.getIndices(iter.pos(), begin, end);
617 filterVoxel(iter.getCoord(), begin, end);
625 for (; begin < end; ++begin) {
626 mPoints.getPos(*begin, vec);
628 if (mRegion.isInside(mMap.applyInverseMap(vec))) {
629 mIndices.push_back(*begin);
636 IndexDeque& mIndices;
643 template<
typename Po
intArray,
typename IndexT>
648 using Range = std::pair<const IndexT*, const IndexT*>;
654 const double leafNodeDim,
const bool subvoxelAccuracy)
658 , mWSCenter(xform.indexToWorld(xyz))
663 , mWSRadiusSqr(
ScalarType(radius * xform.voxelSize()[0]))
665 , mSubvoxelAccuracy(subvoxelAccuracy)
668 mVoxelDist1 = voxelRadius +
ScalarType(radius);
669 mVoxelDist1 *= mVoxelDist1;
671 if (radius > voxelRadius) {
672 mVoxelDist2 =
ScalarType(radius) - voxelRadius;
673 mVoxelDist2 *= mVoxelDist2;
677 mLeafNodeDist1 = leafNodeRadius +
ScalarType(radius);
678 mLeafNodeDist1 *= mLeafNodeDist1;
680 if (radius > leafNodeRadius) {
681 mLeafNodeDist2 =
ScalarType(radius) - leafNodeRadius;
682 mLeafNodeDist2 *= mLeafNodeDist2;
685 mWSRadiusSqr *= mWSRadiusSqr;
688 template <
typename LeafNodeType>
692 const Coord& ijk = leaf.origin();
697 vec +=
ScalarType(LeafNodeType::DIM - 1) * 0.5;
701 if (dist > mLeafNodeDist1)
return;
703 if (mLeafNodeDist2 > 0.0 && dist < mLeafNodeDist2) {
704 const IndexT* begin = &leaf.indices().front();
705 mRanges.push_back(
Range(begin, begin + leaf.indices().size()));
710 typename LeafNodeType::ValueOnCIter iter;
712 *begin =
static_cast<IndexT*
>(
nullptr),
713 *end =
static_cast<IndexT*
>(
nullptr);
714 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
715 leaf.getIndices(iter.pos(), begin, end);
716 filterVoxel(iter.getCoord(), begin, end);
730 if (dist > mVoxelDist1)
return;
732 if (!mSubvoxelAccuracy || (mVoxelDist2 > 0.0 && dist < mVoxelDist2)) {
733 if (!mRanges.empty() && mRanges.back().second == begin) {
734 mRanges.back().second = end;
736 mRanges.push_back(
Range(begin, end));
743 while (begin < end) {
744 mPoints.getPos(*begin, vec);
745 vec = mWSCenter - vec;
747 if (vec.lengthSqr() < mWSRadiusSqr) {
748 mIndices.push_back(*begin);
756 IndexDeque& mIndices;
757 const PosType mCenter, mWSCenter;
758 ScalarType mVoxelDist1, mVoxelDist2, mLeafNodeDist1, mLeafNodeDist2, mWSRadiusSqr;
760 const bool mSubvoxelAccuracy;
767 template<
typename RangeFilterType,
typename LeafNodeType>
772 using PointIndexT =
typename LeafNodeType::ValueType;
773 Index xPos(0), yPos(0), pos(0);
776 const PointIndexT* dataPtr = &leaf.indices().front();
777 PointIndexT beginOffset, endOffset;
779 for (ijk[0] =
min[0]; ijk[0] <=
max[0]; ++ijk[0]) {
780 xPos = (ijk[0] & (LeafNodeType::DIM - 1u)) << (2 * LeafNodeType::LOG2DIM);
781 for (ijk[1] =
min[1]; ijk[1] <=
max[1]; ++ijk[1]) {
782 yPos = xPos + ((ijk[1] & (LeafNodeType::DIM - 1u)) << LeafNodeType::LOG2DIM);
783 for (ijk[2] =
min[2]; ijk[2] <=
max[2]; ++ijk[2]) {
784 pos = yPos + (ijk[2] & (LeafNodeType::DIM - 1u));
786 beginOffset = (pos == 0 ? PointIndexT(0) : leaf.getValue(pos - 1));
787 endOffset = leaf.getValue(pos);
789 if (endOffset > beginOffset) {
790 filter.filterVoxel(ijk, dataPtr + beginOffset, dataPtr + endOffset);
798 template<
typename RangeFilterType,
typename ConstAccessor>
802 using LeafNodeType =
typename ConstAccessor::TreeType::LeafNodeType;
803 Coord ijk(0), ijkMax(0), ijkA(0), ijkB(0);
804 const Coord leafMin = bbox.
min() & ~(LeafNodeType::DIM - 1);
805 const Coord leafMax = bbox.
max() & ~(LeafNodeType::DIM - 1);
807 for (ijk[0] = leafMin[0]; ijk[0] <= leafMax[0]; ijk[0] += LeafNodeType::DIM) {
808 for (ijk[1] = leafMin[1]; ijk[1] <= leafMax[1]; ijk[1] += LeafNodeType::DIM) {
809 for (ijk[2] = leafMin[2]; ijk[2] <= leafMax[2]; ijk[2] += LeafNodeType::DIM) {
811 if (
const LeafNodeType* leaf = acc.probeConstLeaf(ijk)) {
813 ijkMax.
offset(LeafNodeType::DIM - 1);
819 if (ijkA != ijk || ijkB != ijkMax) {
822 filter.filterLeafNode(*leaf);
834 template<
typename RangeDeque,
typename LeafNodeType>
839 using PointIndexT =
typename LeafNodeType::ValueType;
840 using IntT =
typename PointIndexT::IntType;
841 using Range =
typename RangeDeque::value_type;
844 const PointIndexT* dataPtr = &leaf.indices().front();
845 PointIndexT beginOffset(0), endOffset(0),
846 previousOffset(
static_cast<IntT
>(leaf.indices().size() + 1u));
849 for (ijk[0] =
min[0]; ijk[0] <=
max[0]; ++ijk[0]) {
850 xPos = (ijk[0] & (LeafNodeType::DIM - 1u)) << (2 * LeafNodeType::LOG2DIM);
852 for (ijk[1] =
min[1]; ijk[1] <=
max[1]; ++ijk[1]) {
853 pos = xPos + ((ijk[1] & (LeafNodeType::DIM - 1u)) << LeafNodeType::LOG2DIM);
854 pos += (
min[2] & (LeafNodeType::DIM - 1u));
856 beginOffset = (pos == 0 ? PointIndexT(0) : leaf.getValue(pos - 1));
857 endOffset = leaf.getValue(pos+zStride);
859 if (endOffset > beginOffset) {
861 if (beginOffset == previousOffset) {
862 rangeList.back().second = dataPtr + endOffset;
864 rangeList.push_back(Range(dataPtr + beginOffset, dataPtr + endOffset));
867 previousOffset = endOffset;
874 template<
typename RangeDeque,
typename ConstAccessor>
878 using LeafNodeType =
typename ConstAccessor::TreeType::LeafNodeType;
879 using PointIndexT =
typename LeafNodeType::ValueType;
880 using Range =
typename RangeDeque::value_type;
882 Coord ijk(0), ijkMax(0), ijkA(0), ijkB(0);
883 const Coord leafMin = bbox.
min() & ~(LeafNodeType::DIM - 1);
884 const Coord leafMax = bbox.
max() & ~(LeafNodeType::DIM - 1);
886 for (ijk[0] = leafMin[0]; ijk[0] <= leafMax[0]; ijk[0] += LeafNodeType::DIM) {
887 for (ijk[1] = leafMin[1]; ijk[1] <= leafMax[1]; ijk[1] += LeafNodeType::DIM) {
888 for (ijk[2] = leafMin[2]; ijk[2] <= leafMax[2]; ijk[2] += LeafNodeType::DIM) {
890 if (
const LeafNodeType* leaf = acc.probeConstLeaf(ijk)) {
892 ijkMax.
offset(LeafNodeType::DIM - 1);
898 if (ijkA != ijk || ijkB != ijkMax) {
902 const PointIndexT* begin = &leaf->indices().front();
903 rangeList.push_back(Range(begin, (begin + leaf->indices().size())));
917 template<
typename TreeType>
922 , mIter(mRangeList.begin())
929 template<
typename TreeType>
933 , mRangeList(rhs.mRangeList)
934 , mIter(mRangeList.begin())
936 , mIndexArraySize(rhs.mIndexArraySize)
938 if (rhs.mIndexArray) {
939 mIndexArray.reset(
new ValueType[mIndexArraySize]);
940 memcpy(mIndexArray.get(), rhs.mIndexArray.get(), mIndexArraySize *
sizeof(
ValueType));
945 template<
typename TreeType>
951 mRangeList = rhs.mRangeList;
952 mIter = mRangeList.begin();
954 mIndexArraySize = rhs.mIndexArraySize;
956 if (rhs.mIndexArray) {
957 mIndexArray.reset(
new ValueType[mIndexArraySize]);
958 memcpy(mIndexArray.get(), rhs.mIndexArray.get(), mIndexArraySize *
sizeof(
ValueType));
965 template<
typename TreeType>
970 , mIter(mRangeList.begin())
975 if (leaf && leaf->getIndices(ijk, mRange.first, mRange.second)) {
976 mRangeList.push_back(mRange);
977 mIter = mRangeList.begin();
982 template<
typename TreeType>
987 , mIter(mRangeList.begin())
993 if (!mRangeList.empty()) {
994 mIter = mRangeList.begin();
995 mRange = mRangeList.front();
1000 template<
typename TreeType>
1004 mIter = mRangeList.begin();
1005 if (!mRangeList.empty()) {
1006 mRange = mRangeList.front();
1007 }
else if (mIndexArray) {
1008 mRange.first = mIndexArray.get();
1009 mRange.second = mRange.first + mIndexArraySize;
1011 mRange.first =
static_cast<ValueType*
>(
nullptr);
1012 mRange.second =
static_cast<ValueType*
>(
nullptr);
1017 template<
typename TreeType>
1022 if (mRange.first >= mRange.second && mIter != mRangeList.end()) {
1024 if (mIter != mRangeList.end()) {
1026 }
else if (mIndexArray) {
1027 mRange.first = mIndexArray.get();
1028 mRange.second = mRange.first + mIndexArraySize;
1034 template<
typename TreeType>
1038 if (!this->test())
return false;
1040 return this->test();
1044 template<
typename TreeType>
1049 typename RangeDeque::const_iterator it = mRangeList.begin();
1051 for ( ; it != mRangeList.end(); ++it) {
1052 count += it->second - it->first;
1055 return count + mIndexArraySize;
1059 template<
typename TreeType>
1063 mRange.first =
static_cast<ValueType*
>(
nullptr);
1064 mRange.second =
static_cast<ValueType*
>(
nullptr);
1066 mIter = mRangeList.end();
1067 mIndexArray.reset();
1068 mIndexArraySize = 0;
1072 template<
typename TreeType>
1078 if (leaf && leaf->getIndices(ijk, mRange.first, mRange.second)) {
1079 mRangeList.push_back(mRange);
1080 mIter = mRangeList.begin();
1085 template<
typename TreeType>
1092 if (!mRangeList.empty()) {
1093 mIter = mRangeList.begin();
1094 mRange = mRangeList.front();
1099 template<
typename TreeType>
1100 template<
typename Po
intArray>
1107 std::vector<CoordBBox> searchRegions;
1113 if (minExtent > 2) {
1124 searchRegions.push_back(region);
1128 std::deque<ValueType> filteredIndices;
1130 filter(mRangeList, filteredIndices, bbox, points, xform);
1132 for (
size_t n = 0, N = searchRegions.size(); n < N; ++n) {
1142 template<
typename TreeType>
1143 template<
typename Po
intArray>
1147 bool subvoxelAccuracy)
1150 std::vector<CoordBBox> searchRegions;
1154 Coord::round(
Vec3d(center[0] - radius, center[1] - radius, center[2] - radius)),
1155 Coord::round(
Vec3d(center[0] + radius, center[1] + radius, center[2] + radius)));
1158 const double iRadius = radius * double(1.0 / std::sqrt(3.0));
1159 if (iRadius > 2.0) {
1162 Coord::round(
Vec3d(center[0] - iRadius, center[1] - iRadius, center[2] - iRadius)),
1163 Coord::round(
Vec3d(center[0] + iRadius, center[1] + iRadius, center[2] + iRadius)));
1172 searchRegions.push_back(bbox);
1176 std::deque<ValueType> filteredIndices;
1177 const double leafNodeDim = double(TreeType::LeafNodeType::DIM);
1181 FilterT filter(mRangeList, filteredIndices,
1182 center, radius, points, xform, leafNodeDim, subvoxelAccuracy);
1184 for (
size_t n = 0, N = searchRegions.size(); n < N; ++n) {
1194 template<
typename TreeType>
1195 template<
typename Po
intArray>
1200 this->searchAndUpdate(
1205 template<
typename TreeType>
1206 template<
typename Po
intArray>
1210 bool subvoxelAccuracy)
1213 (radius / xform.
voxelSize()[0]), acc, points, xform, subvoxelAccuracy);
1221 template<
typename Po
intArray,
typename TreeType>
1225 : mPoints(&points), mAcc(tree), mXform(xform), mInvVoxelSize(1.0/xform.voxelSize()[0])
1230 template<
typename Po
intArray,
typename TreeType>
1233 : mPoints(rhs.mPoints)
1234 , mAcc(rhs.mAcc.tree())
1235 , mXform(rhs.mXform)
1236 , mInvVoxelSize(rhs.mInvVoxelSize)
1241 template<
typename Po
intArray,
typename TreeType>
1242 template<
typename FilterType>
1247 if (radius * mInvVoxelSize <
ScalarType(8.0)) {
1249 mXform.worldToIndexCellCentered(center - radius),
1250 mXform.worldToIndexCellCentered(center + radius)), mAcc);
1252 mIter.worldSpaceSearchAndUpdate(
1253 center, radius, mAcc, *mPoints, mXform,
false);
1256 const ScalarType radiusSqr = radius * radius;
1259 for (; mIter; ++mIter) {
1260 mPoints->getPos(*mIter, pos);
1262 distSqr = pos.lengthSqr();
1264 if (distSqr < radiusSqr) {
1265 op(distSqr, *mIter);
1274 template<
typename Gr
idT,
typename Po
intArrayT>
1275 inline typename GridT::Ptr
1278 typename GridT::Ptr grid = GridT::create(
typename GridT::ValueType(0));
1279 grid->setTransform(xform.
copy());
1281 if (points.size() > 0) {
1283 grid->tree(), grid->transform(), points);
1290 template<
typename Gr
idT,
typename Po
intArrayT>
1291 inline typename GridT::Ptr
1295 return createPointIndexGrid<GridT>(points, *xform);
1299 template<
typename Po
intArrayT,
typename Gr
idT>
1306 for (
size_t n = 0, N = leafs.
leafCount(); n < N; ++n) {
1314 tbb::atomic<bool> changed;
1318 op(changed, points, grid.transform());
1322 return !bool(changed);
1326 template<
typename Gr
idT,
typename Po
intArrayT>
1327 inline typename GridT::ConstPtr
1334 return createPointIndexGrid<GridT>(points, grid->transform());
1338 template<
typename Gr
idT,
typename Po
intArrayT>
1339 inline typename GridT::Ptr
1346 return createPointIndexGrid<GridT>(points, grid->transform());
1353 template<
typename T, Index Log2Dim>
1405 const T& value = zeroVal<T>(),
bool active =
false)
1416 template<
typename OtherType, Index OtherLog2Dim>
1427 BaseLeaf::merge<Policy>(rhs);
1429 template<MergePolicy Policy>
void merge(
const ValueType& tileValue,
bool tileActive) {
1430 BaseLeaf::template merge<Policy>(tileValue, tileActive);
1433 template<MergePolicy Policy>
1437 BaseLeaf::template merge<Policy>(other);
1441 template<
typename AccessorT>
1447 template<
typename AccessorT>
1450 template<
typename NodeT,
typename AccessorT>
1454 if (!(std::is_same<NodeT, PointIndexLeafNode>::value))
return nullptr;
1455 return reinterpret_cast<NodeT*
>(
this);
1459 template<
typename AccessorT>
1466 template<
typename AccessorT>
1468 template<
typename AccessorT>
1471 template<
typename NodeT,
typename AccessorT>
1475 if (!(std::is_same<NodeT, PointIndexLeafNode>::value))
return nullptr;
1476 return reinterpret_cast<const NodeT*
>(
this);
1484 void readBuffers(std::istream& is,
bool fromHalf =
false);
1486 void writeBuffers(std::ostream& os,
bool toHalf =
false)
const;
1498 assert(
false &&
"Cannot modify voxel values in a PointIndexTree.");
1524 template<
typename ModifyOp>
1527 template<
typename ModifyOp>
1530 template<
typename ModifyOp>
1539 template<
typename AccessorT>
1542 template<
typename ModifyOp,
typename AccessorT>
1547 template<
typename AccessorT>
1550 template<
typename AccessorT>
1606 #define VMASK_ this->getValueMask()
1650 template<
typename T, Index Log2Dim>
1655 return getIndices(LeafNodeType::coordToOffset(ijk), begin, end);
1659 template<
typename T, Index Log2Dim>
1664 if (this->isValueMaskOn(offset)) {
1665 const ValueType* dataPtr = &mIndices.front();
1666 begin = dataPtr + (offset == 0 ?
ValueType(0) : this->buffer()[offset - 1]);
1667 end = dataPtr + this->buffer()[offset];
1674 template<
typename T, Index Log2Dim>
1678 this->buffer().setValue(offset, val);
1679 this->setValueMaskOn(offset);
1683 template<
typename T, Index Log2Dim>
1687 this->buffer().setValue(offset, val);
1691 template<
typename T, Index Log2Dim>
1698 for (ijk[0] = bbox.
min()[0]; ijk[0] <= bbox.
max()[0]; ++ijk[0]) {
1699 xPos = (ijk[0] & (DIM - 1u)) << (2 * LOG2DIM);
1701 for (ijk[1] = bbox.
min()[1]; ijk[1] <= bbox.
max()[1]; ++ijk[1]) {
1702 pos = xPos + ((ijk[1] & (DIM - 1u)) << LOG2DIM);
1703 pos += (bbox.
min()[2] & (DIM - 1u));
1705 if (this->buffer()[pos+zStride] > (pos == 0 ? T(0) : this->buffer()[pos - 1])) {
1715 template<
typename T, Index Log2Dim>
1719 BaseLeaf::readBuffers(is, fromHalf);
1722 is.read(
reinterpret_cast<char*
>(&numIndices),
sizeof(
Index64));
1724 mIndices.resize(
size_t(numIndices));
1725 is.read(
reinterpret_cast<char*
>(mIndices.data()), numIndices *
sizeof(T));
1729 template<
typename T, Index Log2Dim>
1734 BaseLeaf::readBuffers(is, bbox, fromHalf);
1737 is.read(
reinterpret_cast<char*
>(&numIndices),
sizeof(
Index64));
1739 const Index64 numBytes = numIndices *
sizeof(T);
1741 if (bbox.
hasOverlap(this->getNodeBoundingBox())) {
1742 mIndices.resize(
size_t(numIndices));
1743 is.read(
reinterpret_cast<char*
>(mIndices.data()), numBytes);
1749 std::unique_ptr<char[]> buf{
new char[numBytes]};
1750 is.read(buf.get(), numBytes);
1755 is.read(
reinterpret_cast<char*
>(&auxDataBytes),
sizeof(
Index64));
1756 if (auxDataBytes > 0) {
1758 std::unique_ptr<char[]> auxData{
new char[auxDataBytes]};
1759 is.read(auxData.get(), auxDataBytes);
1764 template<
typename T, Index Log2Dim>
1768 BaseLeaf::writeBuffers(os, toHalf);
1771 os.write(
reinterpret_cast<const char*
>(&numIndices),
sizeof(
Index64));
1772 os.write(
reinterpret_cast<const char*
>(mIndices.data()), numIndices *
sizeof(T));
1776 os.write(
reinterpret_cast<const char*
>(&auxDataBytes),
sizeof(
Index64));
1780 template<
typename T, Index Log2Dim>
1784 return BaseLeaf::memUsage() +
Index64((
sizeof(T)*mIndices.capacity()) +
sizeof(mIndices));
1797 template<Index Dim1,
typename T2>
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
#define VMASK_
Definition: PointIndexGrid.h:1606
Spatially partitions points using a parallel radix-based sorting algorithm.
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:577
Definition: openvdb/Exceptions.h:60
Tag dispatch class that distinguishes constructors during file input.
Definition: openvdb/Types.h:548
const Vec3T & max() const
Return a const reference to the maximum point of this bounding box.
Definition: BBox.h:64
const Vec3T & min() const
Return a const reference to the minimum point of this bounding box.
Definition: BBox.h:62
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:249
const Coord & min() const
Definition: Coord.h:321
void expand(ValueType padding)
Pad this bounding box with the specified padding.
Definition: Coord.h:418
const Coord & max() const
Definition: Coord.h:322
bool hasOverlap(const CoordBBox &b) const
Return true if the given bounding box overlaps with this bounding box.
Definition: Coord.h:412
Coord dim() const
Return the dimensions of the coordinates spanned by this bounding box.
Definition: Coord.h:380
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:26
Int32 y() const
Definition: Coord.h:132
static Coord round(const Vec3< T > &xyz)
Return xyz rounded to the closest integer coordinates (cell centered conversion).
Definition: Coord.h:51
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition: Coord.h:176
void maxComponent(const Coord &other)
Perform a component-wise maximum with the other Coord.
Definition: Coord.h:184
Coord & offset(Int32 dx, Int32 dy, Int32 dz)
Definition: Coord.h:84
Int32 x() const
Definition: Coord.h:131
static Coord max()
Return the largest possible coordinate.
Definition: Coord.h:47
Int32 z() const
Definition: Coord.h:133
Abstract base class for maps.
Definition: Maps.h:135
Definition: InternalNode.h:34
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:30
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:85
void foreach(const LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager.
Definition: LeafManager.h:483
size_t leafCount() const
Return the number of leaf nodes.
Definition: LeafManager.h:287
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition: LeafManager.h:318
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim....
Definition: LeafNode.h:38
static const Index NUM_VOXELS
Definition: LeafNode.h:52
static const Index DIM
Definition: LeafNode.h:50
static const Index LEVEL
Definition: LeafNode.h:54
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...
Definition: LeafNode.h:1469
static const Index NUM_VALUES
Definition: LeafNode.h:51
static const Index LOG2DIM
Definition: LeafNode.h:48
bool operator==(const LeafNode &other) const
Check for buffer, state and origin equivalence.
Definition: LeafNode.h:1431
static const Index SIZE
Definition: LeafNode.h:53
bool isEmpty() const
Return true if this node has no active voxels.
Definition: LeafNode.h:148
static const Index TOTAL
Definition: LeafNode.h:49
Definition: RootNode.h:39
Definition: ValueAccessor.h:183
void addLeaf(LeafNodeT *leaf)
Add the specified leaf to this tree, possibly creating a child branch in the process....
Definition: ValueAccessor.h:329
const LeafNodeT * probeConstLeaf(const Coord &xyz) const
Definition: ValueAccessor.h:384
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation.
Definition: NodeMasks.h:308
DenseMaskIterator< NodeMask > DenseIterator
Definition: NodeMasks.h:350
OnMaskIterator< NodeMask > OnIterator
Definition: NodeMasks.h:348
OffMaskIterator< NodeMask > OffIterator
Definition: NodeMasks.h:349
Selectively extract and filter point data using a custom filter operator.
Partitions points into BucketLog2Dim aligned buckets using a parallel radix-based sorting algorithm.
Vec3< double > Vec3d
Definition: Vec3.h:668
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:477
std::vector< Index > IndexArray
Definition: PointMove.h:161
Index64 pointCount(const PointDataTreeT &tree, const FilterT &filter=NullFilter(), const bool inCoreOnly=false, const bool threaded=true)
Count the total number of points in a PointDataTree.
Definition: PointCount.h:88
Index32 Index
Definition: openvdb/Types.h:32
math::BBox< Vec3d > BBoxd
Definition: openvdb/Types.h:62
uint64_t Index64
Definition: openvdb/Types.h:31
std::shared_ptr< T > SharedPtr
Definition: openvdb/Types.h:92
Definition: openvdb/Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition: openvdb/Exceptions.h:74
Definition: LeafNode.h:204
Leaf nodes have no children, so their child iterators have no get/set accessors.
Definition: LeafNode.h:244
Definition: LeafNode.h:204
Definition: LeafNode.h:204
Definition: LeafNode.h:253
Definition: LeafNode.h:203
Definition: LeafNode.h:212
Definition: LeafNode.h:203
Definition: LeafNode.h:203
Definition: LeafNode.h:912
static const bool value
Definition: LeafNode.h:912
Library and file format version numbers.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:101
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:153