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;
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);
146 namespace v2s_internal {
150 PointAccessor(std::vector<Vec3R>&
points)
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;
182 const math::Transform& mTransform;
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>
201 LeafOp<Index32LeafT>::run(
bool threaded)
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)
274 NodeOp::run(
bool threaded)
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>
404 ClosestPointDist<Index32LeafT>::run(
bool threaded)
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;
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);
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)
587 UpdatePoints::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()));
597 UpdatePoints::operator()(
const tbb::blocked_range<size_t>& range)
600 for (
size_t n = range.begin();
n != range.end(); ++
n) {
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];
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);
686 LEVEL_SET_HALF_WIDTH, LEVEL_SET_HALF_WIDTH, scaledXform.get(), interrupter);
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;
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);
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>
827 typename ClosestSurfacePoint<GridT>::Ptr
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)
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));
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()]);
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
void parallel_for(int64_t start, int64_t end, std::function< void(int64_t index)> &&task, parallel_options opt=parallel_options(0, Split_Y, 1))
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
GA_API const UT_StringHolder dist
__hostdev__ uint64_t pointCount() const
GLdouble GLdouble GLint GLint const GLdouble * points
vfloat4 sqrt(const vfloat4 &a)
GLdouble GLdouble GLdouble z
#define OPENVDB_LOG_WARN(mesg)
#define OPENVDB_REAL_TREE_INSTANTIATE(Function)
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
void swap(T &lhs, T &rhs)
#define OPENVDB_USE_VERSION_NAMESPACE
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
Tolerance for floating-point comparison.
float Cbrt(float x)
Return the cube root of a floating-point value.
GA_API const UT_StringHolder scale
IMATH_NAMESPACE::V2f float
#define OPENVDB_INSTANTIATE_CLASS
Extract polygonal surfaces from scalar volumes.
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
OPENVDB_API void initialize()
Global registration of native Grid, Transform, Metadata and Point attribute types. Also initializes blosc (if enabled).
GA_API const UT_StringHolder transform
Miscellaneous utility methods that operate primarily or exclusively on level set grids.
Container class that associates a tree with a transform and metadata.
auto search(const T &set, const V &val) -> std::pair< bool, decltype(std::begin(detail::smart_deref(set)))>
A search function.
Type Clamp(Type x, Type min, Type max)
Return x clamped to [min, max].
#define OPENVDB_LOG_DEBUG_RUNTIME(mesg)
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
GA_API const UT_StringHolder N
Implementation of morphological dilation and erosion.
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
ImageBuf OIIO_API add(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
void OIIO_UTIL_API split(string_view str, std::vector< string_view > &result, string_view sep=string_view(), int maxsplit=-1)
void setTransform(math::Transform::Ptr)
Associate the given transform with this grid, in place of its existing transform. ...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.