HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LevelSetRebuild.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2012-2017 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 <hboost/type_traits/is_floating_point.hpp>
43 #include <hboost/utility/enable_if.hpp>
44 #include <tbb/blocked_range.h>
45 #include <tbb/parallel_for.h>
46 
47 
48 namespace openvdb {
50 namespace OPENVDB_VERSION_NAME {
51 namespace tools {
52 
53 
54 /// @brief Return a new grid of type @c GridType that contains a narrow-band level set
55 /// representation of an isosurface of a given grid.
56 ///
57 /// @param grid a scalar, floating-point grid with one or more disjoint,
58 /// closed isosurfaces at the given @a isovalue
59 /// @param isovalue the isovalue that defines the implicit surface (defaults to zero,
60 /// which is typical if the input grid is already a level set or a SDF).
61 /// @param halfWidth half the width of the narrow band, in voxel units
62 /// (defaults to 3 voxels, which is required for some level set operations)
63 /// @param xform optional transform for the output grid
64 /// (if not provided, the transform of the input @a grid will be matched)
65 ///
66 /// @throw TypeError if @a grid is not scalar or not floating-point
67 ///
68 /// @note If the input grid contains overlapping isosurfaces, interior edges will be lost.
69 template<class GridType>
70 inline typename GridType::Ptr
71 levelSetRebuild(const GridType& grid, float isovalue = 0,
72  float halfWidth = float(LEVEL_SET_HALF_WIDTH), const math::Transform* xform = NULL);
73 
74 
75 /// @brief Return a new grid of type @c GridType that contains a narrow-band level set
76 /// representation of an isosurface of a given grid.
77 ///
78 /// @param grid a scalar, floating-point grid with one or more disjoint,
79 /// closed isosurfaces at the given @a isovalue
80 /// @param isovalue the isovalue that defines the implicit surface
81 /// @param exBandWidth the exterior narrow-band width in voxel units
82 /// @param inBandWidth the interior narrow-band width in voxel units
83 /// @param xform optional transform for the output grid
84 /// (if not provided, the transform of the input @a grid will be matched)
85 ///
86 /// @throw TypeError if @a grid is not scalar or not floating-point
87 ///
88 /// @note If the input grid contains overlapping isosurfaces, interior edges will be lost.
89 template<class GridType>
90 inline typename GridType::Ptr
91 levelSetRebuild(const GridType& grid, float isovalue, float exBandWidth, float inBandWidth,
92  const math::Transform* xform = NULL);
93 
94 
95 /// @brief Return a new grid of type @c GridType that contains a narrow-band level set
96 /// representation of an isosurface of a given grid.
97 ///
98 /// @param grid a scalar, floating-point grid with one or more disjoint,
99 /// closed isosurfaces at the given @a isovalue
100 /// @param isovalue the isovalue that defines the implicit surface
101 /// @param exBandWidth the exterior narrow-band width in voxel units
102 /// @param inBandWidth the interior narrow-band width in voxel units
103 /// @param xform optional transform for the output grid
104 /// (if not provided, the transform of the input @a grid will be matched)
105 /// @param interrupter optional interrupter object
106 ///
107 /// @throw TypeError if @a grid is not scalar or not floating-point
108 ///
109 /// @note If the input grid contains overlapping isosurfaces, interior edges will be lost.
110 template<class GridType, typename InterruptT>
111 inline typename GridType::Ptr
112 levelSetRebuild(const GridType& grid, float isovalue, float exBandWidth, float inBandWidth,
113  const math::Transform* xform = NULL, InterruptT* interrupter = NULL);
114 
115 
116 ////////////////////////////////////////
117 
118 
119 // Internal utility objects and implementation details
120 
121 namespace internal {
122 
124 {
125 public:
126  PointListTransform(const PointList& pointsIn, std::vector<Vec3s>& pointsOut,
127  const math::Transform& xform)
128  : mPointsIn(pointsIn)
129  , mPointsOut(&pointsOut)
130  , mXform(xform)
131  {
132  }
133 
134  void runParallel()
135  {
136  tbb::parallel_for(tbb::blocked_range<size_t>(0, mPointsOut->size()), *this);
137  }
138 
139  void runSerial()
140  {
141  (*this)(tbb::blocked_range<size_t>(0, mPointsOut->size()));
142  }
143 
144  inline void operator()(const tbb::blocked_range<size_t>& range) const
145  {
146  for (size_t n = range.begin(); n < range.end(); ++n) {
147  (*mPointsOut)[n] = Vec3s(mXform.worldToIndex(mPointsIn[n]));
148  }
149  }
150 
151 private:
152  const PointList& mPointsIn;
153  std::vector<Vec3s> * const mPointsOut;
154  const math::Transform& mXform;
155 };
156 
157 
158 class PrimCpy
159 {
160 public:
161  PrimCpy(const PolygonPoolList& primsIn, const std::vector<size_t>& indexList,
162  std::vector<Vec4I>& primsOut)
163  : mPrimsIn(primsIn)
164  , mIndexList(indexList)
165  , mPrimsOut(&primsOut)
166  {
167  }
168 
169  void runParallel()
170  {
171  tbb::parallel_for(tbb::blocked_range<size_t>(0, mIndexList.size()), *this);
172  }
173 
174  void runSerial()
175  {
176  (*this)(tbb::blocked_range<size_t>(0, mIndexList.size()));
177  }
178 
179  inline void operator()(const tbb::blocked_range<size_t>& range) const
180  {
181  openvdb::Vec4I quad;
182  quad[3] = openvdb::util::INVALID_IDX;
183  std::vector<Vec4I>& primsOut = *mPrimsOut;
184 
185  for (size_t n = range.begin(); n < range.end(); ++n) {
186  size_t index = mIndexList[n];
187  PolygonPool& polygons = mPrimsIn[n];
188 
189  // Copy quads
190  for (size_t i = 0, I = polygons.numQuads(); i < I; ++i) {
191  primsOut[index++] = polygons.quad(i);
192  }
193  polygons.clearQuads();
194 
195  // Copy triangles (adaptive mesh)
196  for (size_t i = 0, I = polygons.numTriangles(); i < I; ++i) {
197  const openvdb::Vec3I& triangle = polygons.triangle(i);
198  quad[0] = triangle[0];
199  quad[1] = triangle[1];
200  quad[2] = triangle[2];
201  primsOut[index++] = quad;
202  }
203 
204  polygons.clearTriangles();
205  }
206  }
207 
208 private:
209  const PolygonPoolList& mPrimsIn;
210  const std::vector<size_t>& mIndexList;
211  std::vector<Vec4I> * const mPrimsOut;
212 };
213 
214 } // namespace internal
215 
216 
217 ////////////////////////////////////////
218 
219 
220 /// The normal entry points for level set rebuild are the levelSetRebuild() functions.
221 /// doLevelSetRebuild() is mainly for internal use, but when the isovalue and half band
222 /// widths are given in ValueType units (for example, if they are queried from
223 /// a grid), it might be more convenient to call this function directly.
224 ///
225 /// @internal This overload is enabled only for grids with a scalar, floating-point ValueType.
226 template<class GridType, typename InterruptT>
227 inline typename hboost::enable_if<hboost::is_floating_point<typename GridType::ValueType>,
228 typename GridType::Ptr>::type
229 doLevelSetRebuild(const GridType& grid, typename GridType::ValueType iso,
230  typename GridType::ValueType exWidth, typename GridType::ValueType inWidth,
231  const math::Transform* xform, InterruptT* interrupter)
232 {
233  const float
234  isovalue = float(iso),
235  exBandWidth = float(exWidth),
236  inBandWidth = float(inWidth);
237 
238  tools::VolumeToMesh mesher(isovalue);
239  mesher(grid);
240 
241  math::Transform::Ptr transform = (xform != NULL) ? xform->copy() : grid.transform().copy();
242 
243  std::vector<Vec3s> points(mesher.pointListSize());
244 
245  { // Copy and transform (required for MeshToVolume) points to grid space.
246  internal::PointListTransform ptnXForm(mesher.pointList(), points, *transform);
247  ptnXForm.runParallel();
248  mesher.pointList().reset(NULL);
249  }
250 
251  std::vector<Vec4I> primitives;
252 
253  { // Copy primitives.
254  PolygonPoolList& polygonPoolList = mesher.polygonPoolList();
255 
256  size_t numPrimitives = 0;
257  std::vector<size_t> indexlist(mesher.polygonPoolListSize());
258 
259  for (size_t n = 0, N = mesher.polygonPoolListSize(); n < N; ++n) {
260  const openvdb::tools::PolygonPool& polygons = polygonPoolList[n];
261  indexlist[n] = numPrimitives;
262  numPrimitives += polygons.numQuads();
263  numPrimitives += polygons.numTriangles();
264  }
265 
266  primitives.resize(numPrimitives);
267  internal::PrimCpy primCpy(polygonPoolList, indexlist, primitives);
268  primCpy.runParallel();
269  }
270 
271  QuadAndTriangleDataAdapter<Vec3s, Vec4I> mesh(points, primitives);
272 
273  if (interrupter) {
274  return meshToVolume<GridType>(*interrupter, mesh, *transform, exBandWidth, inBandWidth,
276  }
277 
278  return meshToVolume<GridType>(mesh, *transform, exBandWidth, inBandWidth,
280 }
281 
282 
283 /// @internal This overload is enabled only for grids that do not have a scalar,
284 /// floating-point ValueType.
285 template<class GridType, typename InterruptT>
286 inline typename hboost::disable_if<hboost::is_floating_point<typename GridType::ValueType>,
287 typename GridType::Ptr>::type
288 doLevelSetRebuild(const GridType&, typename GridType::ValueType /*isovalue*/,
289  typename GridType::ValueType /*exWidth*/, typename GridType::ValueType /*inWidth*/,
290  const math::Transform*, InterruptT*)
291 {
292  OPENVDB_THROW(TypeError,
293  "level set rebuild is supported only for scalar, floating-point grids");
294 }
295 
296 
297 ////////////////////////////////////////
298 
299 
300 template<class GridType, typename InterruptT>
301 inline typename GridType::Ptr
302 levelSetRebuild(const GridType& grid, float iso, float exWidth, float inWidth,
303  const math::Transform* xform, InterruptT* interrupter)
304 {
305  typedef typename GridType::ValueType ValueT;
306  ValueT
307  isovalue(zeroVal<ValueT>() + ValueT(iso)),
308  exBandWidth(zeroVal<ValueT>() + ValueT(exWidth)),
309  inBandWidth(zeroVal<ValueT>() + ValueT(inWidth));
310 
311  return doLevelSetRebuild(grid, isovalue, exBandWidth, inBandWidth, xform, interrupter);
312 }
313 
314 
315 template<class GridType>
316 inline typename GridType::Ptr
317 levelSetRebuild(const GridType& grid, float iso, float exWidth, float inWidth,
318  const math::Transform* xform)
319 {
320  typedef typename GridType::ValueType ValueT;
321  ValueT
322  isovalue(zeroVal<ValueT>() + ValueT(iso)),
323  exBandWidth(zeroVal<ValueT>() + ValueT(exWidth)),
324  inBandWidth(zeroVal<ValueT>() + ValueT(inWidth));
325 
326  return doLevelSetRebuild<GridType, util::NullInterrupter>(
327  grid, isovalue, exBandWidth, inBandWidth, xform, NULL);
328 }
329 
330 
331 template<class GridType>
332 inline typename GridType::Ptr
333 levelSetRebuild(const GridType& grid, float iso, float halfVal, const math::Transform* xform)
334 {
335  typedef typename GridType::ValueType ValueT;
336  ValueT
337  isovalue(zeroVal<ValueT>() + ValueT(iso)),
338  halfWidth(zeroVal<ValueT>() + ValueT(halfVal));
339 
340  return doLevelSetRebuild<GridType, util::NullInterrupter>(
341  grid, isovalue, halfWidth, halfWidth, xform, NULL);
342 }
343 
344 
345 } // namespace tools
346 } // namespace OPENVDB_VERSION_NAME
347 } // namespace openvdb
348 
349 #endif // OPENVDB_TOOLS_LEVELSETREBUILD_HAS_BEEN_INCLUDED
350 
351 // Copyright (c) 2012-2017 DreamWorks Animation LLC
352 // All rights reserved. This software is distributed under the
353 // 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
hboost::enable_if< hboost::is_floating_point< typename GridType::ValueType >, typename GridType::Ptr >::type doLevelSetRebuild(const GridType &grid, typename GridType::ValueType iso, typename GridType::ValueType exWidth, typename GridType::ValueType inWidth, const math::Transform *xform, InterruptT *interrupter)
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:91
Calculate an axis-aligned bounding box in index space from a bounding sphere in world space...
Definition: Transform.h:66
Extract polygonal surfaces from scalar volumes.
#define OPENVDB_VERSION_NAME
Definition: version.h:43
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
GLuint index
Definition: glcorearb.h:785
math::Vec3< Index32 > Vec3I
Definition: Types.h:76
GA_API const UT_StringHolder N
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:107
GridType::Ptr levelSetRebuild(const GridType &grid, float isovalue=0, float halfWidth=float(LEVEL_SET_HALF_WIDTH), const math::Transform *xform=NULL)
Return a new grid of type GridType that contains a narrow-band level set representation of an isosurf...
hboost::scoped_array< openvdb::Vec3s > PointList
Point and primitive list types.
Definition: VolumeToMesh.h:179
Contiguous quad and triangle data adapter class.
Definition: MeshToVolume.h:191
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
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_THROW(exception, message)
Definition: Exceptions.h:101
Collection of quads and triangles.
Definition: VolumeToMesh.h:121