8#ifndef OPENVDB_TOOLS_VOLUME_TO_SPHERES_HAS_BEEN_INCLUDED
9#define OPENVDB_TOOLS_VOLUME_TO_SPHERES_HAS_BEEN_INCLUDED
20#include <tbb/blocked_range.h>
21#include <tbb/parallel_for.h>
22#include <tbb/parallel_reduce.h>
60template<
typename Gr
idT,
typename InterrupterT = util::NullInterrupter>
64 std::vector<openvdb::Vec4s>& spheres,
65 const Vec2i& sphereCount =
Vec2i(1, 50),
66 bool overlapping =
false,
67 float minRadius = 1.0,
68 float maxRadius = std::numeric_limits<float>::max(),
70 int instanceCount = 10000,
71 InterrupterT* interrupter =
nullptr);
80template<
typename Gr
idT>
81class ClosestSurfacePoint
84 using Ptr = std::unique_ptr<ClosestSurfacePoint>;
85 using TreeT =
typename GridT::TreeType;
86 using BoolTreeT =
typename TreeT::template ValueConverter<bool>::Type;
87 using Index32TreeT =
typename TreeT::template ValueConverter<Index32>::Type;
88 using Int16TreeT =
typename TreeT::template ValueConverter<Int16>::Type;
101 template<
typename InterrupterT = util::NullInterrupter>
102 static Ptr create(
const GridT& grid,
float isovalue = 0.0,
103 InterrupterT* interrupter =
nullptr);
108 bool search(
const std::vector<Vec3R>&
points, std::vector<float>& distances);
121 using Index32LeafT =
typename Index32TreeT::LeafNodeType;
122 using IndexRange = std::pair<size_t, size_t>;
124 std::vector<Vec4R> mLeafBoundingSpheres, mNodeBoundingSpheres;
125 std::vector<IndexRange> mLeafRanges;
126 std::vector<const Index32LeafT*> mLeafNodes;
128 size_t mPointListSize = 0, mMaxNodeLeafs = 0;
129 typename Index32TreeT::Ptr mIdxTreePt;
130 typename Int16TreeT::Ptr mSignTreePt;
133 template<
typename InterrupterT = util::NullInterrupter>
134 bool initialize(
const GridT&,
float isovalue, InterrupterT*);
135 bool search(std::vector<Vec3R>&, std::vector<float>&,
bool transformPoints);
146namespace v2s_internal {
150 PointAccessor(std::vector<Vec3R>&
points)
155 void add(
const Vec3R &pos)
157 mPoints.push_back(pos);
160 std::vector<Vec3R>& mPoints;
164template<
typename Index32LeafT>
169 LeafOp(std::vector<Vec4R>& leafBoundingSpheres,
170 const std::vector<const Index32LeafT*>& leafNodes,
171 const math::Transform& transform,
172 const PointList& surfacePointList);
174 void run(
bool threaded =
true);
177 void operator()(
const tbb::blocked_range<size_t>&)
const;
180 std::vector<Vec4R>& mLeafBoundingSpheres;
181 const std::vector<const Index32LeafT*>& mLeafNodes;
182 const math::Transform& mTransform;
186template<
typename Index32LeafT>
187LeafOp<Index32LeafT>::LeafOp(
188 std::vector<Vec4R>& leafBoundingSpheres,
189 const std::vector<const Index32LeafT*>& leafNodes,
190 const math::Transform& transform,
191 const PointList& surfacePointList)
192 : mLeafBoundingSpheres(leafBoundingSpheres)
193 , mLeafNodes(leafNodes)
194 , mTransform(transform)
195 , mSurfacePointList(surfacePointList)
199template<
typename Index32LeafT>
201LeafOp<Index32LeafT>::run(
bool threaded)
204 tbb::parallel_for(tbb::blocked_range<size_t>(0, mLeafNodes.size()), *
this);
206 (*this)(tbb::blocked_range<size_t>(0, mLeafNodes.size()));
210template<
typename Index32LeafT>
212LeafOp<Index32LeafT>::operator()(
const tbb::blocked_range<size_t>& range)
const
214 typename Index32LeafT::ValueOnCIter iter;
217 for (
size_t n = range.begin(); n != range.end(); ++n) {
223 for (iter = mLeafNodes[n]->cbeginValueOn(); iter; ++iter) {
224 avg += mSurfacePointList[iter.getValue()];
227 if (count > 1) avg *= float(1.0 /
double(count));
230 for (iter = mLeafNodes[n]->cbeginValueOn(); iter; ++iter) {
231 float tmpDist = (mSurfacePointList[iter.getValue()] - avg).lengthSqr();
232 if (tmpDist > maxDist) maxDist = tmpDist;
235 Vec4R& sphere = mLeafBoundingSpheres[n];
239 sphere[3] = maxDist * 2.0;
247 using IndexRange = std::pair<size_t, size_t>;
249 NodeOp(std::vector<Vec4R>& nodeBoundingSpheres,
250 const std::vector<IndexRange>& leafRanges,
251 const std::vector<Vec4R>& leafBoundingSpheres);
253 inline void run(
bool threaded =
true);
255 inline void operator()(
const tbb::blocked_range<size_t>&)
const;
258 std::vector<Vec4R>& mNodeBoundingSpheres;
259 const std::vector<IndexRange>& mLeafRanges;
260 const std::vector<Vec4R>& mLeafBoundingSpheres;
264NodeOp::NodeOp(std::vector<Vec4R>& nodeBoundingSpheres,
265 const std::vector<IndexRange>& leafRanges,
266 const std::vector<Vec4R>& leafBoundingSpheres)
267 : mNodeBoundingSpheres(nodeBoundingSpheres)
268 , mLeafRanges(leafRanges)
269 , mLeafBoundingSpheres(leafBoundingSpheres)
274NodeOp::run(
bool threaded)
277 tbb::parallel_for(tbb::blocked_range<size_t>(0, mLeafRanges.size()), *
this);
279 (*this)(tbb::blocked_range<size_t>(0, mLeafRanges.size()));
284NodeOp::operator()(
const tbb::blocked_range<size_t>& range)
const
288 for (
size_t n = range.begin(); n != range.end(); ++n) {
294 int count = int(mLeafRanges[n].second) - int(mLeafRanges[n].first);
296 for (
size_t i = mLeafRanges[n].first; i < mLeafRanges[n].second; ++i) {
297 avg[0] += mLeafBoundingSpheres[i][0];
298 avg[1] += mLeafBoundingSpheres[i][1];
299 avg[2] += mLeafBoundingSpheres[i][2];
302 if (count > 1) avg *= float(1.0 /
double(count));
305 double maxDist = 0.0;
307 for (
size_t i = mLeafRanges[n].first; i < mLeafRanges[n].second; ++i) {
308 pos[0] = mLeafBoundingSpheres[i][0];
309 pos[1] = mLeafBoundingSpheres[i][1];
310 pos[2] = mLeafBoundingSpheres[i][2];
311 const auto radiusSqr = mLeafBoundingSpheres[i][3];
313 double tmpDist = (pos - avg).lengthSqr() + radiusSqr;
314 if (tmpDist > maxDist) maxDist = tmpDist;
317 Vec4R& sphere = mNodeBoundingSpheres[n];
322 sphere[3] = maxDist * 2.0;
330template<
typename Index32LeafT>
331class ClosestPointDist
334 using IndexRange = std::pair<size_t, size_t>;
337 std::vector<Vec3R>& instancePoints,
338 std::vector<float>& instanceDistances,
339 const PointList& surfacePointList,
340 const std::vector<const Index32LeafT*>& leafNodes,
341 const std::vector<IndexRange>& leafRanges,
342 const std::vector<Vec4R>& leafBoundingSpheres,
343 const std::vector<Vec4R>& nodeBoundingSpheres,
345 bool transformPoints =
false);
348 void run(
bool threaded =
true);
351 void operator()(
const tbb::blocked_range<size_t>&)
const;
355 void evalLeaf(
size_t index,
const Index32LeafT& leaf)
const;
356 void evalNode(
size_t pointIndex,
size_t nodeIndex)
const;
359 std::vector<Vec3R>& mInstancePoints;
360 std::vector<float>& mInstanceDistances;
364 const std::vector<const Index32LeafT*>& mLeafNodes;
365 const std::vector<IndexRange>& mLeafRanges;
366 const std::vector<Vec4R>& mLeafBoundingSpheres;
367 const std::vector<Vec4R>& mNodeBoundingSpheres;
369 std::vector<float> mLeafDistances, mNodeDistances;
371 const bool mTransformPoints;
372 size_t mClosestPointIndex;
376template<
typename Index32LeafT>
377ClosestPointDist<Index32LeafT>::ClosestPointDist(
378 std::vector<Vec3R>& instancePoints,
379 std::vector<float>& instanceDistances,
381 const std::vector<const Index32LeafT*>& leafNodes,
382 const std::vector<IndexRange>& leafRanges,
383 const std::vector<Vec4R>& leafBoundingSpheres,
384 const std::vector<Vec4R>& nodeBoundingSpheres,
386 bool transformPoints)
387 : mInstancePoints(instancePoints)
388 , mInstanceDistances(instanceDistances)
389 , mSurfacePointList(surfacePointList)
390 , mLeafNodes(leafNodes)
391 , mLeafRanges(leafRanges)
392 , mLeafBoundingSpheres(leafBoundingSpheres)
393 , mNodeBoundingSpheres(nodeBoundingSpheres)
394 , mLeafDistances(maxNodeLeafs, 0.0)
395 , mNodeDistances(leafRanges.size(), 0.0)
396 , mTransformPoints(transformPoints)
397 , mClosestPointIndex(0)
402template<
typename Index32LeafT>
404ClosestPointDist<Index32LeafT>::run(
bool threaded)
407 tbb::parallel_for(tbb::blocked_range<size_t>(0, mInstancePoints.size()), *
this);
409 (*this)(tbb::blocked_range<size_t>(0, mInstancePoints.size()));
413template<
typename Index32LeafT>
415ClosestPointDist<Index32LeafT>::evalLeaf(
size_t index,
const Index32LeafT& leaf)
const
417 typename Index32LeafT::ValueOnCIter iter;
418 const Vec3s center = mInstancePoints[index];
419 size_t& closestPointIndex =
const_cast<size_t&
>(mClosestPointIndex);
421 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
423 const Vec3s& point = mSurfacePointList[iter.getValue()];
424 float tmpDist = (point - center).lengthSqr();
426 if (tmpDist < mInstanceDistances[index]) {
427 mInstanceDistances[index] = tmpDist;
428 closestPointIndex = iter.getValue();
434template<
typename Index32LeafT>
436ClosestPointDist<Index32LeafT>::evalNode(
size_t pointIndex,
size_t nodeIndex)
const
438 if (nodeIndex >= mLeafRanges.size())
return;
440 const Vec3R& pos = mInstancePoints[pointIndex];
441 float minDist = mInstanceDistances[pointIndex];
442 size_t minDistIdx = 0;
444 bool updatedDist =
false;
446 for (
size_t i = mLeafRanges[nodeIndex].first, n = 0;
447 i < mLeafRanges[nodeIndex].second; ++i, ++n)
449 float& distToLeaf =
const_cast<float&
>(mLeafDistances[n]);
451 center[0] = mLeafBoundingSpheres[i][0];
452 center[1] = mLeafBoundingSpheres[i][1];
453 center[2] = mLeafBoundingSpheres[i][2];
454 const auto radiusSqr = mLeafBoundingSpheres[i][3];
456 distToLeaf = float(std::max(0.0, (pos - center).lengthSqr() - radiusSqr));
458 if (distToLeaf < minDist) {
459 minDist = distToLeaf;
465 if (!updatedDist)
return;
467 evalLeaf(pointIndex, *mLeafNodes[minDistIdx]);
469 for (
size_t i = mLeafRanges[nodeIndex].first, n = 0;
470 i < mLeafRanges[nodeIndex].second; ++i, ++n)
472 if (mLeafDistances[n] < mInstanceDistances[pointIndex] && i != minDistIdx) {
473 evalLeaf(pointIndex, *mLeafNodes[i]);
479template<
typename Index32LeafT>
481ClosestPointDist<Index32LeafT>::operator()(
const tbb::blocked_range<size_t>& range)
const
484 for (
size_t n = range.begin(); n != range.end(); ++n) {
486 const Vec3R& pos = mInstancePoints[n];
487 float minDist = mInstanceDistances[n];
488 size_t minDistIdx = 0;
490 for (
size_t i = 0, I = mNodeDistances.size(); i < I; ++i) {
491 float& distToNode =
const_cast<float&
>(mNodeDistances[i]);
493 center[0] = mNodeBoundingSpheres[i][0];
494 center[1] = mNodeBoundingSpheres[i][1];
495 center[2] = mNodeBoundingSpheres[i][2];
496 const auto radiusSqr = mNodeBoundingSpheres[i][3];
498 distToNode = float(std::max(0.0, (pos - center).lengthSqr() - radiusSqr));
500 if (distToNode < minDist) {
501 minDist = distToNode;
506 evalNode(n, minDistIdx);
508 for (
size_t i = 0, I = mNodeDistances.size(); i < I; ++i) {
509 if (mNodeDistances[i] < mInstanceDistances[n] && i != minDistIdx) {
514 mInstanceDistances[n] = std::sqrt(mInstanceDistances[n]);
516 if (mTransformPoints) mInstancePoints[n] = mSurfacePointList[mClosestPointIndex];
526 const std::vector<Vec3R>& points,
527 std::vector<float>& distances,
528 std::vector<unsigned char>& mask,
531 float radius()
const {
return mRadius; }
532 int index()
const {
return mIndex; }
534 inline void run(
bool threaded =
true);
537 UpdatePoints(UpdatePoints&, tbb::split);
538 inline void operator()(
const tbb::blocked_range<size_t>& range);
539 void join(
const UpdatePoints& rhs)
541 if (rhs.mRadius > mRadius) {
542 mRadius = rhs.mRadius;
548 const Vec4s& mSphere;
549 const std::vector<Vec3R>& mPoints;
550 std::vector<float>& mDistances;
551 std::vector<unsigned char>& mMask;
552 const bool mOverlapping;
558UpdatePoints::UpdatePoints(
560 const std::vector<Vec3R>& points,
561 std::vector<float>& distances,
562 std::vector<unsigned char>& mask,
566 , mDistances(distances)
568 , mOverlapping(overlapping)
575UpdatePoints::UpdatePoints(UpdatePoints& rhs, tbb::split)
576 : mSphere(rhs.mSphere)
577 , mPoints(rhs.mPoints)
578 , mDistances(rhs.mDistances)
580 , mOverlapping(rhs.mOverlapping)
587UpdatePoints::run(
bool threaded)
590 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, mPoints.size()), *
this);
592 (*this)(tbb::blocked_range<size_t>(0, mPoints.size()));
597UpdatePoints::operator()(
const tbb::blocked_range<size_t>& range)
600 for (
size_t n = range.begin(); n != range.end(); ++n) {
601 if (mMask[n])
continue;
603 pos.x() = float(mPoints[n].x()) - mSphere[0];
604 pos.y() = float(mPoints[n].y()) - mSphere[1];
605 pos.z() = float(mPoints[n].z()) - mSphere[2];
607 float dist = pos.length();
609 if (dist < mSphere[3]) {
615 mDistances[n] = std::min(mDistances[n], (dist - mSphere[3]));
618 if (mDistances[n] > mRadius) {
619 mRadius = mDistances[n];
633template<
typename Gr
idT,
typename InterrupterT>
637 std::vector<openvdb::Vec4s>& spheres,
638 const Vec2i& sphereCount,
644 InterrupterT* interrupter)
648 if (grid.empty())
return;
651 minSphereCount = sphereCount[0],
652 maxSphereCount = sphereCount[1];
653 if ((minSphereCount > maxSphereCount) || (maxSphereCount < 1)) {
655 << minSphereCount <<
") exceeds maximum count (" << maxSphereCount <<
")");
658 spheres.reserve(maxSphereCount);
660 auto gridPtr = grid.copy();
668 isovalue = std::min(isovalue,
679 auto numVoxels = gridPtr->activeVoxelCount();
680 if (numVoxels < 10000) {
681 const auto scale = 1.0 /
math::Cbrt(2.0 * 10000.0 /
double(numVoxels));
682 auto scaledXform = gridPtr->transform().copy();
683 scaledXform->preScale(scale);
688 const auto newNumVoxels = newGridPtr->activeVoxelCount();
689 if (newNumVoxels > numVoxels) {
691 << numVoxels <<
" voxel" << (numVoxels == 1 ?
"" :
"s")
692 <<
" to " << newNumVoxels <<
" voxel" << (newNumVoxels == 1 ?
"" :
"s"));
693 gridPtr = newGridPtr;
694 numVoxels = newNumVoxels;
698 const bool addNarrowBandPoints = (numVoxels < 10000);
699 int instances = std::max(instanceCount, maxSphereCount);
701 using TreeT =
typename GridT::TreeType;
702 using BoolTreeT =
typename TreeT::template ValueConverter<bool>::Type;
703 using Int16TreeT =
typename TreeT::template ValueConverter<Int16>::Type;
705 using RandGen = std::mersenne_twister_engine<uint32_t, 32, 351, 175, 19,
706 0xccab8ee7, 11, 0xffffffff, 7, 0x31b6ab00, 15, 0xffe50000, 17, 1812433253>;
709 const TreeT&
tree = gridPtr->tree();
712 std::vector<Vec3R> instancePoints;
722 interiorMaskPtr->
tree().topologyUnion(
tree);
725 if (interrupter && interrupter->wasInterrupted())
return;
730 if (!addNarrowBandPoints || (minSphereCount <= 0)) {
734 auto& maskTree = interiorMaskPtr->
tree();
738 if (maskTree.empty()) { interiorMaskPtr->
setTree(copyOfTree); }
742 instancePoints.reserve(instances);
743 v2s_internal::PointAccessor ptnAcc(instancePoints);
745 const auto scatterCount =
Index64(addNarrowBandPoints ? (instances / 2) : instances);
748 ptnAcc, scatterCount, mtRand, 1.0, interrupter);
749 scatter(*interiorMaskPtr);
752 if (interrupter && interrupter->wasInterrupted())
return;
758 if (instancePoints.size() <
size_t(instances)) {
759 const Int16TreeT& signTree = csp->signTree();
760 for (
auto leafIt = signTree.cbeginLeaf(); leafIt; ++leafIt) {
761 for (
auto it = leafIt->cbeginValueOn(); it; ++it) {
762 const int flags = int(it.getValue());
763 if (!(volume_to_mesh_internal::EDGES & flags)
764 && (volume_to_mesh_internal::INSIDE & flags))
766 instancePoints.push_back(transform.
indexToWorld(it.getCoord()));
768 if (instancePoints.size() ==
size_t(instances))
break;
770 if (instancePoints.size() ==
size_t(instances))
break;
774 if (interrupter && interrupter->wasInterrupted())
return;
778 std::vector<float> instanceRadius;
779 if (!csp->search(instancePoints, instanceRadius))
return;
781 float largestRadius = 0.0;
782 int largestRadiusIdx = 0;
783 for (
size_t n = 0, N = instancePoints.size(); n < N; ++n) {
784 if (instanceRadius[n] > largestRadius) {
785 largestRadius = instanceRadius[n];
786 largestRadiusIdx = int(n);
790 std::vector<unsigned char> instanceMask(instancePoints.size(), 0);
792 minRadius = float(minRadius * transform.
voxelSize()[0]);
793 maxRadius = float(maxRadius * transform.
voxelSize()[0]);
795 for (
size_t s = 0, S = std::min(
size_t(maxSphereCount), instancePoints.size()); s < S; ++s) {
797 if (interrupter && interrupter->wasInterrupted())
return;
799 largestRadius = std::min(maxRadius, largestRadius);
801 if ((
int(s) >= minSphereCount) && (largestRadius < minRadius))
break;
804 float(instancePoints[largestRadiusIdx].x()),
805 float(instancePoints[largestRadiusIdx].y()),
806 float(instancePoints[largestRadiusIdx].z()),
809 spheres.push_back(sphere);
810 instanceMask[largestRadiusIdx] = 1;
812 v2s_internal::UpdatePoints op(
813 sphere, instancePoints, instanceRadius, instanceMask, overlapping);
816 largestRadius = op.radius();
817 largestRadiusIdx = op.index();
825template<
typename Gr
idT>
826template<
typename InterrupterT>
827typename ClosestSurfacePoint<GridT>::Ptr
830 auto csp =
Ptr{
new ClosestSurfacePoint};
831 if (!csp->initialize(grid, isovalue, interrupter)) csp.reset();
836template<
typename Gr
idT>
837template<
typename InterrupterT>
839ClosestSurfacePoint<GridT>::initialize(
840 const GridT& grid,
float isovalue, InterrupterT* interrupter)
843 using ValueT =
typename GridT::ValueType;
845 const TreeT&
tree = grid.tree();
850 BoolTreeT mask(
false);
851 volume_to_mesh_internal::identifySurfaceIntersectingVoxels(mask,
tree, ValueT(isovalue));
853 mSignTreePt.reset(
new Int16TreeT(0));
854 mIdxTreePt.reset(
new Index32TreeT(std::numeric_limits<Index32>::max()));
857 volume_to_mesh_internal::computeAuxiliaryData(
858 *mSignTreePt, *mIdxTreePt, mask,
tree, ValueT(isovalue));
860 if (interrupter && interrupter->wasInterrupted())
return false;
864 using Int16LeafNodeType =
typename Int16TreeT::LeafNodeType;
865 using Index32LeafNodeType =
typename Index32TreeT::LeafNodeType;
867 std::vector<Int16LeafNodeType*> signFlagsLeafNodes;
868 mSignTreePt->getNodes(signFlagsLeafNodes);
870 const tbb::blocked_range<size_t> auxiliaryLeafNodeRange(0, signFlagsLeafNodes.size());
872 std::unique_ptr<Index32[]> leafNodeOffsets(
new Index32[signFlagsLeafNodes.size()]);
874 tbb::parallel_for(auxiliaryLeafNodeRange,
875 volume_to_mesh_internal::LeafNodePointCount<Int16LeafNodeType::LOG2DIM>
876 (signFlagsLeafNodes, leafNodeOffsets));
880 for (
size_t n = 0, N = signFlagsLeafNodes.size(); n < N; ++n) {
881 const Index32 tmp = leafNodeOffsets[n];
882 leafNodeOffsets[n] = pointCount;
886 mPointListSize = size_t(pointCount);
887 mSurfacePointList.reset(
new Vec3s[mPointListSize]);
891 std::vector<Index32LeafNodeType*> pointIndexLeafNodes;
892 mIdxTreePt->getNodes(pointIndexLeafNodes);
894 tbb::parallel_for(auxiliaryLeafNodeRange, volume_to_mesh_internal::ComputePoints<TreeT>(
895 mSurfacePointList.get(),
tree, pointIndexLeafNodes,
896 signFlagsLeafNodes, leafNodeOffsets, transform, ValueT(isovalue)));
899 if (interrupter && interrupter->wasInterrupted())
return false;
901 Index32LeafManagerT idxLeafs(*mIdxTreePt);
903 using Index32RootNodeT =
typename Index32TreeT::RootNodeType;
904 using Index32NodeChainT =
typename Index32RootNodeT::NodeChainType;
905 static_assert(Index32NodeChainT::Size > 1,
906 "expected tree depth greater than one");
907 using Index32InternalNodeT =
typename Index32NodeChainT::template Get<1>;
909 typename Index32TreeT::NodeCIter nIt = mIdxTreePt->cbeginNode();
910 nIt.setMinDepth(Index32TreeT::NodeCIter::LEAF_DEPTH - 1);
911 nIt.setMaxDepth(Index32TreeT::NodeCIter::LEAF_DEPTH - 1);
913 std::vector<const Index32InternalNodeT*> internalNodes;
915 const Index32InternalNodeT* node =
nullptr;
918 if (node) internalNodes.push_back(node);
921 std::vector<IndexRange>().swap(mLeafRanges);
922 mLeafRanges.resize(internalNodes.size());
924 std::vector<const Index32LeafT*>().swap(mLeafNodes);
925 mLeafNodes.reserve(idxLeafs.leafCount());
927 typename Index32InternalNodeT::ChildOnCIter leafIt;
929 for (
size_t n = 0, N = internalNodes.size(); n < N; ++n) {
931 mLeafRanges[n].first = mLeafNodes.size();
933 size_t leafCount = 0;
934 for (leafIt = internalNodes[n]->cbeginChildOn(); leafIt; ++leafIt) {
935 mLeafNodes.push_back(&(*leafIt));
939 mMaxNodeLeafs = std::max(leafCount, mMaxNodeLeafs);
941 mLeafRanges[n].second = mLeafNodes.size();
944 std::vector<Vec4R>().swap(mLeafBoundingSpheres);
945 mLeafBoundingSpheres.resize(mLeafNodes.size());
947 v2s_internal::LeafOp<Index32LeafT> leafBS(
948 mLeafBoundingSpheres, mLeafNodes, transform, mSurfacePointList);
952 std::vector<Vec4R>().swap(mNodeBoundingSpheres);
953 mNodeBoundingSpheres.resize(internalNodes.size());
955 v2s_internal::NodeOp nodeBS(mNodeBoundingSpheres, mLeafRanges, mLeafBoundingSpheres);
961template<
typename Gr
idT>
963ClosestSurfacePoint<GridT>::search(std::vector<Vec3R>&
points,
964 std::vector<float>& distances,
bool transformPoints)
967 distances.resize(
points.size(), std::numeric_limits<float>::infinity());
969 v2s_internal::ClosestPointDist<Index32LeafT> cpd(
points, distances, mSurfacePointList,
970 mLeafNodes, mLeafRanges, mLeafBoundingSpheres, mNodeBoundingSpheres,
971 mMaxNodeLeafs, transformPoints);
979template<
typename Gr
idT>
983 return search(
const_cast<std::vector<Vec3R>&
>(
points), distances,
false);
987template<
typename Gr
idT>
990 std::vector<float>& distances)
1001#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
1003#ifdef OPENVDB_INSTANTIATE_VOLUMETOSPHERES
1010#define _FUNCTION(TreeT) \
1011 void fillWithSpheres(const Grid<TreeT>&, std::vector<openvdb::Vec4s>&, const Vec2i&, \
1012 bool, float, float, float, int, util::NullInterrupter*)
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
Miscellaneous utility methods that operate primarily or exclusively on level set grids.
Implementation of morphological dilation and erosion.
Extract polygonal surfaces from scalar volumes.
void setTransform(math::Transform::Ptr)
Associate the given transform with this grid, in place of its existing transform.
Definition Grid.h:1267
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition Grid.h:906
static Ptr create(const ValueType &background)
Return a new grid with the given background value.
Definition Grid.h:1350
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.
Definition Grid.h:1487
SharedPtr< Grid > Ptr
Definition Grid.h:573
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition LeafManager.h:86
#define OPENVDB_LOG_WARN(message)
Log a warning message of the form 'someVar << "some text" << ...'.
Definition logging.h:256
#define OPENVDB_LOG_DEBUG_RUNTIME(message)
Log a debugging message in both debug and optimized builds.
Definition logging.h:270
OPENVDB_AX_API void run(const char *ax, openvdb::GridBase &grid, const AttributeBindings &bindings={})
Run a full AX pipeline (parse, compile and execute) on a single OpenVDB Grid.
Vec2< int32_t > Vec2i
Definition Vec2.h:569
Vec4< float > Vec4s
Definition Vec4.h:604
Vec3< double > Vec3d
Definition Vec3.h:708
Type Clamp(Type x, Type min, Type max)
Return x clamped to [min, max].
Definition Math.h:274
Vec3< float > Vec3s
Definition Vec3.h:707
float Cbrt(float x)
Return the cube root of a floating-point value.
Definition Math.h:837
Definition AttributeArray.h:42
Definition PointDataGrid.h:170
static const Real LEVEL_SET_HALF_WIDTH
Definition Types.h:532
void initialize()
Global registration of native Grid, Transform, Metadata and Point attribute types....
@ GRID_FOG_VOLUME
Definition Types.h:527
@ GRID_LEVEL_SET
Definition Types.h:526
uint32_t Index32
Definition Types.h:32
math::Vec3< Real > Vec3R
Definition Types.h:53
uint64_t Index64
Definition Types.h:33
math::Vec4< Real > Vec4R
Definition Types.h:68
SharedPtr< T > StaticPtrCast(const SharedPtr< U > &ptr)
Return a new shared pointer that points to the same object as the given pointer after a static_cast.
Definition Types.h:127
Definition Exceptions.h:13
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
static T value()
Definition Math.h:159
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:291
#define OPENVDB_INSTANTIATE_CLASS
Definition version.h.in:231
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)
Definition version.h.in:235