HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LevelSetRebuild.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
4 #ifndef OPENVDB_TOOLS_LEVELSETREBUILD_HAS_BEEN_INCLUDED
5 #define OPENVDB_TOOLS_LEVELSETREBUILD_HAS_BEEN_INCLUDED
6 
7 #include <openvdb/Grid.h>
8 #include <openvdb/Exceptions.h>
9 #include <openvdb/math/Math.h>
10 #include <openvdb/math/Transform.h>
14 #include <openvdb/util/Util.h>
15 #include <tbb/blocked_range.h>
16 #include <tbb/parallel_for.h>
17 #include <type_traits>
18 
19 
20 namespace openvdb {
22 namespace OPENVDB_VERSION_NAME {
23 namespace tools {
24 
25 
26 /// @brief Return a new grid of type @c GridType that contains a narrow-band level set
27 /// representation of an isosurface of a given grid.
28 ///
29 /// @param grid a scalar, floating-point grid with one or more disjoint,
30 /// closed isosurfaces at the given @a isovalue
31 /// @param isovalue the isovalue that defines the implicit surface (defaults to zero,
32 /// which is typical if the input grid is already a level set or a SDF).
33 /// @param halfWidth half the width of the narrow band, in voxel units
34 /// (defaults to 3 voxels, which is required for some level set operations)
35 /// @param xform optional transform for the output grid
36 /// (if not provided, the transform of the input @a grid will be matched)
37 ///
38 /// @throw TypeError if @a grid is not scalar or not floating-point
39 ///
40 /// @note If the input grid contains overlapping isosurfaces, interior edges will be lost.
41 template<class GridType>
42 inline typename GridType::Ptr
43 levelSetRebuild(const GridType& grid, float isovalue = 0,
44  float halfWidth = float(LEVEL_SET_HALF_WIDTH), const math::Transform* xform = nullptr);
45 
46 
47 /// @brief Return a new grid of type @c GridType that contains a narrow-band level set
48 /// representation of an isosurface of a given grid.
49 ///
50 /// @param grid a scalar, floating-point grid with one or more disjoint,
51 /// closed isosurfaces at the given @a isovalue
52 /// @param isovalue the isovalue that defines the implicit surface
53 /// @param exBandWidth the exterior narrow-band width in voxel units
54 /// @param inBandWidth the interior narrow-band width in voxel units
55 /// @param xform optional transform for the output grid
56 /// (if not provided, the transform of the input @a grid will be matched)
57 ///
58 /// @throw TypeError if @a grid is not scalar or not floating-point
59 ///
60 /// @note If the input grid contains overlapping isosurfaces, interior edges will be lost.
61 template<class GridType>
62 inline typename GridType::Ptr
63 levelSetRebuild(const GridType& grid, float isovalue, float exBandWidth, float inBandWidth,
64  const math::Transform* xform = nullptr);
65 
66 
67 /// @brief Return a new grid of type @c GridType that contains a narrow-band level set
68 /// representation of an isosurface of a given grid.
69 ///
70 /// @param grid a scalar, floating-point grid with one or more disjoint,
71 /// closed isosurfaces at the given @a isovalue
72 /// @param isovalue the isovalue that defines the implicit surface
73 /// @param exBandWidth the exterior narrow-band width in voxel units
74 /// @param inBandWidth the interior narrow-band width in voxel units
75 /// @param xform optional transform for the output grid
76 /// (if not provided, the transform of the input @a grid will be matched)
77 /// @param interrupter optional interrupter object
78 ///
79 /// @throw TypeError if @a grid is not scalar or not floating-point
80 ///
81 /// @note If the input grid contains overlapping isosurfaces, interior edges will be lost.
82 template<class GridType, typename InterruptT>
83 inline typename GridType::Ptr
84 levelSetRebuild(const GridType& grid, float isovalue, float exBandWidth, float inBandWidth,
85  const math::Transform* xform = nullptr, InterruptT* interrupter = nullptr);
86 
87 
88 ////////////////////////////////////////
89 
90 /// @cond OPENVDB_DOCS_INTERNAL
91 
92 // Internal utility objects and implementation details
93 
94 namespace internal {
95 
96 class PointListTransform
97 {
98 public:
99  PointListTransform(const PointList& pointsIn, std::vector<Vec3s>& pointsOut,
100  const math::Transform& xform)
101  : mPointsIn(pointsIn)
102  , mPointsOut(&pointsOut)
103  , mXform(xform)
104  {
105  }
106 
107  void runParallel()
108  {
109  tbb::parallel_for(tbb::blocked_range<size_t>(0, mPointsOut->size()), *this);
110  }
111 
112  void runSerial()
113  {
114  (*this)(tbb::blocked_range<size_t>(0, mPointsOut->size()));
115  }
116 
117  inline void operator()(const tbb::blocked_range<size_t>& range) const
118  {
119  for (size_t n = range.begin(); n < range.end(); ++n) {
120  (*mPointsOut)[n] = Vec3s(mXform.worldToIndex(mPointsIn[n]));
121  }
122  }
123 
124 private:
125  const PointList& mPointsIn;
126  std::vector<Vec3s> * const mPointsOut;
127  const math::Transform& mXform;
128 };
129 
130 
131 class PrimCpy
132 {
133 public:
134  PrimCpy(const PolygonPoolList& primsIn, const std::vector<size_t>& indexList,
135  std::vector<Vec4I>& primsOut)
136  : mPrimsIn(primsIn)
137  , mIndexList(indexList)
138  , mPrimsOut(&primsOut)
139  {
140  }
141 
142  void runParallel()
143  {
144  tbb::parallel_for(tbb::blocked_range<size_t>(0, mIndexList.size()), *this);
145  }
146 
147  void runSerial()
148  {
149  (*this)(tbb::blocked_range<size_t>(0, mIndexList.size()));
150  }
151 
152  inline void operator()(const tbb::blocked_range<size_t>& range) const
153  {
154  openvdb::Vec4I quad;
155  quad[3] = openvdb::util::INVALID_IDX;
156  std::vector<Vec4I>& primsOut = *mPrimsOut;
157 
158  for (size_t n = range.begin(); n < range.end(); ++n) {
159  size_t index = mIndexList[n];
160  PolygonPool& polygons = mPrimsIn[n];
161 
162  // Copy quads
163  for (size_t i = 0, I = polygons.numQuads(); i < I; ++i) {
164  primsOut[index++] = polygons.quad(i);
165  }
166  polygons.clearQuads();
167 
168  // Copy triangles (adaptive mesh)
169  for (size_t i = 0, I = polygons.numTriangles(); i < I; ++i) {
170  const openvdb::Vec3I& triangle = polygons.triangle(i);
171  quad[0] = triangle[0];
172  quad[1] = triangle[1];
173  quad[2] = triangle[2];
174  primsOut[index++] = quad;
175  }
176 
177  polygons.clearTriangles();
178  }
179  }
180 
181 private:
182  const PolygonPoolList& mPrimsIn;
183  const std::vector<size_t>& mIndexList;
184  std::vector<Vec4I> * const mPrimsOut;
185 };
186 
187 } // namespace internal
188 
189 /// @endcond
190 
191 ////////////////////////////////////////
192 
193 
194 //{
195 /// @cond OPENVDB_DOCS_INTERNAL
196 
197 /// The normal entry points for level set rebuild are the levelSetRebuild() functions.
198 /// doLevelSetRebuild() is mainly for internal use, but when the isovalue and half band
199 /// widths are given in ValueType units (for example, if they are queried from
200 /// a grid), it might be more convenient to call this function directly.
201 ///
202 /// @internal This overload is enabled only for grids with a scalar, floating-point ValueType.
203 template<class GridType, typename InterruptT>
204 inline typename std::enable_if<
206 doLevelSetRebuild(const GridType& grid, typename GridType::ValueType iso,
207  typename GridType::ValueType exWidth, typename GridType::ValueType inWidth,
208  const math::Transform* xform, InterruptT* interrupter)
209 {
210  const float
211  isovalue = float(iso),
212  exBandWidth = float(exWidth),
213  inBandWidth = float(inWidth);
214 
215  tools::VolumeToMesh mesher(isovalue);
216  mesher(grid);
217 
218  math::Transform::Ptr transform = (xform != nullptr) ? xform->copy() : grid.transform().copy();
219 
220  std::vector<Vec3s> points(mesher.pointListSize());
221 
222  { // Copy and transform (required for MeshToVolume) points to grid space.
223  internal::PointListTransform ptnXForm(mesher.pointList(), points, *transform);
224  ptnXForm.runParallel();
225  mesher.pointList().reset(nullptr);
226  }
227 
228  std::vector<Vec4I> primitives;
229 
230  { // Copy primitives.
231  PolygonPoolList& polygonPoolList = mesher.polygonPoolList();
232 
233  size_t numPrimitives = 0;
234  std::vector<size_t> indexlist(mesher.polygonPoolListSize());
235 
236  for (size_t n = 0, N = mesher.polygonPoolListSize(); n < N; ++n) {
237  const openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
238  indexlist[n] = numPrimitives;
239  numPrimitives += polygons.numQuads();
240  numPrimitives += polygons.numTriangles();
241  }
242 
243  primitives.resize(numPrimitives);
244  internal::PrimCpy primCpy(polygonPoolList, indexlist, primitives);
245  primCpy.runParallel();
246  }
247 
248  QuadAndTriangleDataAdapter<Vec3s, Vec4I> mesh(points, primitives);
249 
250  if (interrupter) {
251  return meshToVolume<GridType>(*interrupter, mesh, *transform, exBandWidth, inBandWidth,
252  DISABLE_RENORMALIZATION, nullptr);
253  }
254 
255  return meshToVolume<GridType>(mesh, *transform, exBandWidth, inBandWidth,
256  DISABLE_RENORMALIZATION, nullptr);
257 }
258 
259 
260 /// @internal This overload is enabled only for grids that do not have a scalar,
261 /// floating-point ValueType.
262 template<class GridType, typename InterruptT>
263 inline typename std::enable_if<
265 doLevelSetRebuild(const GridType&, typename GridType::ValueType /*isovalue*/,
266  typename GridType::ValueType /*exWidth*/, typename GridType::ValueType /*inWidth*/,
267  const math::Transform*, InterruptT*)
268 {
269  OPENVDB_THROW(TypeError,
270  "level set rebuild is supported only for scalar, floating-point grids");
271 }
272 
273 /// @endcond
274 //}
275 
276 
277 ////////////////////////////////////////
278 
279 
280 template<class GridType, typename InterruptT>
281 inline typename GridType::Ptr
282 levelSetRebuild(const GridType& grid, float iso, float exWidth, float inWidth,
283  const math::Transform* xform, InterruptT* interrupter)
284 {
285  using ValueT = typename GridType::ValueType;
286  ValueT
287  isovalue(zeroVal<ValueT>() + ValueT(iso)),
288  exBandWidth(zeroVal<ValueT>() + ValueT(exWidth)),
289  inBandWidth(zeroVal<ValueT>() + ValueT(inWidth));
290 
291  return doLevelSetRebuild(grid, isovalue, exBandWidth, inBandWidth, xform, interrupter);
292 }
293 
294 
295 template<class GridType>
296 inline typename GridType::Ptr
297 levelSetRebuild(const GridType& grid, float iso, float exWidth, float inWidth,
298  const math::Transform* xform)
299 {
300  using ValueT = typename GridType::ValueType;
301  ValueT
302  isovalue(zeroVal<ValueT>() + ValueT(iso)),
303  exBandWidth(zeroVal<ValueT>() + ValueT(exWidth)),
304  inBandWidth(zeroVal<ValueT>() + ValueT(inWidth));
305 
306  return doLevelSetRebuild<GridType, util::NullInterrupter>(
307  grid, isovalue, exBandWidth, inBandWidth, xform, nullptr);
308 }
309 
310 
311 template<class GridType>
312 inline typename GridType::Ptr
313 levelSetRebuild(const GridType& grid, float iso, float halfVal, const math::Transform* xform)
314 {
315  using ValueT = typename GridType::ValueType;
316  ValueT
317  isovalue(zeroVal<ValueT>() + ValueT(iso)),
318  halfWidth(zeroVal<ValueT>() + ValueT(halfVal));
319 
320  return doLevelSetRebuild<GridType, util::NullInterrupter>(
321  grid, isovalue, halfWidth, halfWidth, xform, nullptr);
322 }
323 
324 
325 } // namespace tools
326 } // namespace OPENVDB_VERSION_NAME
327 } // namespace openvdb
328 
329 #endif // OPENVDB_TOOLS_LEVELSETREBUILD_HAS_BEEN_INCLUDED
std::unique_ptr< openvdb::Vec3s[]> PointList
Point and primitive list types.
Definition: VolumeToMesh.h:150
void parallel_for(int64_t start, int64_t end, std::function< void(int64_t index)> &&task, parallel_options opt=parallel_options(0, Split_Y, 1))
Definition: parallel.h:127
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:178
std::unique_ptr< PolygonPool[]> PolygonPoolList
Point and primitive list types.
Definition: VolumeToMesh.h:151
GLuint GLenum GLenum transform
Definition: glew.h:15055
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:107
math::Vec4< Index32 > Vec4I
Definition: Types.h:84
Extract polygonal surfaces from scalar volumes.
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
OPENVDB_API const Index32 INVALID_IDX
GLuint GLdouble GLdouble GLint GLint const GLdouble * points
Definition: glew.h:3460
GLdouble n
Definition: glcorearb.h:2007
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...
GLuint index
Definition: glcorearb.h:785
math::Vec3< Index32 > Vec3I
Definition: Types.h:69
GA_API const UT_StringHolder N
GLsizei const GLfloat * value
Definition: glcorearb.h:823
GLenum GLint * range
Definition: glcorearb.h:1924
Convert polygonal meshes that consist of quads and/or triangles into signed or unsigned distance fiel...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:114
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74