OpenVDB  1.1.0
LevelSetRebuild.h
Go to the documentation of this file.
1 
2 //
3 // Copyright (c) 2012-2013 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 //
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>
38 #include <openvdb/tools/VolumeToMesh.h>
39 #include <openvdb/tools/MeshToVolume.h>
40 #include <openvdb/util/NullInterrupter.h>
41 #include <openvdb/util/Util.h>
42 #include <boost/type_traits/is_floating_point.hpp>
43 #include <boost/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 
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 
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 
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 
117 
118 
119 // Internal utility objects and implementation details
120 
121 namespace internal {
122 
124 {
125 public:
126  PointTransform(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] = 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 
218 
219 
226 template<class GridType, typename InterruptT>
227 inline typename boost::enable_if<boost::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, 0.0005);
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::PointTransform 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  MeshToVolume<GridType, InterruptT> vol(transform, 0, interrupter);
272  vol.convertToLevelSet(points, primitives, exBandWidth, inBandWidth);
273  return vol.distGridPtr();
274 }
275 
276 
279 template<class GridType, typename InterruptT>
280 inline typename boost::disable_if<boost::is_floating_point<typename GridType::ValueType>,
281 typename GridType::Ptr>::type
282 doLevelSetRebuild(const GridType&, typename GridType::ValueType /*isovalue*/,
283  typename GridType::ValueType /*exWidth*/, typename GridType::ValueType /*inWidth*/,
284  const math::Transform*, InterruptT*)
285 {
287  "level set rebuild is supported only for scalar, floating-point grids");
288 }
289 
290 
292 
293 
294 template<class GridType, typename InterruptT>
295 inline typename GridType::Ptr
296 levelSetRebuild(const GridType& grid, float iso, float exWidth, float inWidth,
297  const math::Transform* xform, InterruptT* interrupter)
298 {
299  typedef typename GridType::ValueType ValueT;
300  ValueT
301  isovalue(zeroVal<ValueT>() + iso),
302  exBandWidth(zeroVal<ValueT>() + exWidth),
303  inBandWidth(zeroVal<ValueT>() + inWidth);
304 
305  return doLevelSetRebuild(grid, isovalue, exBandWidth, inBandWidth, xform, interrupter);
306 }
307 
308 
309 template<class GridType>
310 inline typename GridType::Ptr
311 levelSetRebuild(const GridType& grid, float iso, float exWidth, float inWidth,
312  const math::Transform* xform)
313 {
314  typedef typename GridType::ValueType ValueT;
315  ValueT
316  isovalue(zeroVal<ValueT>() + iso),
317  exBandWidth(zeroVal<ValueT>() + exWidth),
318  inBandWidth(zeroVal<ValueT>() + inWidth);
319 
320  return doLevelSetRebuild<GridType, util::NullInterrupter>(
321  grid, isovalue, exBandWidth, inBandWidth, xform, NULL);
322 }
323 
324 
325 template<class GridType>
326 inline typename GridType::Ptr
327 levelSetRebuild(const GridType& grid, float iso, float half, const math::Transform* xform)
328 {
329  typedef typename GridType::ValueType ValueT;
330  ValueT
331  isovalue(zeroVal<ValueT>() + iso),
332  halfWidth(zeroVal<ValueT>() + half);
333 
334  return doLevelSetRebuild<GridType, util::NullInterrupter>(
335  grid, isovalue, halfWidth, halfWidth, xform, NULL);
336 }
337 
338 
339 } // namespace tools
340 } // namespace OPENVDB_VERSION_NAME
341 } // namespace openvdb
342 
343 #endif // OPENVDB_TOOLS_LEVELSETREBUILD_HAS_BEEN_INCLUDED
344 
345 // Copyright (c) 2012-2013 DreamWorks Animation LLC
346 // All rights reserved. This software is distributed under the
347 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )