OpenVDB: VolumeToSpheres.h Source File

OpenVDB 7.1.0

VolumeToSpheres.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
7
8 #ifndef OPENVDB_TOOLS_VOLUME_TO_SPHERES_HAS_BEEN_INCLUDED
9 #define OPENVDB_TOOLS_VOLUME_TO_SPHERES_HAS_BEEN_INCLUDED
10
11 #include <openvdb/tree/LeafManager.h>
12 #include <openvdb/math/Math.h>
13 #include "Morphology.h" // for erodeVoxels()
14 #include "PointScatter.h"
15 #include "LevelSetRebuild.h"
16 #include "LevelSetUtil.h"
17 #include "VolumeToMesh.h"
18
19 #include <tbb/blocked_range.h>
20 #include <tbb/parallel_for.h>
21 #include <tbb/parallel_reduce.h>
22
23 #include <algorithm> // for std::min(), std::max()
24 #include <cmath> // for std::sqrt()
25 #include <limits> // for std::numeric_limits
26 #include <memory>
27 #include <random>
28 #include <utility> // for std::pair
29 #include <vector>
30
31
32 namespace openvdb {
33 OPENVDB_USE_VERSION_NAMESPACE
34 namespace OPENVDB_VERSION_NAME {
35 namespace tools {
36
59 template<typename GridT, typename InterrupterT = util::NullInterrupter>
60 inline void
61 fillWithSpheres(
62 const GridT& grid,
63 std::vector<openvdb::Vec4s>& spheres,
64 const Vec2i& sphereCount = Vec2i(1, 50),
65 bool overlapping = false,
66 float minRadius = 1.0,
67 float maxRadius = std::numeric_limits<float>::max(),
68 float isovalue = 0.0,
69 int instanceCount = 10000,
70 InterrupterT* interrupter = nullptr);
71
72
74 template<typename GridT, typename InterrupterT = util::NullInterrupter>
75 OPENVDB_DEPRECATED
76 inline void
77 fillWithSpheres(
78 const GridT& grid,
79 std::vector<openvdb::Vec4s>& spheres,
80 int maxSphereCount,
81 bool overlapping = false,
82 float minRadius = 1.0,
83 float maxRadius = std::numeric_limits<float>::max(),
84 float isovalue = 0.0,
85 int instanceCount = 10000,
86 InterrupterT* interrupter = nullptr);
87
88
90
91
95 template<typename GridT>
96 class ClosestSurfacePoint
97 {
98 public:
99 using Ptr = std::unique_ptr<ClosestSurfacePoint>;
100 using TreeT = typename GridT::TreeType;
101 using BoolTreeT = typename TreeT::template ValueConverter<bool>::Type;
102 using Index32TreeT = typename TreeT::template ValueConverter<Index32>::Type;
103 using Int16TreeT = typename TreeT::template ValueConverter<Int16>::Type;
104
116 template<typename InterrupterT = util::NullInterrupter>
117 static inline Ptr create(const GridT& grid, float isovalue = 0.0,
118 InterrupterT* interrupter = nullptr);
119
123 inline bool search(const std::vector<Vec3R>& points, std::vector<float>& distances);
124
128 inline bool searchAndReplace(std::vector<Vec3R>& points, std::vector<float>& distances);
129
131 const Index32TreeT& indexTree() const { return *mIdxTreePt; }
133 const Int16TreeT& signTree() const { return *mSignTreePt; }
134
135 private:
136 using Index32LeafT = typename Index32TreeT::LeafNodeType;
137 using IndexRange = std::pair<size_t, size_t>;
138
139 std::vector<Vec4R> mLeafBoundingSpheres, mNodeBoundingSpheres;
140 std::vector<IndexRange> mLeafRanges;
141 std::vector<const Index32LeafT*> mLeafNodes;
142 PointList mSurfacePointList;
143 size_t mPointListSize = 0, mMaxNodeLeafs = 0;
144 typename Index32TreeT::Ptr mIdxTreePt;
145 typename Int16TreeT::Ptr mSignTreePt;
146
147 ClosestSurfacePoint() = default;
148 template<typename InterrupterT = util::NullInterrupter>
149 inline bool initialize(const GridT&, float isovalue, InterrupterT*);
150 inline bool search(std::vector<Vec3R>&, std::vector<float>&, bool transformPoints);
151 };
152
153
155
156
157 // Internal utility methods
158
159 namespace v2s_internal {
160
161 struct PointAccessor
162 {
163 PointAccessor(std::vector<Vec3R>& points)
164 : mPoints(points)
165 {
166 }
167
168 void add(const Vec3R &pos)
169 {
170 mPoints.push_back(pos);
171 }
172 private:
173 std::vector<Vec3R>& mPoints;
174 };
175
176
177 template<typename Index32LeafT>
178 class LeafOp
179 {
180 public:
181
182 LeafOp(std::vector<Vec4R>& leafBoundingSpheres,
183 const std::vector<const Index32LeafT*>& leafNodes,
184 const math::Transform& transform,
185 const PointList& surfacePointList);
186
187 void run(bool threaded = true);
188
189
190 void operator()(const tbb::blocked_range<size_t>&) const;
191
192 private:
193 std::vector<Vec4R>& mLeafBoundingSpheres;
194 const std::vector<const Index32LeafT*>& mLeafNodes;
195 const math::Transform& mTransform;
196 const PointList& mSurfacePointList;
197 };
198
199 template<typename Index32LeafT>
200 LeafOp<Index32LeafT>::LeafOp(
201 std::vector<Vec4R>& leafBoundingSpheres,
202 const std::vector<const Index32LeafT*>& leafNodes,
203 const math::Transform& transform,
204 const PointList& surfacePointList)
205 : mLeafBoundingSpheres(leafBoundingSpheres)
206 , mLeafNodes(leafNodes)
207 , mTransform(transform)
208 , mSurfacePointList(surfacePointList)
209 {
210 }
211
212 template<typename Index32LeafT>
213 void
214 LeafOp<Index32LeafT>::run(bool threaded)
215 {
216 if (threaded) {
217 tbb::parallel_for(tbb::blocked_range<size_t>(0, mLeafNodes.size()), *this);
218 } else {
219 (*this)(tbb::blocked_range<size_t>(0, mLeafNodes.size()));
220 }
221 }
222
223 template<typename Index32LeafT>
224 void
225 LeafOp<Index32LeafT>::operator()(const tbb::blocked_range<size_t>& range) const
226 {
227 typename Index32LeafT::ValueOnCIter iter;
228 Vec3s avg;
229
230 for (size_t n = range.begin(); n != range.end(); ++n) {
231 avg[0] = 0.0;
232 avg[1] = 0.0;
233 avg[2] = 0.0;
234
235 int count = 0;
236 for (iter = mLeafNodes[n]->cbeginValueOn(); iter; ++iter) {
237 avg += mSurfacePointList[iter.getValue()];
238 ++count;
239 }
240 if (count > 1) avg *= float(1.0 / double(count));
241
242 float maxDist = 0.0;
243 for (iter = mLeafNodes[n]->cbeginValueOn(); iter; ++iter) {
244 float tmpDist = (mSurfacePointList[iter.getValue()] - avg).lengthSqr();
245 if (tmpDist > maxDist) maxDist = tmpDist;
246 }
247
248 Vec4R& sphere = mLeafBoundingSpheres[n];
249 sphere[0] = avg[0];
250 sphere[1] = avg[1];
251 sphere[2] = avg[2];
252 sphere[3] = maxDist * 2.0; // padded radius
253 }
254 }
255
256
257 class NodeOp
258 {
259 public:
260 using IndexRange = std::pair<size_t, size_t>;
261
262 NodeOp(std::vector<Vec4R>& nodeBoundingSpheres,
263 const std::vector<IndexRange>& leafRanges,
264 const std::vector<Vec4R>& leafBoundingSpheres);
265
266 inline void run(bool threaded = true);
267
268 inline void operator()(const tbb::blocked_range<size_t>&) const;
269
270 private:
271 std::vector<Vec4R>& mNodeBoundingSpheres;
272 const std::vector<IndexRange>& mLeafRanges;
273 const std::vector<Vec4R>& mLeafBoundingSpheres;
274 };
275
276 inline
277 NodeOp::NodeOp(std::vector<Vec4R>& nodeBoundingSpheres,
278 const std::vector<IndexRange>& leafRanges,
279 const std::vector<Vec4R>& leafBoundingSpheres)
280 : mNodeBoundingSpheres(nodeBoundingSpheres)
281 , mLeafRanges(leafRanges)
282 , mLeafBoundingSpheres(leafBoundingSpheres)
283 {
284 }
285
286 inline void
287 NodeOp::run(bool threaded)
288 {
289 if (threaded) {
290 tbb::parallel_for(tbb::blocked_range<size_t>(0, mLeafRanges.size()), *this);
291 } else {
292 (*this)(tbb::blocked_range<size_t>(0, mLeafRanges.size()));
293 }
294 }
295
296 inline void
297 NodeOp::operator()(const tbb::blocked_range<size_t>& range) const
298 {
299 Vec3d avg, pos;
300
301 for (size_t n = range.begin(); n != range.end(); ++n) {
302
303 avg[0] = 0.0;
304 avg[1] = 0.0;
305 avg[2] = 0.0;
306
307 int count = int(mLeafRanges[n].second) - int(mLeafRanges[n].first);
308
309 for (size_t i = mLeafRanges[n].first; i < mLeafRanges[n].second; ++i) {
310 avg[0] += mLeafBoundingSpheres[i][0];
311 avg[1] += mLeafBoundingSpheres[i][1];
312 avg[2] += mLeafBoundingSpheres[i][2];
313 }
314
315 if (count > 1) avg *= float(1.0 / double(count));
316
317
318 double maxDist = 0.0;
319
320 for (size_t i = mLeafRanges[n].first; i < mLeafRanges[n].second; ++i) {
321 pos[0] = mLeafBoundingSpheres[i][0];
322 pos[1] = mLeafBoundingSpheres[i][1];
323 pos[2] = mLeafBoundingSpheres[i][2];
324 const auto radiusSqr = mLeafBoundingSpheres[i][3];
325
326 double tmpDist = (pos - avg).lengthSqr() + radiusSqr;
327 if (tmpDist > maxDist) maxDist = tmpDist;
328 }
329
330 Vec4R& sphere = mNodeBoundingSpheres[n];
331
332 sphere[0] = avg[0];
333 sphere[1] = avg[1];
334 sphere[2] = avg[2];
335 sphere[3] = maxDist * 2.0; // padded radius
336 }
337 }
338
339
341
342
343 template<typename Index32LeafT>
344 class ClosestPointDist
345 {
346 public:
347 using IndexRange = std::pair<size_t, size_t>;
348
349 ClosestPointDist(
350 std::vector<Vec3R>& instancePoints,
351 std::vector<float>& instanceDistances,
352 const PointList& surfacePointList,
353 const std::vector<const Index32LeafT*>& leafNodes,
354 const std::vector<IndexRange>& leafRanges,
355 const std::vector<Vec4R>& leafBoundingSpheres,
356 const std::vector<Vec4R>& nodeBoundingSpheres,
357 size_t maxNodeLeafs,
358 bool transformPoints = false);
359
360
361 void run(bool threaded = true);
362
363
364 void operator()(const tbb::blocked_range<size_t>&) const;
365
366 private:
367
368 void evalLeaf(size_t index, const Index32LeafT& leaf) const;
369 void evalNode(size_t pointIndex, size_t nodeIndex) const;
370
371
372 std::vector<Vec3R>& mInstancePoints;
373 std::vector<float>& mInstanceDistances;
374
375 const PointList& mSurfacePointList;
376
377 const std::vector<const Index32LeafT*>& mLeafNodes;
378 const std::vector<IndexRange>& mLeafRanges;
379 const std::vector<Vec4R>& mLeafBoundingSpheres;
380 const std::vector<Vec4R>& mNodeBoundingSpheres;
381
382 std::vector<float> mLeafDistances, mNodeDistances;
383
384 const bool mTransformPoints;
385 size_t mClosestPointIndex;
386 };// ClosestPointDist
387
388
389 template<typename Index32LeafT>
390 ClosestPointDist<Index32LeafT>::ClosestPointDist(
391 std::vector<Vec3R>& instancePoints,
392 std::vector<float>& instanceDistances,
393 const PointList& surfacePointList,
394 const std::vector<const Index32LeafT*>& leafNodes,
395 const std::vector<IndexRange>& leafRanges,
396 const std::vector<Vec4R>& leafBoundingSpheres,
397 const std::vector<Vec4R>& nodeBoundingSpheres,
398 size_t maxNodeLeafs,
399 bool transformPoints)
400 : mInstancePoints(instancePoints)
401 , mInstanceDistances(instanceDistances)
402 , mSurfacePointList(surfacePointList)
403 , mLeafNodes(leafNodes)
404 , mLeafRanges(leafRanges)
405 , mLeafBoundingSpheres(leafBoundingSpheres)
406 , mNodeBoundingSpheres(nodeBoundingSpheres)
407 , mLeafDistances(maxNodeLeafs, 0.0)
408 , mNodeDistances(leafRanges.size(), 0.0)
409 , mTransformPoints(transformPoints)
410 , mClosestPointIndex(0)
411 {
412 }
413
414
415 template<typename Index32LeafT>
416 void
417 ClosestPointDist<Index32LeafT>::run(bool threaded)
418 {
419 if (threaded) {
420 tbb::parallel_for(tbb::blocked_range<size_t>(0, mInstancePoints.size()), *this);
421 } else {
422 (*this)(tbb::blocked_range<size_t>(0, mInstancePoints.size()));
423 }
424 }
425
426 template<typename Index32LeafT>
427 void
428 ClosestPointDist<Index32LeafT>::evalLeaf(size_t index, const Index32LeafT& leaf) const
429 {
430 typename Index32LeafT::ValueOnCIter iter;
431 const Vec3s center = mInstancePoints[index];
432 size_t& closestPointIndex = const_cast<size_t&>(mClosestPointIndex);
433
434 for (iter = leaf.cbeginValueOn(); iter; ++iter) {
435
436 const Vec3s& point = mSurfacePointList[iter.getValue()];
437 float tmpDist = (point - center).lengthSqr();
438
439 if (tmpDist < mInstanceDistances[index]) {
440 mInstanceDistances[index] = tmpDist;
441 closestPointIndex = iter.getValue();
442 }
443 }
444 }
445
446
447 template<typename Index32LeafT>
448 void
449 ClosestPointDist<Index32LeafT>::evalNode(size_t pointIndex, size_t nodeIndex) const
450 {
451 if (nodeIndex >= mLeafRanges.size()) return;
452
453 const Vec3R& pos = mInstancePoints[pointIndex];
454 float minDist = mInstanceDistances[pointIndex];
455 size_t minDistIdx = 0;
456 Vec3R center;
457 bool updatedDist = false;
458
459 for (size_t i = mLeafRanges[nodeIndex].first, n = 0;
460 i < mLeafRanges[nodeIndex].second; ++i, ++n)
461 {
462 float& distToLeaf = const_cast<float&>(mLeafDistances[n]);
463
464 center[0] = mLeafBoundingSpheres[i][0];
465 center[1] = mLeafBoundingSpheres[i][1];
466 center[2] = mLeafBoundingSpheres[i][2];
467 const auto radiusSqr = mLeafBoundingSpheres[i][3];
468
469 distToLeaf = float(std::max(0.0, (pos - center).lengthSqr() - radiusSqr));
470
471 if (distToLeaf < minDist) {
472 minDist = distToLeaf;
473 minDistIdx = i;
474 updatedDist = true;
475 }
476 }
477
478 if (!updatedDist) return;
479
480 evalLeaf(pointIndex, *mLeafNodes[minDistIdx]);
481
482 for (size_t i = mLeafRanges[nodeIndex].first, n = 0;
483 i < mLeafRanges[nodeIndex].second; ++i, ++n)
484 {
485 if (mLeafDistances[n] < mInstanceDistances[pointIndex] && i != minDistIdx) {
486 evalLeaf(pointIndex, *mLeafNodes[i]);
487 }
488 }
489 }
490
491
492 template<typename Index32LeafT>
493 void
494 ClosestPointDist<Index32LeafT>::operator()(const tbb::blocked_range<size_t>& range) const
495 {
496 Vec3R center;
497 for (size_t n = range.begin(); n != range.end(); ++n) {
498
499 const Vec3R& pos = mInstancePoints[n];
500 float minDist = mInstanceDistances[n];
501 size_t minDistIdx = 0;
502
503 for (size_t i = 0, I = mNodeDistances.size(); i < I; ++i) {
504 float& distToNode = const_cast<float&>(mNodeDistances[i]);
505
506 center[0] = mNodeBoundingSpheres[i][0];
507 center[1] = mNodeBoundingSpheres[i][1];
508 center[2] = mNodeBoundingSpheres[i][2];
509 const auto radiusSqr = mNodeBoundingSpheres[i][3];
510
511 distToNode = float(std::max(0.0, (pos - center).lengthSqr() - radiusSqr));
512
513 if (distToNode < minDist) {
514 minDist = distToNode;
515 minDistIdx = i;
516 }
517 }
518
519 evalNode(n, minDistIdx);
520
521 for (size_t i = 0, I = mNodeDistances.size(); i < I; ++i) {
522 if (mNodeDistances[i] < mInstanceDistances[n] && i != minDistIdx) {
523 evalNode(n, i);
524 }
525 }
526
527 mInstanceDistances[n] = std::sqrt(mInstanceDistances[n]);
528
529 if (mTransformPoints) mInstancePoints[n] = mSurfacePointList[mClosestPointIndex];
530 }
531 }
532
533
534 class UpdatePoints
535 {
536 public:
537 UpdatePoints(
538 const Vec4s& sphere,
539 const std::vector<Vec3R>& points,
540 std::vector<float>& distances,
541 std::vector<unsigned char>& mask,
542 bool overlapping);
543
544 float radius() const { return mRadius; }
545 int index() const { return mIndex; }
546
547 inline void run(bool threaded = true);
548
549
550 UpdatePoints(UpdatePoints&, tbb::split);
551 inline void operator()(const tbb::blocked_range<size_t>& range);
552 void join(const UpdatePoints& rhs)
553 {
554 if (rhs.mRadius > mRadius) {
555 mRadius = rhs.mRadius;
556 mIndex = rhs.mIndex;
557 }
558 }
559
560 private:
561 const Vec4s& mSphere;
562 const std::vector<Vec3R>& mPoints;
563 std::vector<float>& mDistances;
564 std::vector<unsigned char>& mMask;
565 bool mOverlapping;
566 float mRadius;
567 int mIndex;
568 };
569
570 inline
571 UpdatePoints::UpdatePoints(
572 const Vec4s& sphere,
573 const std::vector<Vec3R>& points,
574 std::vector<float>& distances,
575 std::vector<unsigned char>& mask,
576 bool overlapping)
577 : mSphere(sphere)
578 , mPoints(points)
579 , mDistances(distances)
580 , mMask(mask)
581 , mOverlapping(overlapping)
582 , mRadius(0.0)
583 , mIndex(0)
584 {
585 }
586
587 inline
588 UpdatePoints::UpdatePoints(UpdatePoints& rhs, tbb::split)
589 : mSphere(rhs.mSphere)
590 , mPoints(rhs.mPoints)
591 , mDistances(rhs.mDistances)
592 , mMask(rhs.mMask)
593 , mOverlapping(rhs.mOverlapping)
594 , mRadius(rhs.mRadius)
595 , mIndex(rhs.mIndex)
596 {
597 }
598
599 inline void
600 UpdatePoints::run(bool threaded)
601 {
602 if (threaded) {
603 tbb::parallel_reduce(tbb::blocked_range<size_t>(0, mPoints.size()), *this);
604 } else {
605 (*this)(tbb::blocked_range<size_t>(0, mPoints.size()));
606 }
607 }
608
609 inline void
610 UpdatePoints::operator()(const tbb::blocked_range<size_t>& range)
611 {
612 Vec3s pos;
613 for (size_t n = range.begin(); n != range.end(); ++n) {
614 if (mMask[n]) continue;
615
616 pos.x() = float(mPoints[n].x()) - mSphere[0];
617 pos.y() = float(mPoints[n].y()) - mSphere[1];
618 pos.z() = float(mPoints[n].z()) - mSphere[2];
619
620 float dist = pos.length();
621
622 if (dist < mSphere[3]) {
623 mMask[n] = 1;
624 continue;
625 }
626
627 if (!mOverlapping) {
628 mDistances[n] = std::min(mDistances[n], (dist - mSphere[3]));
629 }
630
631 if (mDistances[n] > mRadius) {
632 mRadius = mDistances[n];
633 mIndex = int(n);
634 }
635 }
636 }
637
638
639 } // namespace v2s_internal
640
641
643
644
645 template<typename GridT, typename InterrupterT>
646 inline void
647 fillWithSpheres(
648 const GridT& grid,
649 std::vector<openvdb::Vec4s>& spheres,
650 int maxSphereCount,
651 bool overlapping,
652 float minRadius,
653 float maxRadius,
654 float isovalue,
655 int instanceCount,
656 InterrupterT* interrupter)
657 {
658 fillWithSpheres(grid, spheres, Vec2i(1, maxSphereCount), overlapping,
659 minRadius, maxRadius, isovalue, instanceCount, interrupter);
660 }
661
662
663 template<typename GridT, typename InterrupterT>
664 inline void
665 fillWithSpheres(
666 const GridT& grid,
667 std::vector<openvdb::Vec4s>& spheres,
668 const Vec2i& sphereCount,
669 bool overlapping,
670 float minRadius,
671 float maxRadius,
672 float isovalue,
673 int instanceCount,
674 InterrupterT* interrupter)
675 {
676 spheres.clear();
677
678 if (grid.empty()) return;
679
680 const int
681 minSphereCount = sphereCount[0],
682 maxSphereCount = sphereCount[1];
683 if ((minSphereCount > maxSphereCount) || (maxSphereCount < 1)) {
684 OPENVDB_LOG_WARN("fillWithSpheres: minimum sphere count ("
685 << minSphereCount << ") exceeds maximum count (" << maxSphereCount << ")");
686 return;
687 }
688 spheres.reserve(maxSphereCount);
689
690 auto gridPtr = grid.copy(); // shallow copy
691
692 if (gridPtr->getGridClass() == GRID_LEVEL_SET) {
693 // Clamp the isovalue to the level set's background value minus epsilon.
694 // (In a valid narrow-band level set, all voxels, including background voxels,
695 // have values less than or equal to the background value, so an isovalue
696 // greater than or equal to the background value would produce a mask with
697 // effectively infinite extent.)
698 isovalue = std::min(isovalue,
699 static_cast<float>(gridPtr->background() - math::Tolerance<float>::value()));
700 } else if (gridPtr->getGridClass() == GRID_FOG_VOLUME) {
701 // Clamp the isovalue of a fog volume between epsilon and one,
702 // again to avoid a mask with infinite extent. (Recall that
703 // fog volume voxel values vary from zero outside to one inside.)
704 isovalue = math::Clamp(isovalue, math::Tolerance<float>::value(), 1.f);
705 }
706
707 // ClosestSurfacePoint is inaccurate for small grids.
708 // Resample the input grid if it is too small.
709 auto numVoxels = gridPtr->activeVoxelCount();
710 if (numVoxels < 10000) {
711 const auto scale = 1.0 / math::Cbrt(2.0 * 10000.0 / double(numVoxels));
712 auto scaledXform = gridPtr->transform().copy();
713 scaledXform->preScale(scale);
714
715 auto newGridPtr = levelSetRebuild(*gridPtr, isovalue,
716 LEVEL_SET_HALF_WIDTH, LEVEL_SET_HALF_WIDTH, scaledXform.get(), interrupter);
717
718 const auto newNumVoxels = newGridPtr->activeVoxelCount();
719 if (newNumVoxels > numVoxels) {
720 OPENVDB_LOG_DEBUG_RUNTIME("fillWithSpheres: resampled input grid from "
721 << numVoxels << " voxel" << (numVoxels == 1 ? "" : "s")
722 << " to " << newNumVoxels << " voxel" << (newNumVoxels == 1 ? "" : "s"));
723 gridPtr = newGridPtr;
724 numVoxels = newNumVoxels;
725 }
726 }
727
728 const bool addNarrowBandPoints = (numVoxels < 10000);
729 int instances = std::max(instanceCount, maxSphereCount);
730
731 using TreeT = typename GridT::TreeType;
732 using BoolTreeT = typename TreeT::template ValueConverter<bool>::Type;
733 using Int16TreeT = typename TreeT::template ValueConverter<Int16>::Type;
734
735 using RandGen = std::mersenne_twister_engine<uint32_t, 32, 351, 175, 19,
736 0xccab8ee7, 11, 0xffffffff, 7, 0x31b6ab00, 15, 0xffe50000, 17, 1812433253>; // mt11213b
737 RandGen mtRand(/*seed=*/0);
738
739 const TreeT& tree = gridPtr->tree();
740 math::Transform transform = gridPtr->transform();
741
742 std::vector<Vec3R> instancePoints;
743 {
744 // Compute a mask of the voxels enclosed by the isosurface.
745 typename Grid<BoolTreeT>::Ptr interiorMaskPtr;
746 if (gridPtr->getGridClass() == GRID_LEVEL_SET) {
747 interiorMaskPtr = sdfInteriorMask(*gridPtr, isovalue);
748 } else {
749 // For non-level-set grids, the interior mask comprises the active voxels.
750 interiorMaskPtr = typename Grid<BoolTreeT>::Ptr(Grid<BoolTreeT>::create(false));
751 interiorMaskPtr->setTransform(transform.copy());
752 interiorMaskPtr->tree().topologyUnion(tree);
753 }
754
755 if (interrupter && interrupter->wasInterrupted()) return;
756
757 // If the interior mask is small and eroding it results in an empty grid,
758 // use the uneroded mask instead. (But if the minimum sphere count is zero,
759 // then eroding away the mask is acceptable.)
760 if (!addNarrowBandPoints || (minSphereCount <= 0)) {
761 erodeVoxels(interiorMaskPtr->tree(), 1);
762 } else {
763 auto& maskTree = interiorMaskPtr->tree();
764 auto copyOfTree = StaticPtrCast<BoolTreeT>(maskTree.copy());
765 erodeVoxels(maskTree, 1);
766 if (maskTree.empty()) { interiorMaskPtr->setTree(copyOfTree); }
767 }
768
769 // Scatter candidate sphere centroids (instancePoints)
770 instancePoints.reserve(instances);
771 v2s_internal::PointAccessor ptnAcc(instancePoints);
772
773 const auto scatterCount = Index64(addNarrowBandPoints ? (instances / 2) : instances);
774
775 UniformPointScatter<v2s_internal::PointAccessor, RandGen, InterrupterT> scatter(
776 ptnAcc, scatterCount, mtRand, 1.0, interrupter);
777 scatter(*interiorMaskPtr);
778 }
779
780 if (interrupter && interrupter->wasInterrupted()) return;
781
782 auto csp = ClosestSurfacePoint<GridT>::create(*gridPtr, isovalue, interrupter);
783 if (!csp) return;
784
785 // Add extra instance points in the interior narrow band.
786 if (instancePoints.size() < size_t(instances)) {
787 const Int16TreeT& signTree = csp->signTree();
788 for (auto leafIt = signTree.cbeginLeaf(); leafIt; ++leafIt) {
789 for (auto it = leafIt->cbeginValueOn(); it; ++it) {
790 const int flags = int(it.getValue());
791 if (!(volume_to_mesh_internal::EDGES & flags)
792 && (volume_to_mesh_internal::INSIDE & flags))
793 {
794 instancePoints.push_back(transform.indexToWorld(it.getCoord()));
795 }
796 if (instancePoints.size() == size_t(instances)) break;
797 }
798 if (instancePoints.size() == size_t(instances)) break;
799 }
800 }
801
802 if (interrupter && interrupter->wasInterrupted()) return;
803
804 // Assign a radius to each candidate sphere. The radius is the world-space
805 // distance from the sphere's center to the closest surface point.
806 std::vector<float> instanceRadius;
807 if (!csp->search(instancePoints, instanceRadius)) return;
808
809 float largestRadius = 0.0;
810 int largestRadiusIdx = 0;
811 for (size_t n = 0, N = instancePoints.size(); n < N; ++n) {
812 if (instanceRadius[n] > largestRadius) {
813 largestRadius = instanceRadius[n];
814 largestRadiusIdx = int(n);
815 }
816 }
817
818 std::vector<unsigned char> instanceMask(instancePoints.size(), 0);
819
820 minRadius = float(minRadius * transform.voxelSize()[0]);
821 maxRadius = float(maxRadius * transform.voxelSize()[0]);
822
823 for (size_t s = 0, S = std::min(size_t(maxSphereCount), instancePoints.size()); s < S; ++s) {
824
825 if (interrupter && interrupter->wasInterrupted()) return;
826
827 largestRadius = std::min(maxRadius, largestRadius);
828
829 if ((int(s) >= minSphereCount) && (largestRadius < minRadius)) break;
830
831 const Vec4s sphere(
832 float(instancePoints[largestRadiusIdx].x()),
833 float(instancePoints[largestRadiusIdx].y()),
834 float(instancePoints[largestRadiusIdx].z()),
835 largestRadius);
836
837 spheres.push_back(sphere);
838 instanceMask[largestRadiusIdx] = 1;
839
840 v2s_internal::UpdatePoints op(
841 sphere, instancePoints, instanceRadius, instanceMask, overlapping);
842 op.run();
843
844 largestRadius = op.radius();
845 largestRadiusIdx = op.index();
846 }
847 } // fillWithSpheres
848
849
851
852
853 template<typename GridT>
854 template<typename InterrupterT>
855 inline typename ClosestSurfacePoint<GridT>::Ptr
856 ClosestSurfacePoint<GridT>::create(const GridT& grid, float isovalue, InterrupterT* interrupter)
857 {
858 auto csp = Ptr{new ClosestSurfacePoint};
859 if (!csp->initialize(grid, isovalue, interrupter)) csp.reset();
860 return csp;
861 }
862
863
864 template<typename GridT>
865 template<typename InterrupterT>
866 inline bool
867 ClosestSurfacePoint<GridT>::initialize(
868 const GridT& grid, float isovalue, InterrupterT* interrupter)
869 {
870 using Index32LeafManagerT = tree::LeafManager<Index32TreeT>;
871 using ValueT = typename GridT::ValueType;
872
873 const TreeT& tree = grid.tree();
874 const math::Transform& transform = grid.transform();
875
876 { // Extract surface point cloud
877
878 BoolTreeT mask(false);
879 volume_to_mesh_internal::identifySurfaceIntersectingVoxels(mask, tree, ValueT(isovalue));
880
881 mSignTreePt.reset(new Int16TreeT(0));
882 mIdxTreePt.reset(new Index32TreeT(std::numeric_limits<Index32>::max()));
883
884
885 volume_to_mesh_internal::computeAuxiliaryData(
886 *mSignTreePt, *mIdxTreePt, mask, tree, ValueT(isovalue));
887
888 if (interrupter && interrupter->wasInterrupted()) return false;
889
890 // count unique points
891
892 using Int16LeafNodeType = typename Int16TreeT::LeafNodeType;
893 using Index32LeafNodeType = typename Index32TreeT::LeafNodeType;
894
895 std::vector<Int16LeafNodeType*> signFlagsLeafNodes;
896 mSignTreePt->getNodes(signFlagsLeafNodes);
897
898 const tbb::blocked_range<size_t> auxiliaryLeafNodeRange(0, signFlagsLeafNodes.size());
899
900 std::unique_ptr<Index32[]> leafNodeOffsets(new Index32[signFlagsLeafNodes.size()]);
901
902 tbb::parallel_for(auxiliaryLeafNodeRange,
903 volume_to_mesh_internal::LeafNodePointCount<Int16LeafNodeType::LOG2DIM>
904 (signFlagsLeafNodes, leafNodeOffsets));
905
906 {
907 Index32 pointCount = 0;
908 for (size_t n = 0, N = signFlagsLeafNodes.size(); n < N; ++n) {
909 const Index32 tmp = leafNodeOffsets[n];
910 leafNodeOffsets[n] = pointCount;
911 pointCount += tmp;
912 }
913
914 mPointListSize = size_t(pointCount);
915 mSurfacePointList.reset(new Vec3s[mPointListSize]);
916 }
917
918
919 std::vector<Index32LeafNodeType*> pointIndexLeafNodes;
920 mIdxTreePt->getNodes(pointIndexLeafNodes);
921
922 tbb::parallel_for(auxiliaryLeafNodeRange, volume_to_mesh_internal::ComputePoints<TreeT>(
923 mSurfacePointList.get(), tree, pointIndexLeafNodes,
924 signFlagsLeafNodes, leafNodeOffsets, transform, ValueT(isovalue)));
925 }
926
927 if (interrupter && interrupter->wasInterrupted()) return false;
928
929 Index32LeafManagerT idxLeafs(*mIdxTreePt);
930
931 using Index32RootNodeT = typename Index32TreeT::RootNodeType;
932 using Index32NodeChainT = typename Index32RootNodeT::NodeChainType;
933 static_assert(Index32NodeChainT::Size > 1,
934 "expected tree depth greater than one");
935 using Index32InternalNodeT = typename Index32NodeChainT::template Get<1>;
936
937 typename Index32TreeT::NodeCIter nIt = mIdxTreePt->cbeginNode();
938 nIt.setMinDepth(Index32TreeT::NodeCIter::LEAF_DEPTH - 1);
939 nIt.setMaxDepth(Index32TreeT::NodeCIter::LEAF_DEPTH - 1);
940
941 std::vector<const Index32InternalNodeT*> internalNodes;
942
943 const Index32InternalNodeT* node = nullptr;
944 for (; nIt; ++nIt) {
945 nIt.getNode(node);
946 if (node) internalNodes.push_back(node);
947 }
948
949 std::vector<IndexRange>().swap(mLeafRanges);
950 mLeafRanges.resize(internalNodes.size());
951
952 std::vector<const Index32LeafT*>().swap(mLeafNodes);
953 mLeafNodes.reserve(idxLeafs.leafCount());
954
955 typename Index32InternalNodeT::ChildOnCIter leafIt;
956 mMaxNodeLeafs = 0;
957 for (size_t n = 0, N = internalNodes.size(); n < N; ++n) {
958
959 mLeafRanges[n].first = mLeafNodes.size();
960
961 size_t leafCount = 0;
962 for (leafIt = internalNodes[n]->cbeginChildOn(); leafIt; ++leafIt) {
963 mLeafNodes.push_back(&(*leafIt));
964 ++leafCount;
965 }
966
967 mMaxNodeLeafs = std::max(leafCount, mMaxNodeLeafs);
968
969 mLeafRanges[n].second = mLeafNodes.size();
970 }
971
972 std::vector<Vec4R>().swap(mLeafBoundingSpheres);
973 mLeafBoundingSpheres.resize(mLeafNodes.size());
974
975 v2s_internal::LeafOp<Index32LeafT> leafBS(
976 mLeafBoundingSpheres, mLeafNodes, transform, mSurfacePointList);
977 leafBS.run();
978
979
980 std::vector<Vec4R>().swap(mNodeBoundingSpheres);
981 mNodeBoundingSpheres.resize(internalNodes.size());
982
983 v2s_internal::NodeOp nodeBS(mNodeBoundingSpheres, mLeafRanges, mLeafBoundingSpheres);
984 nodeBS.run();
985 return true;
986 } // ClosestSurfacePoint::initialize
987
988
989 template<typename GridT>
990 inline bool
991 ClosestSurfacePoint<GridT>::search(std::vector<Vec3R>& points,
992 std::vector<float>& distances, bool transformPoints)
993 {
994 distances.clear();
995 distances.resize(points.size(), std::numeric_limits<float>::infinity());
996
997 v2s_internal::ClosestPointDist<Index32LeafT> cpd(points, distances, mSurfacePointList,
998 mLeafNodes, mLeafRanges, mLeafBoundingSpheres, mNodeBoundingSpheres,
999 mMaxNodeLeafs, transformPoints);
1000
1001 cpd.run();
1002
1003 return true;
1004 }
1005
1006
1007 template<typename GridT>
1008 inline bool
1009 ClosestSurfacePoint<GridT>::search(const std::vector<Vec3R>& points, std::vector<float>& distances)
1010 {
1011 return search(const_cast<std::vector<Vec3R>& >(points), distances, false);
1012 }
1013
1014
1015 template<typename GridT>
1016 inline bool
1017 ClosestSurfacePoint<GridT>::searchAndReplace(std::vector<Vec3R>& points,
1018 std::vector<float>& distances)
1019 {
1020 return search(points, distances, true);
1021 }
1022
1023 } // namespace tools
1024 } // namespace OPENVDB_VERSION_NAME
1025 } // namespace openvdb
1026
1027 #endif // OPENVDB_TOOLS_VOLUME_TO_MESH_HAS_BEEN_INCLUDED
openvdb::v7_1::math::Vec3< Real >
openvdb::v7_1::tools::v2s_internal::NodeOp
Definition: VolumeToSpheres.h:258
openvdb::v7_1::tools::v2s_internal::NodeOp::operator()
void operator()(const tbb::blocked_range< size_t > &) const
Definition: VolumeToSpheres.h:297
openvdb::v7_1::math::Vec3::x
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:83
openvdb::v7_1::math::Transform::voxelSize
Vec3d voxelSize() const
Return the size of a voxel using the linear component of the map.
Definition: Transform.h:93
openvdb::v7_1::tools::erodeVoxels
void erodeVoxels(TreeType &tree, int iterations=1, NearestNeighbors nn=NN_FACE)
Topologically erode all leaf-level active voxels in the given tree.
Definition: Morphology.h:846
openvdb::v7_1::Grid::Ptr
SharedPtr< Grid > Ptr
Definition: Grid.h:574
openvdb::v7_1::tools::v2s_internal::ClosestPointDist::IndexRange
std::pair< size_t, size_t > IndexRange
Definition: VolumeToSpheres.h:347
openvdb::v7_1::tools::v2s_internal::NodeOp::run
void run(bool threaded=true)
Definition: VolumeToSpheres.h:287
openvdb::v7_1::points::pointCount
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
openvdb::v7_1::math::Transform::copy
Ptr copy() const
Definition: Transform.h:50
LevelSetRebuild.h
openvdb::v7_1::tools::volume_to_mesh_internal::LeafNodePointCount
Definition: VolumeToMesh.h:3889
openvdb::v7_1::tools::v2s_internal::UpdatePoints::UpdatePoints
UpdatePoints(const Vec4s &sphere, const std::vector< Vec3R > &points, std::vector< float > &distances, std::vector< unsigned char > &mask, bool overlapping)
Definition: VolumeToSpheres.h:571
PointScatter.h
We offer three different algorithms (each in its own class) for scattering of points in active voxels...
openvdb::v7_1::tools::PointList
std::unique_ptr< openvdb::Vec3s[]> PointList
Point and primitive list types.
Definition: VolumeToMesh.h:150
openvdb::v7_1::tools::v2s_internal::NodeOp::IndexRange
std::pair< size_t, size_t > IndexRange
Definition: VolumeToSpheres.h:260
openvdb::v7_1::tools::volume_to_mesh_internal::EDGES
@ EDGES
Definition: VolumeToMesh.h:398
openvdb::v7_1::tools::composite::min
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:102
openvdb::v7_1::tools::ClosestSurfacePoint::Index32TreeT
typename TreeT::template ValueConverter< Index32 >::Type Index32TreeT
Definition: VolumeToSpheres.h:102
LevelSetUtil.h
Miscellaneous utility methods that operate primarily or exclusively on level set grids.
openvdb::v7_1::tools::v2s_internal::ClosestPointDist::run
void run(bool threaded=true)
Definition: VolumeToSpheres.h:417
openvdb::v7_1::math::scale
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:620
openvdb::v7_1::tree::LeafManager
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:83
openvdb::v7_1::math::Cbrt
float Cbrt(float x)
Return the cube root of a floating-point value.
Definition: Math.h:736
openvdb::v7_1::math::Tolerance
Tolerance for floating-point comparison.
Definition: Math.h:110
openvdb::v7_1::Index64
uint64_t Index64
Definition: Types.h:30
openvdb::v7_1::Grid::tree
TreeType & tree()
Return a reference to this grid's tree, which might be shared with other grids.
Definition: Grid.h:908
openvdb::v7_1::tools::ClosestSurfacePoint::Ptr
std::unique_ptr< ClosestSurfacePoint > Ptr
Definition: VolumeToSpheres.h:99
openvdb::v7_1::tools::v2s_internal::LeafOp::run
void run(bool threaded=true)
Definition: VolumeToSpheres.h:214
openvdb::v7_1::initialize
OPENVDB_IMPORT void initialize()
Global registration of basic types.
openvdb::v7_1::tools::v2s_internal::UpdatePoints::index
int index() const
Definition: VolumeToSpheres.h:545
openvdb::v7_1::tools::ClosestSurfacePoint::Int16TreeT
typename TreeT::template ValueConverter< Int16 >::Type Int16TreeT
Definition: VolumeToSpheres.h:103
openvdb::v7_1::tools::ClosestSurfacePoint::search
bool search(const std::vector< Vec3R > &points, std::vector< float > &distances)
Compute the distance from each input point to its closest surface point.
Definition: VolumeToSpheres.h:1009
openvdb::v7_1::Grid
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:28
openvdb::v7_1::math::Transform::indexToWorld
Vec3d indexToWorld(const Vec3d &xyz) const
Apply this transformation to the given coordinates.
Definition: Transform.h:108
openvdb::v7_1::math::Vec2i
Vec2< int32_t > Vec2i
Definition: Vec2.h:529
openvdb::v7_1::GRID_LEVEL_SET
@ GRID_LEVEL_SET
Definition: Types.h:818
openvdb::v7_1::tools::levelSetRebuild
GridType::Ptr levelSetRebuild(const GridType &grid, float isovalue=0, float halfWidth=float(LEVEL_SET_HALF_WIDTH), const math::Transform *xform=nullptr)
Return a new grid of type GridType that contains a narrow-band level set representation of an isosurf...
Definition: LevelSetRebuild.h:311
openvdb::v7_1::Index32
uint32_t Index32
Definition: Types.h:29
OPENVDB_DEPRECATED
#define OPENVDB_DEPRECATED
Definition: Platform.h:42
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
openvdb::v7_1::tools::v2s_internal::PointAccessor::add
void add(const Vec3R &pos)
Definition: VolumeToSpheres.h:168
openvdb::v7_1::tools::ClosestSurfacePoint::create
static Ptr create(const GridT &grid, float isovalue=0.0, InterrupterT *interrupter=nullptr)
Extract surface points and construct a spatial acceleration structure.
Definition: VolumeToSpheres.h:856
OPENVDB_LOG_DEBUG_RUNTIME
#define OPENVDB_LOG_DEBUG_RUNTIME(message)
Log a debugging message in both debug and optimized builds.
Definition: logging.h:267
openvdb::v7_1::tools::v2s_internal::PointAccessor::PointAccessor
PointAccessor(std::vector< Vec3R > &points)
Definition: VolumeToSpheres.h:163
openvdb::v7_1::tools::ClosestSurfacePoint
Accelerated closest surface point queries for narrow band level sets.
Definition: VolumeToSpheres.h:97
openvdb::v7_1::math::Vec4s
Vec4< float > Vec4s
Definition: Vec4.h:559
openvdb::v7_1::tools::volume_to_mesh_internal::computeAuxiliaryData
void computeAuxiliaryData(typename InputTreeType::template ValueConverter< Int16 >::Type &signFlagsTree, typename InputTreeType::template ValueConverter< Index32 >::Type &pointIndexTree, const typename InputTreeType::template ValueConverter< bool >::Type &intersectionTree, const InputTreeType &inputTree, typename InputTreeType::ValueType isovalue)
Definition: VolumeToMesh.h:3864
openvdb::v7_1::tools::v2s_internal::UpdatePoints::join
void join(const UpdatePoints &rhs)
Definition: VolumeToSpheres.h:552
openvdb::v7_1::math::Vec3s
Vec3< float > Vec3s
Definition: Vec3.h:661
VolumeToMesh.h
Extract polygonal surfaces from scalar volumes.
openvdb::v7_1::tools::ClosestSurfacePoint::searchAndReplace
bool searchAndReplace(std::vector< Vec3R > &points, std::vector< float > &distances)
Overwrite each input point with its closest surface point.
Definition: VolumeToSpheres.h:1017
openvdb::v7_1::math::Vec3d
Vec3< double > Vec3d
Definition: Vec3.h:662
openvdb::v7_1::tools::ClosestSurfacePoint::signTree
const Int16TreeT & signTree() const
Tree accessor.
Definition: VolumeToSpheres.h:133
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:146
openvdb::v7_1::tools::UniformPointScatter
The two point scatters UniformPointScatter and NonUniformPointScatter depend on the following two cla...
Definition: tools/PointScatter.h:90
openvdb::v7_1::tools::v2s_internal::ClosestPointDist::operator()
void operator()(const tbb::blocked_range< size_t > &) const
Definition: VolumeToSpheres.h:494
openvdb::v7_1::math::Clamp
Type Clamp(Type x, Type min, Type max)
Return x clamped to [min, max].
Definition: Math.h:223
openvdb::v7_1::tools::v2s_internal::UpdatePoints::run
void run(bool threaded=true)
Definition: VolumeToSpheres.h:600
openvdb::v7_1::tools::ClosestSurfacePoint::BoolTreeT
typename TreeT::template ValueConverter< bool >::Type BoolTreeT
Definition: VolumeToSpheres.h:101
LeafManager.h
A LeafManager manages a linear array of pointers to a given tree's leaf nodes, as well as optional au...
openvdb::v7_1::tools::v2s_internal::NodeOp::NodeOp
NodeOp(std::vector< Vec4R > &nodeBoundingSpheres, const std::vector< IndexRange > &leafRanges, const std::vector< Vec4R > &leafBoundingSpheres)
Definition: VolumeToSpheres.h:277
openvdb::v7_1::tools::sdfInteriorMask
GridOrTreeType::template ValueConverter< bool >::Type::Ptr sdfInteriorMask(const GridOrTreeType &volume, typename GridOrTreeType::ValueType isovalue=lsutilGridZero< GridOrTreeType >())
Threaded method to construct a boolean mask that represents interior regions in a signed distance fie...
Definition: LevelSetUtil.h:2270
openvdb::v7_1::GRID_FOG_VOLUME
@ GRID_FOG_VOLUME
Definition: Types.h:819
openvdb::v7_1::tools::fillWithSpheres
void fillWithSpheres(const GridT &grid, std::vector< openvdb::Vec4s > &spheres, int maxSphereCount, bool overlapping, float minRadius, float maxRadius, float isovalue, int instanceCount, InterrupterT *interrupter)
Definition: VolumeToSpheres.h:647
openvdb::v7_1::tools::volume_to_mesh_internal::identifySurfaceIntersectingVoxels
void identifySurfaceIntersectingVoxels(typename InputTreeType::template ValueConverter< bool >::Type &intersectionTree, const InputTreeType &inputTree, typename InputTreeType::ValueType isovalue)
Definition: VolumeToMesh.h:3322
openvdb::v7_1::tools::ClosestSurfacePoint::TreeT
typename GridT::TreeType TreeT
Definition: VolumeToSpheres.h:100
openvdb::v7_1::math::Vec4
Definition: Mat4.h:24
openvdb::v7_1::tools::fillWithSpheres
void fillWithSpheres(const GridT &grid, std::vector< openvdb::Vec4s > &spheres, const Vec2i &sphereCount=Vec2i(1, 50), bool overlapping=false, float minRadius=1.0, float maxRadius=std::numeric_limits< float >::max(), float isovalue=0.0, int instanceCount=10000, InterrupterT *interrupter=nullptr)
Fill a closed level set or fog volume with adaptively-sized spheres.
Definition: VolumeToSpheres.h:665
Morphology.h
Implementation of morphological dilation and erosion.
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:94
openvdb::v7_1::tools::v2s_internal::UpdatePoints::operator()
void operator()(const tbb::blocked_range< size_t > &range)
Definition: VolumeToSpheres.h:610
openvdb::v7_1::Grid::setTree
void setTree(TreeBase::Ptr) override
Associate the given tree with this grid, in place of its existing tree.
Definition: Grid.h:1471
openvdb::v7_1::tools::v2s_internal::UpdatePoints::radius
float radius() const
Definition: VolumeToSpheres.h:544
openvdb::v7_1::math::Transform
Definition: Transform.h:40
openvdb::v7_1::tools::v2s_internal::ClosestPointDist
Definition: VolumeToSpheres.h:345
openvdb::v7_1::tools::v2s_internal::LeafOp
Definition: VolumeToSpheres.h:179
openvdb
Definition: Exceptions.h:13
openvdb::v7_1::LEVEL_SET_HALF_WIDTH
static const Real LEVEL_SET_HALF_WIDTH
Definition: Types.h:824
openvdb::v7_1::tools::v2s_internal::LeafOp::operator()
void operator()(const tbb::blocked_range< size_t > &) const
Definition: VolumeToSpheres.h:225
openvdb::v7_1::tools::v2s_internal::UpdatePoints
Definition: VolumeToSpheres.h:535
openvdb::v7_1::tools::v2s_internal::ClosestPointDist::ClosestPointDist
ClosestPointDist(std::vector< Vec3R > &instancePoints, std::vector< float > &instanceDistances, const PointList &surfacePointList, const std::vector< const Index32LeafT * > &leafNodes, const std::vector< IndexRange > &leafRanges, const std::vector< Vec4R > &leafBoundingSpheres, const std::vector< Vec4R > &nodeBoundingSpheres, size_t maxNodeLeafs, bool transformPoints=false)
Definition: VolumeToSpheres.h:390
openvdb::v7_1::tree::LeafManager::tree
const TreeType & tree() const
Return a const reference to tree associated with this manager.
Definition: LeafManager.h:315
openvdb::v7_1::tools::v2s_internal::PointAccessor
Definition: VolumeToSpheres.h:162
openvdb::v7_1::tools::ClosestSurfacePoint::indexTree
const Index32TreeT & indexTree() const
Tree accessor.
Definition: VolumeToSpheres.h:131
openvdb::v7_1::tools::composite::max
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:106
OPENVDB_LOG_WARN
#define OPENVDB_LOG_WARN(message)
Log a warning message of the form 'someVar << "some text" << ...'.
Definition: logging.h:253
openvdb::v7_1::tools::volume_to_mesh_internal::INSIDE
@ INSIDE
Definition: VolumeToMesh.h:398