HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LevelSetRebuild.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2012-2018 DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
29 ///////////////////////////////////////////////////////////////////////////
30 
31 #ifndef OPENVDB_TOOLS_LEVELSETREBUILD_HAS_BEEN_INCLUDED
32 #define OPENVDB_TOOLS_LEVELSETREBUILD_HAS_BEEN_INCLUDED
33 
34 #include <openvdb/Grid.h>
35 #include <openvdb/Exceptions.h>
36 #include <openvdb/math/Math.h>
37 #include <openvdb/math/Transform.h>
41 #include <openvdb/util/Util.h>
42 #include <tbb/blocked_range.h>
43 #include <tbb/parallel_for.h>
44 #include <type_traits>
45 
46 
47 namespace openvdb {
49 namespace OPENVDB_VERSION_NAME {
50 namespace tools {
51 
52 
53 /// @brief Return a new grid of type @c GridType that contains a narrow-band level set
54 /// representation of an isosurface of a given grid.
55 ///
56 /// @param grid a scalar, floating-point grid with one or more disjoint,
57 /// closed isosurfaces at the given @a isovalue
58 /// @param isovalue the isovalue that defines the implicit surface (defaults to zero,
59 /// which is typical if the input grid is already a level set or a SDF).
60 /// @param halfWidth half the width of the narrow band, in voxel units
61 /// (defaults to 3 voxels, which is required for some level set operations)
62 /// @param xform optional transform for the output grid
63 /// (if not provided, the transform of the input @a grid will be matched)
64 ///
65 /// @throw TypeError if @a grid is not scalar or not floating-point
66 ///
67 /// @note If the input grid contains overlapping isosurfaces, interior edges will be lost.
68 template<class GridType>
69 inline typename GridType::Ptr
70 levelSetRebuild(const GridType& grid, float isovalue = 0,
71  float halfWidth = float(LEVEL_SET_HALF_WIDTH), const math::Transform* xform = nullptr);
72 
73 
74 /// @brief Return a new grid of type @c GridType that contains a narrow-band level set
75 /// representation of an isosurface of a given grid.
76 ///
77 /// @param grid a scalar, floating-point grid with one or more disjoint,
78 /// closed isosurfaces at the given @a isovalue
79 /// @param isovalue the isovalue that defines the implicit surface
80 /// @param exBandWidth the exterior narrow-band width in voxel units
81 /// @param inBandWidth the interior narrow-band width in voxel units
82 /// @param xform optional transform for the output grid
83 /// (if not provided, the transform of the input @a grid will be matched)
84 ///
85 /// @throw TypeError if @a grid is not scalar or not floating-point
86 ///
87 /// @note If the input grid contains overlapping isosurfaces, interior edges will be lost.
88 template<class GridType>
89 inline typename GridType::Ptr
90 levelSetRebuild(const GridType& grid, float isovalue, float exBandWidth, float inBandWidth,
91  const math::Transform* xform = nullptr);
92 
93 
94 /// @brief Return a new grid of type @c GridType that contains a narrow-band level set
95 /// representation of an isosurface of a given grid.
96 ///
97 /// @param grid a scalar, floating-point grid with one or more disjoint,
98 /// closed isosurfaces at the given @a isovalue
99 /// @param isovalue the isovalue that defines the implicit surface
100 /// @param exBandWidth the exterior narrow-band width in voxel units
101 /// @param inBandWidth the interior narrow-band width in voxel units
102 /// @param xform optional transform for the output grid
103 /// (if not provided, the transform of the input @a grid will be matched)
104 /// @param interrupter optional interrupter object
105 ///
106 /// @throw TypeError if @a grid is not scalar or not floating-point
107 ///
108 /// @note If the input grid contains overlapping isosurfaces, interior edges will be lost.
109 template<class GridType, typename InterruptT>
110 inline typename GridType::Ptr
111 levelSetRebuild(const GridType& grid, float isovalue, float exBandWidth, float inBandWidth,
112  const math::Transform* xform = nullptr, InterruptT* interrupter = nullptr);
113 
114 
115 ////////////////////////////////////////
116 
117 
118 // Internal utility objects and implementation details
119 
120 namespace internal {
121 
123 {
124 public:
125  PointListTransform(const PointList& pointsIn, std::vector<Vec3s>& pointsOut,
126  const math::Transform& xform)
127  : mPointsIn(pointsIn)
128  , mPointsOut(&pointsOut)
129  , mXform(xform)
130  {
131  }
132 
133  void runParallel()
134  {
135  tbb::parallel_for(tbb::blocked_range<size_t>(0, mPointsOut->size()), *this);
136  }
137 
138  void runSerial()
139  {
140  (*this)(tbb::blocked_range<size_t>(0, mPointsOut->size()));
141  }
142 
143  inline void operator()(const tbb::blocked_range<size_t>& range) const
144  {
145  for (size_t n = range.begin(); n < range.end(); ++n) {
146  (*mPointsOut)[n] = Vec3s(mXform.worldToIndex(mPointsIn[n]));
147  }
148  }
149 
150 private:
151  const PointList& mPointsIn;
152  std::vector<Vec3s> * const mPointsOut;
153  const math::Transform& mXform;
154 };
155 
156 
157 class PrimCpy
158 {
159 public:
160  PrimCpy(const PolygonPoolList& primsIn, const std::vector<size_t>& indexList,
161  std::vector<Vec4I>& primsOut)
162  : mPrimsIn(primsIn)
163  , mIndexList(indexList)
164  , mPrimsOut(&primsOut)
165  {
166  }
167 
168  void runParallel()
169  {
170  tbb::parallel_for(tbb::blocked_range<size_t>(0, mIndexList.size()), *this);
171  }
172 
173  void runSerial()
174  {
175  (*this)(tbb::blocked_range<size_t>(0, mIndexList.size()));
176  }
177 
178  inline void operator()(const tbb::blocked_range<size_t>& range) const
179  {
180  openvdb::Vec4I quad;
181  quad[3] = openvdb::util::INVALID_IDX;
182  std::vector<Vec4I>& primsOut = *mPrimsOut;
183 
184  for (size_t n = range.begin(); n < range.end(); ++n) {
185  size_t index = mIndexList[n];
186  PolygonPool& polygons = mPrimsIn[n];
187 
188  // Copy quads
189  for (size_t i = 0, I = polygons.numQuads(); i < I; ++i) {
190  primsOut[index++] = polygons.quad(i);
191  }
192  polygons.clearQuads();
193 
194  // Copy triangles (adaptive mesh)
195  for (size_t i = 0, I = polygons.numTriangles(); i < I; ++i) {
196  const openvdb::Vec3I& triangle = polygons.triangle(i);
197  quad[0] = triangle[0];
198  quad[1] = triangle[1];
199  quad[2] = triangle[2];
200  primsOut[index++] = quad;
201  }
202 
203  polygons.clearTriangles();
204  }
205  }
206 
207 private:
208  const PolygonPoolList& mPrimsIn;
209  const std::vector<size_t>& mIndexList;
210  std::vector<Vec4I> * const mPrimsOut;
211 };
212 
213 } // namespace internal
214 
215 
216 ////////////////////////////////////////
217 
218 
219 //{
220 /// @cond OPENVDB_LEVEL_SET_REBUILD_INTERNAL
221 
222 /// The normal entry points for level set rebuild are the levelSetRebuild() functions.
223 /// doLevelSetRebuild() is mainly for internal use, but when the isovalue and half band
224 /// widths are given in ValueType units (for example, if they are queried from
225 /// a grid), it might be more convenient to call this function directly.
226 ///
227 /// @internal This overload is enabled only for grids with a scalar, floating-point ValueType.
228 template<class GridType, typename InterruptT>
229 inline typename std::enable_if<
231 doLevelSetRebuild(const GridType& grid, typename GridType::ValueType iso,
232  typename GridType::ValueType exWidth, typename GridType::ValueType inWidth,
233  const math::Transform* xform, InterruptT* interrupter)
234 {
235  const float
236  isovalue = float(iso),
237  exBandWidth = float(exWidth),
238  inBandWidth = float(inWidth);
239 
240  tools::VolumeToMesh mesher(isovalue);
241  mesher(grid);
242 
243  math::Transform::Ptr transform = (xform != nullptr) ? xform->copy() : grid.transform().copy();
244 
245  std::vector<Vec3s> points(mesher.pointListSize());
246 
247  { // Copy and transform (required for MeshToVolume) points to grid space.
248  internal::PointListTransform ptnXForm(mesher.pointList(), points, *transform);
249  ptnXForm.runParallel();
250  mesher.pointList().reset(nullptr);
251  }
252 
253  std::vector<Vec4I> primitives;
254 
255  { // Copy primitives.
256  PolygonPoolList& polygonPoolList = mesher.polygonPoolList();
257 
258  size_t numPrimitives = 0;
259  std::vector<size_t> indexlist(mesher.polygonPoolListSize());
260 
261  for (size_t n = 0, N = mesher.polygonPoolListSize(); n < N; ++n) {
262  const openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
263  indexlist[n] = numPrimitives;
264  numPrimitives += polygons.numQuads();
265  numPrimitives += polygons.numTriangles();
266  }
267 
268  primitives.resize(numPrimitives);
269  internal::PrimCpy primCpy(polygonPoolList, indexlist, primitives);
270  primCpy.runParallel();
271  }
272 
273  QuadAndTriangleDataAdapter<Vec3s, Vec4I> mesh(points, primitives);
274 
275  if (interrupter) {
276  return meshToVolume<GridType>(*interrupter, mesh, *transform, exBandWidth, inBandWidth,
277  DISABLE_RENORMALIZATION, nullptr);
278  }
279 
280  return meshToVolume<GridType>(mesh, *transform, exBandWidth, inBandWidth,
281  DISABLE_RENORMALIZATION, nullptr);
282 }
283 
284 
285 /// @internal This overload is enabled only for grids that do not have a scalar,
286 /// floating-point ValueType.
287 template<class GridType, typename InterruptT>
288 inline typename std::enable_if<
290 doLevelSetRebuild(const GridType&, typename GridType::ValueType /*isovalue*/,
291  typename GridType::ValueType /*exWidth*/, typename GridType::ValueType /*inWidth*/,
292  const math::Transform*, InterruptT*)
293 {
294  OPENVDB_THROW(TypeError,
295  "level set rebuild is supported only for scalar, floating-point grids");
296 }
297 
298 /// @endcond
299 //}
300 
301 
302 ////////////////////////////////////////
303 
304 
305 template<class GridType, typename InterruptT>
306 inline typename GridType::Ptr
307 levelSetRebuild(const GridType& grid, float iso, float exWidth, float inWidth,
308  const math::Transform* xform, InterruptT* interrupter)
309 {
310  using ValueT = typename GridType::ValueType;
311  ValueT
312  isovalue(zeroVal<ValueT>() + ValueT(iso)),
313  exBandWidth(zeroVal<ValueT>() + ValueT(exWidth)),
314  inBandWidth(zeroVal<ValueT>() + ValueT(inWidth));
315 
316  return doLevelSetRebuild(grid, isovalue, exBandWidth, inBandWidth, xform, interrupter);
317 }
318 
319 
320 template<class GridType>
321 inline typename GridType::Ptr
322 levelSetRebuild(const GridType& grid, float iso, float exWidth, float inWidth,
323  const math::Transform* xform)
324 {
325  using ValueT = typename GridType::ValueType;
326  ValueT
327  isovalue(zeroVal<ValueT>() + ValueT(iso)),
328  exBandWidth(zeroVal<ValueT>() + ValueT(exWidth)),
329  inBandWidth(zeroVal<ValueT>() + ValueT(inWidth));
330 
331  return doLevelSetRebuild<GridType, util::NullInterrupter>(
332  grid, isovalue, exBandWidth, inBandWidth, xform, nullptr);
333 }
334 
335 
336 template<class GridType>
337 inline typename GridType::Ptr
338 levelSetRebuild(const GridType& grid, float iso, float halfVal, const math::Transform* xform)
339 {
340  using ValueT = typename GridType::ValueType;
341  ValueT
342  isovalue(zeroVal<ValueT>() + ValueT(iso)),
343  halfWidth(zeroVal<ValueT>() + ValueT(halfVal));
344 
345  return doLevelSetRebuild<GridType, util::NullInterrupter>(
346  grid, isovalue, halfWidth, halfWidth, xform, nullptr);
347 }
348 
349 
350 } // namespace tools
351 } // namespace OPENVDB_VERSION_NAME
352 } // namespace openvdb
353 
354 #endif // OPENVDB_TOOLS_LEVELSETREBUILD_HAS_BEEN_INCLUDED
355 
356 // Copyright (c) 2012-2018 DreamWorks Animation LLC
357 // All rights reserved. This software is distributed under the
358 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
PrimCpy(const PolygonPoolList &primsIn, const std::vector< size_t > &indexList, std::vector< Vec4I > &primsOut)
GLenum GLint * range
Definition: glcorearb.h:1924
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:189
void operator()(const tbb::blocked_range< size_t > &range) const
void operator()(const tbb::blocked_range< size_t > &range) const
png_uint_32 i
Definition: png.h:2877
GLdouble n
Definition: glcorearb.h:2007
math::Vec4< Index32 > Vec4I
Definition: Types.h:95
Extract polygonal surfaces from scalar volumes.
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
hboost::scoped_array< PolygonPool > PolygonPoolList
Point and primitive list types.
Definition: VolumeToMesh.h:180
OPENVDB_API const Index32 INVALID_IDX
Mesh any scalar grid that has a continuous isosurface.
Definition: VolumeToMesh.h:188
GA_API const UT_StringHolder transform
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...
GLsizei const GLfloat * value
Definition: glcorearb.h:823
GLuint index
Definition: glcorearb.h:785
math::Vec3< Index32 > Vec3I
Definition: Types.h:80
GA_API const UT_StringHolder N
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:107
hboost::scoped_array< openvdb::Vec3s > PointList
Point and primitive list types.
Definition: VolumeToMesh.h:179
Vec3d worldToIndex(const Vec3d &xyz) const
Apply this transformation to the given coordinates.
Definition: Transform.h:137
Convert polygonal meshes that consist of quads and/or triangles into signed or unsigned distance fiel...
PointListTransform(const PointList &pointsIn, std::vector< Vec3s > &pointsOut, const math::Transform &xform)
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:135
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
Collection of quads and triangles.
Definition: VolumeToMesh.h:121