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> 60 template<
typename Gr
idT,
typename InterrupterT = util::NullInterrupter>
64 std::vector<openvdb::Vec4s>& spheres,
66 bool overlapping =
false,
67 float minRadius = 1.0,
70 int instanceCount = 10000,
71 InterrupterT* interrupter =
nullptr);
80 template<
typename Gr
idT>
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);
113 bool searchAndReplace(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);
146 namespace v2s_internal {
150 PointAccessor(std::vector<Vec3R>& points)
155 void add(
const Vec3R &pos)
157 mPoints.push_back(pos);
160 std::vector<Vec3R>& mPoints;
164 template<
typename Index32LeafT>
169 LeafOp(std::vector<Vec4R>& leafBoundingSpheres,
170 const std::vector<const Index32LeafT*>& leafNodes,
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;
186 template<
typename Index32LeafT>
187 LeafOp<Index32LeafT>::LeafOp(
188 std::vector<Vec4R>& leafBoundingSpheres,
189 const std::vector<const Index32LeafT*>& leafNodes,
192 : mLeafBoundingSpheres(leafBoundingSpheres)
193 , mLeafNodes(leafNodes)
194 , mTransform(transform)
195 , mSurfacePointList(surfacePointList)
199 template<
typename Index32LeafT>
204 tbb::parallel_for(tbb::blocked_range<size_t>(0, mLeafNodes.size()), *
this);
206 (*this)(tbb::blocked_range<size_t>(0, mLeafNodes.size()));
210 template<
typename Index32LeafT>
212 LeafOp<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;
264 NodeOp::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)
277 tbb::parallel_for(tbb::blocked_range<size_t>(0, mLeafRanges.size()), *
this);
279 (*this)(tbb::blocked_range<size_t>(0, mLeafRanges.size()));
284 NodeOp::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;
330 template<
typename Index32LeafT>
331 class ClosestPointDist
334 using IndexRange = std::pair<size_t, size_t>;
337 std::vector<Vec3R>& instancePoints,
338 std::vector<float>& instanceDistances,
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;
376 template<
typename Index32LeafT>
377 ClosestPointDist<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)
402 template<
typename Index32LeafT>
407 tbb::parallel_for(tbb::blocked_range<size_t>(0, mInstancePoints.size()), *
this);
409 (*this)(tbb::blocked_range<size_t>(0, mInstancePoints.size()));
413 template<
typename Index32LeafT>
415 ClosestPointDist<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();
434 template<
typename Index32LeafT>
436 ClosestPointDist<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]);
479 template<
typename Index32LeafT>
481 ClosestPointDist<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;
558 UpdatePoints::UpdatePoints(
560 const std::vector<Vec3R>& points,
561 std::vector<float>& distances,
562 std::vector<unsigned char>& mask,
566 , mDistances(distances)
568 , mOverlapping(overlapping)
575 UpdatePoints::UpdatePoints(UpdatePoints& rhs, tbb::split)
576 : mSphere(rhs.mSphere)
577 , mPoints(rhs.mPoints)
578 , mDistances(rhs.mDistances)
580 , mOverlapping(rhs.mOverlapping)
581 , mRadius(rhs.mRadius)
590 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, mPoints.size()), *
this);
592 (*this)(tbb::blocked_range<size_t>(0, mPoints.size()));
597 UpdatePoints::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];
633 template<
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();
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();
735 auto copyOfTree = StaticPtrCast<BoolTreeT>(maskTree.copy());
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();
825 template<
typename Gr
idT>
826 template<
typename InterrupterT>
831 if (!csp->initialize(grid, isovalue, interrupter)) csp.reset();
836 template<
typename Gr
idT>
837 template<
typename InterrupterT>
840 const GridT& grid,
float isovalue, InterrupterT* interrupter)
843 using ValueT =
typename GridT::ValueType;
851 volume_to_mesh_internal::identifySurfaceIntersectingVoxels(mask, tree, ValueT(isovalue));
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];
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);
961 template<
typename Gr
idT>
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);
979 template<
typename Gr
idT>
983 return search(
const_cast<std::vector<Vec3R>&
>(points), distances,
false);
987 template<
typename Gr
idT>
990 std::vector<float>& distances)
992 return search(points, distances,
true);
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*) 1016 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION 1023 #endif // OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED
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
SharedPtr< Grid > Ptr
Definition: Grid.h:579
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
const TreeType & tree() const
Return a const reference to tree associated with this manager.
Definition: LeafManager.h:302
#define OPENVDB_LOG_DEBUG_RUNTIME(message)
Log a debugging message in both debug and optimized builds.
Definition: logging.h:270
Tolerance for floating-point comparison.
Definition: Math.h:147
OPENVDB_IMPORT void initialize()
Global registration of basic types.
Extract polygonal surfaces from scalar volumes.
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:917
Vec2< int32_t > Vec2i
Definition: Vec2.h:534
Implementation of morphological dilation and erosion.
uint64_t Index64
Definition: Types.h:53
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.
Definition: Grid.h:1473
Definition: Exceptions.h:13
ValueT value
Definition: GridBuilder.h:1287
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:84
Vec4< float > Vec4s
Definition: Vec4.h:565
float Cbrt(float x)
Return the cube root of a floating-point value.
Definition: Math.h:772
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:637
Type Clamp(Type x, Type min, Type max)
Return x clamped to [min, max].
Definition: Math.h:260
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:28
#define OPENVDB_INSTANTIATE_CLASS
Definition: version.h.in:143
#define OPENVDB_LOG_WARN(message)
Log a warning message of the form 'someVar << "some text" << ...'.
Definition: logging.h:256
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.
Vec3< float > Vec3s
Definition: Vec3.h:667
Miscellaneous utility methods that operate primarily or exclusively on level set grids.
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)
Definition: version.h.in:147
uint32_t Index32
Definition: Types.h:52
void setTransform(math::Transform::Ptr)
Associate the given transform with this grid, in place of its existing transform. ...
Definition: Grid.h:1247
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
static const Real LEVEL_SET_HALF_WIDTH
Definition: Types.h:422
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202