OpenVDB 13.0.1
Loading...
Searching...
No Matches
PolySoupToLevelSet.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/// @author Ken Museth
5///
6/// @file tools/PolySoupToLevelSet.h
7///
8/// @brief Generates a LOD family of watertight shrink wrap level set surfaces
9/// (or meshes) from a soup of polygons.
10///
11/// @details Details of this algorithm are given in an upcoming publication.
12
13#ifndef OPENVDB_TOOLS_POLYSOUP_TO_LEVELSET_HAS_BEEN_INCLUDED
14#define OPENVDB_TOOLS_POLYSOUP_TO_LEVELSET_HAS_BEEN_INCLUDED
15
16#include <openvdb/Types.h>
17#include <openvdb/Grid.h>
18#include <openvdb/math/Math.h>
19#include <openvdb/util/Assert.h>
20
21#include "Composite.h" // for csgUnion
22#include "ValueTransformer.h"// for tools::foreach
23#include "GridTransformer.h" // for resampleToMatch
24#include "MeshToVolume.h"// for meshToLevelSet
25#include "VolumeToMesh.h"// for volumeToMesh
26#include "LevelSetDilatedMesh.h"// for createLevelSetDilatedMesh
27#include "LevelSetFilter.h"// for Filter
28#include "LevelSetMeasure.h"// for levelSetVolume
29#include "FastSweeping.h"// for fogToSdf
30#include "LevelSetUtil.h" // for distanceFieldToSDF
31
32#include <iostream>
33#include <vector>
34
35namespace openvdb {
37namespace OPENVDB_VERSION_NAME {
38namespace tools {
39
40/// @brief Simple structure for a polygon soup
41/// @details bbox is allowed to be invalid, in which case it will be derived from vtx
42struct PolySoup {
43 std::vector<Vec3s> vtx;
44 std::vector<Vec3I> tri;
45 std::vector<Vec4I> quad;
47};
48
49/// @brief Class used to define and control the shrink wrap behaviour.
50/// @note This class is required to have a member method with the signature:
51/// float operator()(float dx) const.
52/// @details See D(dx) in our paper for details on the closing threshold.
53class ShrinkWrapLimit;
54
55/// @brief Class that implements the actual shrink wrap algorithm
56/// @tparam GridType Template parameter of the desired shrink wrap grids
57template <typename GridType = FloatGrid>
59
60/// @brief Convert a soup of polygons to a shrink wrapped level set volume. This version
61/// takes a PolySoup struct and optional voxel dimension and/or voxel size. If the
62/// voxel size is invalid, i.e. not positive, the dimension and bbox of the PolySoup
63/// is used to derive the voxel size.
64///
65/// @return A shared pointer to grid of type @c GridType containing a narrow-band level set
66/// that shrink wraps the input polygons.
67///
68/// @throw TypeError if @c GridType is not scalar or not floating-point
69///
70/// @note Unlike tools::meshToLevelSet this method works for any polygons,
71/// and does not require a closed surface.
72///
73/// @param poly Struct with polygon soup, that will be destroyed (moved)
74/// @param dim Optional dimension in voxel units (assuming voxelSize is invalid)
75/// @param voxelSize Optional voxel size in world units (if invalid dim will be used instead)
76/// @param D Functor mapping voxel size to maximum allowed surface deformation
77/// allowed by shrink wrapping as a function of the voxel size
78/// @param halfWidth Half the width of the narrow band, in voxel units
79/// @param progress Optional pointer to progress bar
80/// @param offset_mode EXPERIMENTAL parameter that will be removed in the near
81/// future. It should only be used by experts!
82template<typename GridType, class ShrinkWrapT = ShrinkWrapLimit, class ProgressT = void>
83typename GridType::Ptr
85 PolySoup &&poly,
86 int dim = 256,
87 float voxelSize = 0.0,// invalid so use dim instead
88 const ShrinkWrapT &D = ShrinkWrapT(),
89 float halfWidth = float(LEVEL_SET_HALF_WIDTH),
90 ProgressT *progress = nullptr,
91 int offset_mode = 0);
92
93/// @brief Convert a soup of polygons to a LOD sequence of shrink wrapped level set volumes.
94///
95/// @return a vector of grids of type @c GridType containing a narrow-band level set
96/// at various resolution shrink wrapping the input polygon mesh. The first
97/// element in this vector has the highest resolution.
98///
99/// @throw TypeError if @c GridType is not scalar or not floating-point
100///
101/// @note Unlike tools::meshToLevelSet this method works for any polygons,
102/// and does not require a closed surface.
103///
104/// @param dim Largest voxel dimension of the finest output grid
105/// @param bbox Bounding box of the vertices of the polygon mesh
106/// @param vtx Vector of world space vertex positions
107/// @param tri Vector of triangle indices
108/// @param quad Vector of quad indices
109/// @param D Functor mapping voxel size to maximum allowed surface deformation
110/// allowed by shrink wrapping as a function of the voxel size
111/// @param halfWidth Half the width of the narrow band, in voxel units
112/// @param progress Optional pointer to progress bar
113/// @param offset_mode EXPERIMENTAL parameter that will be removed in the near
114/// future. It should only be used by experts!
115template<typename GridType, class ShrinkWrapT = ShrinkWrapLimit, class ProgressT = void>
116std::vector<typename GridType::Ptr>
118 int dim,
119 const math::BBox<Vec3f> &bbox,
120 std::vector<Vec3s>& vtx,
121 std::vector<Vec3I>& tri,
122 std::vector<Vec4I>& quad,
123 const ShrinkWrapT &D = ShrinkWrapT(),
124 float halfWidth = float(LEVEL_SET_HALF_WIDTH),
125 ProgressT *progress = nullptr,
126 int offset_mode = 0);
127
128/// @brief Convert a soup of polygons to a LOD sequence of shrink wrapped level set volumes.
129///
130/// @return a vector of grids of type @c GridType containing a narrow-band level set
131/// at various resolution shrink wrapping the input polygon mesh. The first
132/// element in this vector has the highest resolution.
133///
134/// @throw TypeError if @c GridType is not scalar or not floating-point
135///
136/// @note Unlike tools::meshToLevelSet this method works for any polygons,
137/// and does not require a closed surface.
138///
139/// @param minVoxelSize Finest/smallest voxel size of the output grids
140/// @param bbox bounding box of the vertices of the polygon mesh
141/// @param vtx vector of world space vertex positions
142/// @param tri vector of triangle indies
143/// @param quad vector of quad indices
144/// @param D functor mapping voxel size to maximum allowed surface deformation
145/// allowed by shrink wrapping as a function of the voxel size
146/// @param halfWidth half the width of the narrow band, in voxel units
147/// @param progress optional pointer to progress bar
148/// @param offset_mode EXPERIMENTAL parameter that will be removed in the near
149/// future. It should only be used by experts!
150template<typename GridType, class ShrinkWrapT = ShrinkWrapLimit, class ProgressT = void>
151std::vector<typename GridType::Ptr>
153 float minVoxelSize,
154 const math::BBox<Vec3f> &bbox,
155 std::vector<Vec3s>& vtx,
156 std::vector<Vec3I>& tri,
157 std::vector<Vec4I>& quad,
158 const ShrinkWrapT &D = ShrinkWrapT(),
159 float halfWidth = float(LEVEL_SET_HALF_WIDTH),
160 ProgressT *progress = nullptr,
161 int offset_mode = 0);
162
163/////////////////////////////////////////////////////////////////////////////////////
164
165/// @brief This class implements our shrink wrap algorithm. Normally the free-standing
166/// function called above should be used instead of this class.
167/// @tparam GridType Grid type of the generated level set surfaces (defaults to FloatGrid)
168template<typename GridType>
170{
171public:
172
173 /// @brief Constructor from a desired voxel dimension.
174 /// @param poly Polygon soup that will be moved to this instance.
175 /// @param dim Desired voxel dimension of the output level set.
176 /// @param width Half-width of the output narrow-band level set, in voxel units.
177 PolySoupToLevelSet(PolySoup &&poly, int dim, float width = float(LEVEL_SET_HALF_WIDTH));
178
179 /// @brief Constructor from a desired voxel size.
180 /// @param poly Polygon soup that will be moved to this instance.
181 /// @param voxelSize Desired voxel size of the output level set in world units.
182 /// @param width Half-width of the output narrow-band level set, in voxel units.
183 PolySoupToLevelSet(PolySoup &&poly, float voxelSize, float width = float(LEVEL_SET_HALF_WIDTH));
184
185 /// @brief Performs the actual processing to generate the shrink wrap surfaces.
186 /// @tparam ShrinkWrapT Optional template parameter of the functor controlling
187 /// the number of constrained erosion steps (see our paper).
188 /// @tparam ProgressT Template parameter of the optional progress bar.
189 /// @param D Optional functor controlling the number of constrained
190 /// erosion steps and the closing threshold (see our paper).
191 /// @param progress Optional pointer to a progress bar.
192 /// @param mode EXPERIMENTAL parameter that will be removed in the near
193 /// future. It should only be used by experts!
194 template<class ShrinkWrapT, class ProgressT>
195 void process(const ShrinkWrapT &D, ProgressT *progress, int mode = 0);
196
197 /// @brief Number of shrink wrap grids generated, i.e. depth of the LOD hierarchy.
198 size_t gridCount() const {return mGrids.size();}
199
200 /// @brief Returns a shared pointer to a particular shrink wrap grid
201 /// @param n Number of the shrink wrap grid, where n = 0 has the finest sampling and
202 /// n = gridCount-1 is the coarsest voxel sampling.
203 typename GridType::Ptr grid(int n = 0) const {return mGrids[n];}
204
205 /// @brief Vector with shared pointers to all the shrink wrap grids
206 /// @note The grids are arranged fine to coarse, grids()[0] is the finest.
207 std::vector<typename GridType::Ptr> grids() const {return mGrids;}
208
209 /// @brief Generate an adaptive polygon mesh from a particular shrink wrap SDF
210 /// @param n Number of the shrink wrap grid, where n = 0 has the finest sampling and
211 /// n = gridCount-1 is the coarsest voxel sampling.
212 /// @param adaptivity Optional adaptivity parameter used for meshing. A value of zero
213 /// means adaptivity is disabled, i.e. uniform quads are produced.
214 /// @param isoValue Iso-value used for the mesh generation.
215 /// @return Reference to the internal PolySoup populated with the generated mesh.
216 const PolySoup& mesh(int n = 0, float adaptivity = 0.005f, float isoValue = 0.0f)
217 {
218 volumeToMesh(*mGrids[n], mPoly.vtx, mPoly.tri, mPoly.quad, isoValue, adaptivity);
219 return mPoly;
220 }
221
222 /// @brief Static method that computes the bounding box of a list of vertex coordinates.
223 /// @param vtx Vector of vertex coordinates.
224 static math::BBox<Vec3f> getBBox(const std::vector<Vec3s> &vtx);
225
226 /// @brief Generates a dx-offset level set surface from the internal polygon soup.
227 /// @param dx Voxel size (world units) of the output level set.
228 /// @param mode 0) old method (using mesh -> UDF -> mesh -> SDF), 1) Mihai's
229 /// signed-flood-fill and 2) Greg's createLevelSetDilatedMesh
230 /// @return Shared pointer to the newly created level set grid.
231 auto offset(float dx, int mode = 0);
232
233 /// @brief Returns the finest/smallest voxel size, in world units, i.e. the
234 /// voxel size of the final (highest-resolution) level set surface.
235 float minVoxelSize() const {return mMinVoxelSize;}
236
237 /// @brief Returns the coarsest/largest voxel size, in world units, used to
238 /// initiate the coarse-to-fine shrink wrap algorithm.
239 float maxVoxelSize() const {return mMaxVoxelSize;}
240
241 /// @brief Returns the half-width of the output narrow-band level set, in voxel units.
242 float halfWidth() const {return mHalfWidth;}
243
244private:
245 PolySoup mPoly;
246 float mMinVoxelSize, mMaxVoxelSize, mHalfWidth;
247 std::vector<typename GridType::Ptr> mGrids;// fine(0) -> coarse grids(size-1)
248 bool mIsGridSDF;
249
250 /// @brief Private method that resamples inGrid(dx) to outGrid(dx/2).
251 auto upsample(const GridType &inGrid);
252
253 /// @brief Performs the shrink wrap operation as a constrained level set erosion.
254 auto shrinkWrap(GridType &grid, const GridType &gridB, float &d);
255
256};// PolySoupToLevelSet<GridType>
257
258/////////////////////////////////////////////////////////////////////////////////////
259
260template<typename GridType>
262 : mPoly(poly), mHalfWidth(width)
263{
264 if constexpr(!std::is_floating_point<typename GridType::ValueType>::value) {
265 OPENVDB_THROW(TypeError, "polySoupToLevelSet: supported only for scalar floating-point grids");
266 }
267 if (!(mHalfWidth > 0.0f)) {
268 OPENVDB_THROW(ValueError, "polySoupToLevelSet: halfWidth must be positive");
269 }
270 if (!mPoly.bbox) mPoly.bbox = PolySoupToLevelSet::getBBox(mPoly.vtx);
271 // The largest extent is what the algorithm divides by; requiring it to be
272 // positive rejects both empty geometry (an unpopulated bbox has a negative
273 // extent) and a single degenerate point, while still allowing a flat/planar
274 // mesh (zero extent along one axis is fine for shrink wrapping).
275 const float maxLength = mPoly.bbox.extents()[mPoly.bbox.maxExtent()];
276 if (!(maxLength > 0.0f)) {
277 OPENVDB_THROW(ValueError, "polySoupToLevelSet: bounding box has non-positive extent (no input geometry?)");
278 }
279 mMinVoxelSize = maxLength/(float(dim) - 2.0f*(mHalfWidth + 1.0f));// +1 since final surface is dilated by dx
280 mMaxVoxelSize = maxLength / 2.0f;
281 // A too-small dim relative to halfWidth drives the denominator above to zero
282 // or negative, yielding a non-finite or non-positive voxel size.
283 if (!math::isFinite(mMinVoxelSize) || !(mMinVoxelSize > 0.0f) ||
284 !math::isFinite(mMaxVoxelSize) || !(mMaxVoxelSize > 0.0f)) {
285 OPENVDB_THROW(ArithmeticError, "polySoupToLevelSet: computed voxel size is not "
286 "finite and positive (is dim too small for the given halfWidth?)");
287 }
288 OPENVDB_ASSERT(2*mMinVoxelSize <= mMaxVoxelSize);
289}// tools::PolySoupToLevelSet::PolySoupToLevelSet()
290
291/////////////////////////////////////////////////////////////////////////////////////
292
293template<typename GridType>
295 : mPoly(poly), mMinVoxelSize(voxelSize), mHalfWidth(width)
296{
297 if constexpr(!std::is_floating_point<typename GridType::ValueType>::value) {
298 OPENVDB_THROW(TypeError, "polySoupToLevelSet: supported only for scalar floating-point grids");
299 }
300 if (!(mHalfWidth > 0.0f)) {
301 OPENVDB_THROW(ValueError, "polySoupToLevelSet: halfWidth must be positive");
302 }
303 if (!math::isFinite(mMinVoxelSize) || !(mMinVoxelSize > 0.0f)) {
304 OPENVDB_THROW(ValueError, "polySoupToLevelSet: voxelSize must be finite and positive");
305 }
306 if (!mPoly.bbox) mPoly.bbox = PolySoupToLevelSet::getBBox(mPoly.vtx);
307 // See note in the dim-based constructor: the largest extent must be positive
308 // (rejects empty/degenerate geometry) but a flat/planar mesh is allowed.
309 const float maxLength = mPoly.bbox.extents()[mPoly.bbox.maxExtent()];
310 if (!(maxLength > 0.0f)) {
311 OPENVDB_THROW(ValueError, "polySoupToLevelSet: bounding box has non-positive extent (no input geometry?)");
312 }
313 mMaxVoxelSize = maxLength / 2.0f;
314 if (!math::isFinite(mMaxVoxelSize) || !(mMaxVoxelSize > 0.0f)) {
315 OPENVDB_THROW(ArithmeticError, "polySoupToLevelSet: computed voxel size is not finite and positive");
316 }
317 OPENVDB_ASSERT(2*mMinVoxelSize <= mMaxVoxelSize);
318}// tools::PolySoupToLevelSet::PolySoupToLevelSet()
319
320/////////////////////////////////////////////////////////////////////////////////////
321
322template<typename GridType>
323template<class ShrinkWrapT, class ProgressT>
324void PolySoupToLevelSet<GridType>::process(const ShrinkWrapT &D, ProgressT *progress, int offset_mode)
325{
326 auto myProgress = [&](const std::string &s){if constexpr(!std::is_same<ProgressT,void>::value) if (progress) (*progress)(s);};
327
328 // Fine to coarse offset generation
329 for (float dx = mMinVoxelSize; dx <= mMaxVoxelSize; dx *= 2.0f) {
330 myProgress("Offset: dx=" + std::to_string(dx)+", range: "+std::to_string(mMinVoxelSize)+" -> "+std::to_string(mMaxVoxelSize));
331 mGrids.push_back(this->offset(dx, offset_mode));
332 }
333
334 // Coarse to fine shrink wrap algorithm
335 double vol[2] = {0.0, 0.0};// levelSetVolume returns Real (double); keep full precision.
336 // Zero-init silences a GCC -Wmaybe-uninitialized false positive:
337 // vol[0] is only read when d>0, after the loop's increment has set it.
338 auto grid = mGrids.back();// initiate grid with the coarsest offset
339 mGrids.pop_back();
340 mIsGridSDF = true;
341 for (auto iter = mGrids.rbegin(), end = mGrids.rend(); iter != end; ++iter) {// coarse -> fine
342 grid = this->upsample(*grid);// grid(dx) -> grid(dx/2)
343 for (float d = 0.0f, dx = float(grid->voxelSize()[0]), Ddx = D(dx); d < Ddx; vol[0] = vol[1]) {
344 myProgress("Shrink wrap d=" + std::to_string(d) + ", D("+std::to_string(dx) + ")=" + std::to_string(Ddx));
345 grid = this->shrinkWrap(*grid, **iter, d);
346 vol[1] = levelSetVolume(*grid);
347 if (d>0.0f && math::isApproxZero(vol[0]-vol[1])) break;
348 }
349 *iter = grid;
350 }// loop from coarse to fine voxel sizes
351
352}// tools::PolySoupToLevelSet::process()
353
354//////////////////////////////////////////////////////////////////////////
355
356template<typename GridType>
358{
359 using RangeT = tbb::blocked_range<std::vector<Vec3s>::const_iterator>;
360 RangeT range(vtx.begin(), vtx.end(), 1024);
361 struct BBoxOp {
363 BBoxOp() : bbox() {}
364 BBoxOp(BBoxOp& s, tbb::split) : bbox(s.bbox) {}
365 void operator()(const RangeT& r) {for (auto p=r.begin(); p!=r.end(); ++p) bbox.expand(*p);}
366 void join(BBoxOp& rhs) {bbox.expand(rhs.bbox);}
367 } tmp;
368#if 0
369 tmp(range);// serial
370#else
371 tbb::parallel_reduce(range, tmp);// parallel
372#endif
373 return tmp.bbox;
374}// tools::PolySoupToLevelSet::getBBox
375
376//////////////////////////////////////////////////////////////////////////
377
378template<typename GridType>
380{
382 typename GridType::Ptr grid(nullptr);
383 switch (mode) {
384 case 0:// algorithm presented in the paper, using mesh<-> VDB round-trip
385 grid = meshToUnsignedDistanceField<GridType>(*xform, mPoly.vtx, mPoly.tri, mPoly.quad, mHalfWidth);// mesh -> UDF
386 volumeToMesh(*grid, mPoly.vtx, mPoly.tri, mPoly.quad, /*iso*/dx, /*adapt*/0.0);// UDF -> mesh (clears and re-allocates mesh)
387 grid = meshToLevelSet<GridType>(*xform, mPoly.vtx, mPoly.tri, mPoly.quad, mHalfWidth);// mesh -> SDF
388 break;
389 case 1:// algorithm using Mihai's signed flood-fill algorithm
390 grid = meshToUnsignedDistanceField<GridType>(*xform, mPoly.vtx, mPoly.tri, mPoly.quad, mHalfWidth + 1);// mesh -> UDF
391 tools::foreach(grid->beginValueOn(), [dx](const typename GridType::ValueOnIter& it){it.setValue(*it - dx);}, /*threaded*/true, /*share functor*/true);
392 //tools::changeBackground(grid->tree(), mHalfWidth*dx);
393 tools::changeLevelSetBackground(grid->tree(), mHalfWidth);
394 //grid->tree().root().setBackground(exteriorWidth, /*updateChildNodes=*/true);
395 //tools::signedFloodFillWithValues(grid->tree(), exteriorWidth, interiorWidth);
396 tools::distanceFieldToSDF(*grid, /*removeDisconnectedInterior*/true, /*rebuildNarrowBand*/true);
397 break;
398 case 2:// algorithm using Greg's polyOffset algorithm
399 grid = tools::createLevelSetDilatedMesh<GridType, float>(mPoly.vtx, mPoly.tri, mPoly.quad, /*radius*/dx, /*voxel size*/dx, mHalfWidth);
400 //tools::distanceFieldToSDF(*grid, /*removeDisconnectedInterior*/true, /*rebuildNarrowBand*/false);
401 break;
402 default:
403 OPENVDB_THROW(TypeError, "polySoupToLevelSet::offset: invalid mode(" + std::to_string(mode) + ")");
404 break;
405 }// end of switch
406 return grid;
407}// tools::PolySoupToLevelSet<GridType>::offset
408
409//////////////////////////////////////////////////////////////////////////
410
411template<typename GridType>
412auto PolySoupToLevelSet<GridType>::upsample(const GridType &inGrid)
413{
414 auto outGrid = createLevelSet<GridType>(inGrid.voxelSize()[0]/2, mHalfWidth);
415 resampleToMatch<BoxSampler>(inGrid, *outGrid);
416 mIsGridSDF = true;
417 return outGrid;
418}// tools::PolySoupToLevelSet<GridType>::upsample
419
420//////////////////////////////////////////////////////////////////////////
421
422template<typename GridType>
423auto PolySoupToLevelSet<GridType>::shrinkWrap(GridType &grid, const GridType &gridB, float &d)
424{
425 const float maxDist = 2.0f;
426 LevelSetFilter<GridType> filter(grid);
427 filter.setNormCount(3);// halfWidth
428#if 1//first-order
429 filter.setSpatialScheme(math::FIRST_BIAS);
430 filter.setTemporalScheme(math::TVD_RK1);
431#else// higher order
432 filter.setSpatialScheme(math::HJWENO5_BIAS);
433 filter.setTemporalScheme(math::TVD_RK3);
434#endif
435 if (mIsGridSDF == false) {
436 filter.normalize();
437 filter.prune();// is this needed?
438 }
439 filter.offset(static_cast<typename GridType::ValueType>(maxDist * grid.voxelSize()[0]));// erode by maxDist * dx
440 mIsGridSDF = false;// the CSG operation messed up the SDF
441 d += maxDist;
442 return csgUnionCopy(grid, gridB);
443}// tools::PolySoupToLevelSet<GridType>::shrinkWrap
444
445//////////////////////////////////////////////////////////////////////////
446
448 const float mErode, mThres;
449public:
450 ShrinkWrapLimit(float erode = 8.0f, float thres = 0.0f) : mErode(erode), mThres(thres) {}
451 float operator()(float dx) const {// if mThres == 0 this always returns mErode
452 return dx>=2*mThres ? mErode : dx<=mThres ? 1.0f : 1.0f + (mErode-1.0f)*(dx-mThres)/mThres;
453 }
454};// ShrinkWrapLimit
455
456/////////////////////////////////////////////////////////////////////////////////////
457
458template<typename GridType, class ShrinkWrapT, class ProgressT>
459typename GridType::Ptr
461 PolySoup &&poly,
462 int dim,
463 float voxelSize,
464 const ShrinkWrapT &D,
465 float halfWidth,
466 ProgressT *progress,
467 int offset_mode)
468{
469 static_assert(std::is_floating_point<typename GridType::ValueType>::value,
470 "polySoupToLevelSet requires an SDF grid with floating-point values");
472 auto ptr = voxelSize > 0.0f ? std::make_unique<T>(std::move(poly), voxelSize, halfWidth) :
473 std::make_unique<T>(std::move(poly), dim, halfWidth);
474 ptr->process(D, progress, offset_mode);
475 return ptr->grid();
476}
477
478/////////////////////////////////////////////////////////////////////////////////////
479
480template<typename GridType, class ShrinkWrapT, class ProgressT>
481std::vector<typename GridType::Ptr>
483 int dim,
484 const math::BBox<Vec3f> &bbox,
485 std::vector<Vec3s>& vtx,
486 std::vector<Vec3I>& tri,
487 std::vector<Vec4I>& quad,
488 const ShrinkWrapT &D,
489 float halfWidth,
490 ProgressT *progress,
491 int offset_mode)
492{
493 static_assert(std::is_floating_point<typename GridType::ValueType>::value,
494 "polySoupToLevelSet requires an SDF grid with floating-point values");
495 PolySoup poly{std::move(vtx), std::move(tri), std::move(quad), bbox};
496 PolySoupToLevelSet<GridType> tmp(std::move(poly), dim, halfWidth);
497 tmp.process(D, progress, offset_mode);
498 return tmp.grids();
499}
500
501/////////////////////////////////////////////////////////////////////////////////////
502
503template<typename GridType, class ShrinkWrapT, class ProgressT>
504std::vector<typename GridType::Ptr>
506 float minVoxelSize,
507 const math::BBox<Vec3f> &bbox,
508 std::vector<Vec3s>& vtx,
509 std::vector<Vec3I>& tri,
510 std::vector<Vec4I>& quad,
511 const ShrinkWrapT &D,
512 float halfWidth,
513 ProgressT *progress,
514 int offset_mode)
515{
516 static_assert(std::is_floating_point<typename GridType::ValueType>::value,
517 "polySoupToLevelSet requires an SDF grid with floating-point values");
518 PolySoup poly{std::move(vtx), std::move(tri), std::move(quad), bbox};
519 PolySoupToLevelSet<GridType> tmp(std::move(poly), minVoxelSize, halfWidth);
520 tmp.process(D, progress, offset_mode);
521 return tmp.grids();
522}// polySoupToLevelSet
523
524} // namespace tools
525} // namespace OPENVDB_VERSION_NAME
526} // namespace openvdb
527
528#endif // OPENVDB_TOOLS_POLYSOUP_TO_LEVELSET_HAS_BEEN_INCLUDED
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Functions to efficiently perform various compositing operations on grids.
Defined the six functions {fog,sdf}To{Sdf,Ext,SdfAndExt} in addition to the two functions maskSdf and...
Generate a narrow-band level set of a dilated surface mesh.
Performs various types of level set deformations with interface tracking. These unrestricted deformat...
Miscellaneous utility methods that operate primarily or exclusively on level set grids.
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Convert polygonal meshes that consist of quads and/or triangles into signed or unsigned distance fiel...
Extract polygonal surfaces from scalar volumes.
Definition Exceptions.h:56
Definition Exceptions.h:64
Definition Exceptions.h:65
Axis-aligned bounding box.
Definition BBox.h:24
void expand(ElementType padding)
Pad this bounding box.
Definition BBox.h:321
static Transform::Ptr createLinearTransform(double voxelSize=1.0)
Create and return a shared pointer to a new transform.
Class that implements the actual shrink wrap algorithm.
Definition PolySoupToLevelSet.h:170
float maxVoxelSize() const
Returns the coarsest/largest voxel size, in world units, used to initiate the coarse-to-fine shrink w...
Definition PolySoupToLevelSet.h:239
float minVoxelSize() const
Returns the finest/smallest voxel size, in world units, i.e. the voxel size of the final (highest-res...
Definition PolySoupToLevelSet.h:235
auto offset(float dx, int mode=0)
Generates a dx-offset level set surface from the internal polygon soup.
Definition PolySoupToLevelSet.h:379
GridType::Ptr grid(int n=0) const
Returns a shared pointer to a particular shrink wrap grid.
Definition PolySoupToLevelSet.h:203
std::vector< typename GridType::Ptr > grids() const
Vector with shared pointers to all the shrink wrap grids.
Definition PolySoupToLevelSet.h:207
const PolySoup & mesh(int n=0, float adaptivity=0.005f, float isoValue=0.0f)
Generate an adaptive polygon mesh from a particular shrink wrap SDF.
Definition PolySoupToLevelSet.h:216
float halfWidth() const
Returns the half-width of the output narrow-band level set, in voxel units.
Definition PolySoupToLevelSet.h:242
void process(const ShrinkWrapT &D, ProgressT *progress, int mode=0)
Performs the actual processing to generate the shrink wrap surfaces.
Definition PolySoupToLevelSet.h:324
static math::BBox< Vec3f > getBBox(const std::vector< Vec3s > &vtx)
Static method that computes the bounding box of a list of vertex coordinates.
Definition PolySoupToLevelSet.h:357
PolySoupToLevelSet(PolySoup &&poly, int dim, float width=float(LEVEL_SET_HALF_WIDTH))
Constructor from a desired voxel dimension.
Definition PolySoupToLevelSet.h:261
size_t gridCount() const
Number of shrink wrap grids generated, i.e. depth of the LOD hierarchy.
Definition PolySoupToLevelSet.h:198
Definition PolySoupToLevelSet.h:447
ShrinkWrapLimit(float erode=8.0f, float thres=0.0f)
Definition PolySoupToLevelSet.h:450
float operator()(float dx) const
Definition PolySoupToLevelSet.h:451
@ TVD_RK1
Definition FiniteDifference.h:235
@ TVD_RK3
Definition FiniteDifference.h:237
bool isApproxZero(const Type &x, const Type &tolerance)
Return true if x is equal to zero to within the given tolerance.
Definition Math.h:360
bool isFinite(const float x)
Return true if x is finite.
Definition Math.h:385
@ FIRST_BIAS
Definition FiniteDifference.h:166
@ HJWENO5_BIAS
Definition FiniteDifference.h:170
void volumeToMesh(const GridType &grid, std::vector< Vec3s > &points, std::vector< Vec4I > &quads, double isovalue=0.0)
Uniformly mesh any scalar grid that has a continuous isosurface.
Definition VolumeToMesh.h:5200
GridType::Ptr polySoupToLevelSet(PolySoup &&poly, int dim=256, float voxelSize=0.0, const ShrinkWrapT &D=ShrinkWrapT(), float halfWidth=float(LEVEL_SET_HALF_WIDTH), ProgressT *progress=nullptr, int offset_mode=0)
Convert a soup of polygons to a shrink wrapped level set volume. This version takes a PolySoup struct...
Definition PolySoupToLevelSet.h:460
GridType::Ptr meshToLevelSet(const openvdb::math::Transform &xform, const std::vector< Vec3s > &points, const std::vector< Vec3I > &triangles, float halfWidth=float(LEVEL_SET_HALF_WIDTH))
Convert a triangle mesh to a level set volume.
Definition MeshToVolume.h:3763
void distanceFieldToSDF(GridType &grid, bool removeDisconnectedInterior=false, bool rebuildNarrowBand=true, float halfWidth=3.0f)
Convert a distance field (unsigned or signed) into a proper signed distance field / level set.
Definition LevelSetUtil.h:2635
GridType::Ptr meshToUnsignedDistanceField(const openvdb::math::Transform &xform, const std::vector< Vec3s > &points, const std::vector< Vec3I > &triangles, const std::vector< Vec4I > &quads, float bandWidth)
Convert a triangle and quad mesh to an unsigned distance field.
Definition MeshToVolume.h:3881
GridOrTreeT::Ptr csgUnionCopy(const GridOrTreeT &a, const GridOrTreeT &b)
Threaded CSG union operation that produces a new grid or tree from immutable inputs.
Definition Composite.h:935
Real levelSetVolume(const GridType &grid, bool useWorldSpace=true)
Return the volume of a narrow-band level set surface.
GridType::Ptr createLevelSetDilatedMesh(const std::vector< math::Vec3< ScalarType > > &vertices, const std::vector< Vec3I > &triangles, ScalarType radius, float voxelSize, float halfWidth=float(LEVEL_SET_HALF_WIDTH), InterruptT *interrupter=nullptr)
Return a grid of type GridType containing a narrow-band level set representation of a dilated triangl...
void foreach(const IterT &iter, XformOp &op, bool threaded=true, bool shareOp=true)
Iterate over a grid and at each step call op(iter).
Definition ValueTransformer.h:386
void resampleToMatch(const GridType &inGrid, GridType &outGrid, Interrupter &interrupter)
Resample an input grid into an output grid of the same type such that, after resampling,...
Definition GridTransformer.h:486
void changeLevelSetBackground(TreeOrLeafManagerT &tree, const typename TreeOrLeafManagerT::ValueType &halfWidth, bool threaded=true, size_t grainSize=32)
Replace the background value in all the nodes of a floating-point tree containing a symmetric narrow-...
Definition ChangeBackground.h:234
static const Real LEVEL_SET_HALF_WIDTH
Definition Types.h:532
GridType::Ptr createLevelSet(Real voxelSize=1.0, Real halfWidth=LEVEL_SET_HALF_WIDTH)
Create a new grid of type GridType classified as a "Level Set", i.e., a narrow-band level set.
Definition Grid.h:1774
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
Simple structure for a polygon soup.
Definition PolySoupToLevelSet.h:42
std::vector< Vec4I > quad
Definition PolySoupToLevelSet.h:45
std::vector< Vec3s > vtx
Definition PolySoupToLevelSet.h:43
math::BBox< Vec3f > bbox
Definition PolySoupToLevelSet.h:46
std::vector< Vec3I > tri
Definition PolySoupToLevelSet.h:44
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:284