35 #ifndef OPENVDB_TOOLS_VOLUME_TO_SPHERES_HAS_BEEN_INCLUDED 36 #define OPENVDB_TOOLS_VOLUME_TO_SPHERES_HAS_BEEN_INCLUDED 44 #include <boost/scoped_array.hpp> 45 #include <tbb/blocked_range.h> 46 #include <tbb/parallel_for.h> 47 #include <tbb/parallel_reduce.h> 77 template<
typename Gr
idT,
typename InterrupterT = util::NullInterrupter>
81 std::vector<openvdb::Vec4s>& spheres,
83 bool overlapping =
false,
84 float minRadius = 1.0,
87 int instanceCount = 10000,
88 InterrupterT* interrupter =
nullptr);
97 template<
typename Gr
idT>
101 using TreeT =
typename GridT::TreeType;
102 using BoolTreeT =
typename TreeT::template ValueConverter<bool>::Type;
103 using Index32TreeT =
typename TreeT::template ValueConverter<Index32>::Type;
104 using Int16TreeT =
typename TreeT::template ValueConverter<Int16>::Type;
118 template<
typename InterrupterT = util::NullInterrupter>
119 bool initialize(
const GridT& grid,
float isovalue = 0.0, InterrupterT* interrupter =
nullptr);
124 bool search(
const std::vector<Vec3R>& points, std::vector<float>& distances);
129 bool searchAndReplace(std::vector<Vec3R>& points, std::vector<float>& distances);
137 using Index32LeafT =
typename Index32TreeT::LeafNodeType;
138 using IndexRange = std::pair<size_t, size_t>;
141 std::vector<Vec4R> mLeafBoundingSpheres, mNodeBoundingSpheres;
142 std::vector<IndexRange> mLeafRanges;
143 std::vector<const Index32LeafT*> mLeafNodes;
145 size_t mPointListSize, mMaxNodeLeafs;
147 typename Index32TreeT::Ptr mIdxTreePt;
148 typename Int16TreeT::Ptr mSignTreePt;
150 bool search(std::vector<Vec3R>&, std::vector<float>&,
bool transformPoints);
170 mPoints.push_back(pos);
173 std::vector<Vec3R>& mPoints;
177 template<
typename Index32LeafT>
182 LeafOp(std::vector<Vec4R>& leafBoundingSpheres,
183 const std::vector<const Index32LeafT*>& leafNodes,
187 void run(
bool threaded =
true);
190 void operator()(
const tbb::blocked_range<size_t>&)
const;
193 std::vector<Vec4R>& mLeafBoundingSpheres;
194 const std::vector<const Index32LeafT*>& mLeafNodes;
199 template<
typename Index32LeafT>
201 std::vector<Vec4R>& leafBoundingSpheres,
202 const std::vector<const Index32LeafT*>& leafNodes,
205 : mLeafBoundingSpheres(leafBoundingSpheres)
206 , mLeafNodes(leafNodes)
207 , mTransform(transform)
208 , mSurfacePointList(surfacePointList)
212 template<
typename Index32LeafT>
217 tbb::parallel_for(tbb::blocked_range<size_t>(0, mLeafNodes.size()), *
this);
219 (*this)(tbb::blocked_range<size_t>(0, mLeafNodes.size()));
223 template<
typename Index32LeafT>
227 typename Index32LeafT::ValueOnCIter iter;
230 for (
size_t n = range.begin(); n != range.end(); ++n) {
237 for (iter = mLeafNodes[n]->cbeginValueOn(); iter; ++iter) {
238 avg += mSurfacePointList[iter.getValue()];
242 if (count > 1) avg *= float(1.0 /
double(count));
246 for (iter = mLeafNodes[n]->cbeginValueOn(); iter; ++iter) {
247 float tmpDist = (mSurfacePointList[iter.getValue()] - avg).lengthSqr();
248 if (tmpDist > maxDist) maxDist = tmpDist;
251 Vec4R& sphere = mLeafBoundingSpheres[n];
256 sphere[3] = maxDist * 2.0;
266 NodeOp(std::vector<Vec4R>& nodeBoundingSpheres,
267 const std::vector<IndexRange>& leafRanges,
268 const std::vector<Vec4R>& leafBoundingSpheres);
270 inline void run(
bool threaded =
true);
272 inline void operator()(
const tbb::blocked_range<size_t>&)
const;
275 std::vector<Vec4R>& mNodeBoundingSpheres;
276 const std::vector<IndexRange>& mLeafRanges;
277 const std::vector<Vec4R>& mLeafBoundingSpheres;
282 const std::vector<IndexRange>& leafRanges,
283 const std::vector<Vec4R>& leafBoundingSpheres)
284 : mNodeBoundingSpheres(nodeBoundingSpheres)
285 , mLeafRanges(leafRanges)
286 , mLeafBoundingSpheres(leafBoundingSpheres)
294 tbb::parallel_for(tbb::blocked_range<size_t>(0, mLeafRanges.size()), *
this);
296 (*this)(tbb::blocked_range<size_t>(0, mLeafRanges.size()));
305 for (
size_t n = range.begin(); n != range.end(); ++n) {
311 int count = int(mLeafRanges[n].second) - int(mLeafRanges[n].first);
313 for (
size_t i = mLeafRanges[n].first;
i < mLeafRanges[n].second; ++
i) {
314 avg[0] += mLeafBoundingSpheres[
i][0];
315 avg[1] += mLeafBoundingSpheres[
i][1];
316 avg[2] += mLeafBoundingSpheres[
i][2];
319 if (count > 1) avg *= float(1.0 /
double(count));
322 double maxDist = 0.0;
324 for (
size_t i = mLeafRanges[n].first;
i < mLeafRanges[n].second; ++
i) {
325 pos[0] = mLeafBoundingSpheres[
i][0];
326 pos[1] = mLeafBoundingSpheres[
i][1];
327 pos[2] = mLeafBoundingSpheres[
i][2];
329 double tmpDist = (pos - avg).lengthSqr() + mLeafBoundingSpheres[
i][3];
330 if (tmpDist > maxDist) maxDist = tmpDist;
333 Vec4R& sphere = mNodeBoundingSpheres[n];
338 sphere[3] = maxDist * 2.0;
346 template<
typename Index32LeafT>
353 std::vector<Vec3R>& instancePoints,
354 std::vector<float>& instanceDistances,
356 const std::vector<const Index32LeafT*>& leafNodes,
357 const std::vector<IndexRange>& leafRanges,
358 const std::vector<Vec4R>& leafBoundingSpheres,
359 const std::vector<Vec4R>& nodeBoundingSpheres,
361 bool transformPoints =
false);
364 void run(
bool threaded =
true);
367 void operator()(
const tbb::blocked_range<size_t>&)
const;
371 void evalLeaf(
size_t index,
const Index32LeafT& leaf)
const;
372 void evalNode(
size_t pointIndex,
size_t nodeIndex)
const;
375 std::vector<Vec3R>& mInstancePoints;
376 std::vector<float>& mInstanceDistances;
380 const std::vector<const Index32LeafT*>& mLeafNodes;
381 const std::vector<IndexRange>& mLeafRanges;
382 const std::vector<Vec4R>& mLeafBoundingSpheres;
383 const std::vector<Vec4R>& mNodeBoundingSpheres;
385 std::vector<float> mLeafDistances, mNodeDistances;
387 const bool mTransformPoints;
388 size_t mClosestPointIndex;
392 template<
typename Index32LeafT>
394 std::vector<Vec3R>& instancePoints,
395 std::vector<float>& instanceDistances,
397 const std::vector<const Index32LeafT*>& leafNodes,
398 const std::vector<IndexRange>& leafRanges,
399 const std::vector<Vec4R>& leafBoundingSpheres,
400 const std::vector<Vec4R>& nodeBoundingSpheres,
402 bool transformPoints)
403 : mInstancePoints(instancePoints)
404 , mInstanceDistances(instanceDistances)
405 , mSurfacePointList(surfacePointList)
406 , mLeafNodes(leafNodes)
407 , mLeafRanges(leafRanges)
408 , mLeafBoundingSpheres(leafBoundingSpheres)
409 , mNodeBoundingSpheres(nodeBoundingSpheres)
410 , mLeafDistances(maxNodeLeafs, 0.0)
411 , mNodeDistances(leafRanges.
size(), 0.0)
412 , mTransformPoints(transformPoints)
413 , mClosestPointIndex(0)
418 template<
typename Index32LeafT>
423 tbb::parallel_for(tbb::blocked_range<size_t>(0, mInstancePoints.size()), *
this);
425 (*this)(tbb::blocked_range<size_t>(0, mInstancePoints.size()));
429 template<
typename Index32LeafT>
433 typename Index32LeafT::ValueOnCIter iter;
434 const Vec3s center = mInstancePoints[index];
435 size_t& closestPointIndex =
const_cast<size_t&
>(mClosestPointIndex);
437 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
439 const Vec3s& point = mSurfacePointList[iter.getValue()];
440 float tmpDist = (point - center).lengthSqr();
442 if (tmpDist < mInstanceDistances[index]) {
443 mInstanceDistances[index] = tmpDist;
444 closestPointIndex = iter.getValue();
450 template<
typename Index32LeafT>
452 ClosestPointDist<Index32LeafT>::evalNode(
size_t pointIndex,
size_t nodeIndex)
const 454 if (nodeIndex >= mLeafRanges.size())
return;
456 const Vec3R& pos = mInstancePoints[pointIndex];
457 float minDist = mInstanceDistances[pointIndex];
458 size_t minDistIdx = 0;
460 bool updatedDist =
false;
462 for (
size_t i = mLeafRanges[nodeIndex].first, n = 0;
463 i < mLeafRanges[nodeIndex].second; ++
i, ++n)
465 float& distToLeaf =
const_cast<float&
>(mLeafDistances[n]);
467 center[0] = mLeafBoundingSpheres[
i][0];
468 center[1] = mLeafBoundingSpheres[
i][1];
469 center[2] = mLeafBoundingSpheres[
i][2];
471 distToLeaf = float((pos - center).lengthSqr() - mLeafBoundingSpheres[
i][3]);
473 if (distToLeaf < minDist) {
474 minDist = distToLeaf;
480 if (!updatedDist)
return;
482 evalLeaf(pointIndex, *mLeafNodes[minDistIdx]);
484 for (
size_t i = mLeafRanges[nodeIndex].first, n = 0;
485 i < mLeafRanges[nodeIndex].second; ++
i, ++n)
487 if (mLeafDistances[n] < mInstanceDistances[pointIndex] &&
i != minDistIdx) {
488 evalLeaf(pointIndex, *mLeafNodes[
i]);
494 template<
typename Index32LeafT>
499 for (
size_t n = range.begin(); n != range.end(); ++n) {
501 const Vec3R& pos = mInstancePoints[n];
502 float minDist = mInstanceDistances[n];
503 size_t minDistIdx = 0;
505 for (
size_t i = 0, I = mNodeDistances.size();
i < I; ++
i) {
506 float& distToNode =
const_cast<float&
>(mNodeDistances[
i]);
508 center[0] = mNodeBoundingSpheres[
i][0];
509 center[1] = mNodeBoundingSpheres[
i][1];
510 center[2] = mNodeBoundingSpheres[
i][2];
512 distToNode = float((pos - center).lengthSqr() - mNodeBoundingSpheres[
i][3]);
514 if (distToNode < minDist) {
515 minDist = distToNode;
520 evalNode(n, minDistIdx);
522 for (
size_t i = 0, I = mNodeDistances.size();
i < I; ++
i) {
523 if (mNodeDistances[
i] < mInstanceDistances[n] &&
i != minDistIdx) {
528 mInstanceDistances[n] = std::sqrt(mInstanceDistances[n]);
530 if (mTransformPoints) mInstancePoints[n] = mSurfacePointList[mClosestPointIndex];
540 const std::vector<Vec3R>& points,
541 std::vector<float>& distances,
542 std::vector<unsigned char>& mask,
546 int index()
const {
return mIndex; }
548 inline void run(
bool threaded =
true);
552 inline void operator()(
const tbb::blocked_range<size_t>& range);
555 if (rhs.mRadius > mRadius) {
556 mRadius = rhs.mRadius;
563 const Vec4s& mSphere;
564 const std::vector<Vec3R>& mPoints;
566 std::vector<float>& mDistances;
567 std::vector<unsigned char>& mMask;
577 const std::vector<Vec3R>& points,
578 std::vector<float>& distances,
579 std::vector<unsigned char>& mask,
583 , mDistances(distances)
585 , mOverlapping(overlapping)
593 : mSphere(rhs.mSphere)
594 , mPoints(rhs.mPoints)
595 , mDistances(rhs.mDistances)
597 , mOverlapping(rhs.mOverlapping)
598 , mRadius(rhs.mRadius)
607 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, mPoints.size()), *
this);
609 (*this)(tbb::blocked_range<size_t>(0, mPoints.size()));
617 for (
size_t n = range.begin(); n != range.end(); ++n) {
618 if (mMask[n])
continue;
620 pos.
x() = float(mPoints[n].x()) - mSphere[0];
621 pos.y() = float(mPoints[n].y()) - mSphere[1];
622 pos.z() = float(mPoints[n].z()) - mSphere[2];
624 float dist = pos.length();
626 if (dist < mSphere[3]) {
632 mDistances[n] =
std::min(mDistances[n], (dist - mSphere[3]));
635 if (mDistances[n] > mRadius) {
636 mRadius = mDistances[n];
649 template<
typename Gr
idT,
typename InterrupterT>
653 std::vector<openvdb::Vec4s>& spheres,
660 InterrupterT* interrupter)
663 spheres.reserve(maxSphereCount);
665 const bool addNBPoints = grid.activeVoxelCount() < 10000;
666 int instances =
std::max(instanceCount, maxSphereCount);
668 using TreeT =
typename GridT::TreeType;
669 using ValueT =
typename GridT::ValueType;
671 using BoolTreeT =
typename TreeT::template ValueConverter<bool>::Type;
672 using Int16TreeT =
typename TreeT::template ValueConverter<Int16>::Type;
674 using RandGen = std::mersenne_twister_engine<uint32_t, 32, 351, 175, 19,
675 0xccab8ee7, 11, 0xffffffff, 7, 0x31b6ab00, 15, 0xffe50000, 17, 1812433253>;
678 const TreeT& tree = grid.tree();
681 std::vector<Vec3R> instancePoints;
704 interiorMaskPtr->
tree().topologyUnion(tree);
707 if (interrupter && interrupter->wasInterrupted())
return;
712 instancePoints.reserve(instances);
716 ptnAcc,
Index64(addNBPoints ? (instances / 2) : instances), mtRand, 1.0, interrupter);
718 scatter(*interiorMaskPtr);
721 if (interrupter && interrupter->wasInterrupted())
return;
724 if (!csp.
initialize(grid, isovalue, interrupter))
return;
727 if (instancePoints.size() < size_t(instances)) {
728 const Int16TreeT& signTree = csp.
signTree();
729 for (
auto leafIt = signTree.cbeginLeaf(); leafIt; ++leafIt) {
730 for (
auto it = leafIt->cbeginValueOn(); it; ++it) {
731 const int flags = int(it.getValue());
735 instancePoints.push_back(transform.
indexToWorld(it.getCoord()));
737 if (instancePoints.size() == size_t(instances))
break;
739 if (instancePoints.size() == size_t(instances))
break;
743 if (interrupter && interrupter->wasInterrupted())
return;
745 std::vector<float> instanceRadius;
746 if (!csp.
search(instancePoints, instanceRadius))
return;
748 std::vector<unsigned char> instanceMask(instancePoints.size(), 0);
749 float largestRadius = 0.0;
750 int largestRadiusIdx = 0;
752 for (
size_t n = 0, N = instancePoints.size(); n < N; ++n) {
753 if (instanceRadius[n] > largestRadius) {
754 largestRadius = instanceRadius[n];
755 largestRadiusIdx = int(n);
761 minRadius = float(minRadius * transform.
voxelSize()[0]);
762 maxRadius = float(maxRadius * transform.
voxelSize()[0]);
764 for (
size_t s = 0, S =
std::min(
size_t(maxSphereCount), instancePoints.size()); s < S; ++s) {
766 if (interrupter && interrupter->wasInterrupted())
return;
768 largestRadius =
std::min(maxRadius, largestRadius);
770 if (s != 0 && largestRadius < minRadius)
break;
772 sphere[0] = float(instancePoints[largestRadiusIdx].x());
773 sphere[1] = float(instancePoints[largestRadiusIdx].y());
774 sphere[2] = float(instancePoints[largestRadiusIdx].z());
775 sphere[3] = largestRadius;
777 spheres.push_back(sphere);
778 instanceMask[largestRadiusIdx] = 1;
781 sphere, instancePoints, instanceRadius, instanceMask, overlapping);
784 largestRadius = op.
radius();
785 largestRadiusIdx = op.
index();
793 template<
typename Gr
idT>
795 : mIsInitialized(false)
804 template<
typename Gr
idT>
805 template<
typename InterrupterT>
808 const GridT& grid,
float isovalue, InterrupterT* interrupter)
810 mIsInitialized =
false;
812 using ValueT =
typename GridT::ValueType;
823 mIdxTreePt.reset(
new Index32TreeT(boost::integer_traits<Index32>::const_max));
827 *mSignTreePt, *mIdxTreePt, mask, tree, ValueT(isovalue));
829 if (interrupter && interrupter->wasInterrupted())
return false;
833 using Int16LeafNodeType =
typename Int16TreeT::LeafNodeType;
834 using Index32LeafNodeType =
typename Index32TreeT::LeafNodeType;
836 std::vector<Int16LeafNodeType*> signFlagsLeafNodes;
837 mSignTreePt->getNodes(signFlagsLeafNodes);
839 const tbb::blocked_range<size_t> auxiliaryLeafNodeRange(0, signFlagsLeafNodes.size());
841 boost::scoped_array<Index32> leafNodeOffsets(
new Index32[signFlagsLeafNodes.size()]);
843 tbb::parallel_for(auxiliaryLeafNodeRange,
845 (signFlagsLeafNodes, leafNodeOffsets));
849 for (
size_t n = 0, N = signFlagsLeafNodes.size(); n < N; ++n) {
850 const Index32 tmp = leafNodeOffsets[n];
856 mSurfacePointList.reset(
new Vec3s[mPointListSize]);
860 std::vector<Index32LeafNodeType*> pointIndexLeafNodes;
861 mIdxTreePt->getNodes(pointIndexLeafNodes);
864 mSurfacePointList.get(), tree, pointIndexLeafNodes,
865 signFlagsLeafNodes, leafNodeOffsets, transform, ValueT(isovalue)));
868 if (interrupter && interrupter->wasInterrupted())
return false;
871 CoordBBox bbox = grid.evalActiveVoxelBoundingBox();
876 dim[0] = std::abs(dim[0]);
877 dim[1] = std::abs(dim[1]);
878 dim[2] = std::abs(dim[2]);
881 mMaxRadiusSqr *= 0.51f;
882 mMaxRadiusSqr *= mMaxRadiusSqr;
885 Index32LeafManagerT idxLeafs(*mIdxTreePt);
887 using Index32RootNodeT =
typename Index32TreeT::RootNodeType;
888 using Index32NodeChainT =
typename Index32RootNodeT::NodeChainType;
889 BOOST_STATIC_ASSERT(boost::mpl::size<Index32NodeChainT>::value > 1);
890 using Index32InternalNodeT =
891 typename boost::mpl::at<Index32NodeChainT, boost::mpl::int_<1> >::type;
893 typename Index32TreeT::NodeCIter nIt = mIdxTreePt->cbeginNode();
894 nIt.setMinDepth(Index32TreeT::NodeCIter::LEAF_DEPTH - 1);
895 nIt.setMaxDepth(Index32TreeT::NodeCIter::LEAF_DEPTH - 1);
897 std::vector<const Index32InternalNodeT*> internalNodes;
899 const Index32InternalNodeT* node =
nullptr;
902 if (node) internalNodes.push_back(node);
905 std::vector<IndexRange>().swap(mLeafRanges);
906 mLeafRanges.resize(internalNodes.size());
908 std::vector<const Index32LeafT*>().swap(mLeafNodes);
909 mLeafNodes.reserve(idxLeafs.leafCount());
911 typename Index32InternalNodeT::ChildOnCIter leafIt;
913 for (
size_t n = 0, N = internalNodes.size(); n < N; ++n) {
915 mLeafRanges[n].first = mLeafNodes.size();
917 size_t leafCount = 0;
918 for (leafIt = internalNodes[n]->cbeginChildOn(); leafIt; ++leafIt) {
919 mLeafNodes.push_back(&(*leafIt));
923 mMaxNodeLeafs =
std::max(leafCount, mMaxNodeLeafs);
925 mLeafRanges[n].second = mLeafNodes.size();
928 std::vector<Vec4R>().swap(mLeafBoundingSpheres);
929 mLeafBoundingSpheres.resize(mLeafNodes.size());
932 mLeafBoundingSpheres, mLeafNodes, transform, mSurfacePointList);
936 std::vector<Vec4R>().swap(mNodeBoundingSpheres);
937 mNodeBoundingSpheres.resize(internalNodes.size());
939 internal::NodeOp nodeBS(mNodeBoundingSpheres, mLeafRanges, mLeafBoundingSpheres);
941 mIsInitialized =
true;
946 template<
typename Gr
idT>
949 std::vector<float>& distances,
bool transformPoints)
951 if (!mIsInitialized)
return false;
954 distances.resize(points.size(), mMaxRadiusSqr);
957 mLeafNodes, mLeafRanges, mLeafBoundingSpheres, mNodeBoundingSpheres,
958 mMaxNodeLeafs, transformPoints);
966 template<
typename Gr
idT>
970 return search(
const_cast<std::vector<Vec3R>&
>(points), distances,
false);
974 template<
typename Gr
idT>
977 std::vector<float>& distances)
979 return search(points, distances,
true);
986 #endif // OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED Vec4< float > Vec4s
Definition: Vec4.h:587
Tolerance for floating-point comparison.
Definition: Math.h:117
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:797
SharedPtr< Grid > Ptr
Definition: Grid.h:502
uint32_t Index32
Definition: Types.h:55
tbb::atomic< Index32 > i
Definition: LeafBuffer.h:71
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:261
We offer three different algorithms (each in its own class) for scattering of points in active voxels...
Vec3< float > Vec3s
Definition: Vec3.h:677
uint64_t Index64
Definition: Types.h:56
Extract polygonal surfaces from scalar volumes.
#define OPENVDB_VERSION_NAME
Definition: version.h:43
const TreeType & tree() const
Return a const reference to tree associated with this manager.
Definition: LeafManager.h:343
Implementation of morphological dilation and erosion.
Definition: Exceptions.h:39
const Coord & max() const
Definition: Coord.h:335
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:109
Vec3< double > Vec3d
Definition: Vec3.h:678
OPENVDB_IMPORT void initialize()
Global registration of basic types.
Type Clamp(Type x, Type min, Type max)
Return x clamped to [min, max].
Definition: Math.h:230
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:110
Miscellaneous utility methods that operate primarily or exclusively on level set grids.
void setTransform(math::Transform::Ptr)
Associate the given transform with this grid, in place of its existing transform. ...
Definition: Grid.h:1112
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:55
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
static T value()
Definition: Math.h:117
const Coord & min() const
Definition: Coord.h:334
static constexpr size_t size
The size of a LeafBuffer when LeafBuffer::mOutOfCore is atomic.
Definition: LeafBuffer.h:85
Index64 pointCount(const PointDataTreeT &tree, const bool inCoreOnly=false)
Total points in the PointDataTree.
Definition: PointCount.h:198