OpenVDB  1.2.0
LevelSetUtil.h
Go to the documentation of this file.
1 //
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 //
35 
36 #ifndef OPENVDB_TOOLS_LEVELSETUTIL_HAS_BEEN_INCLUDED
37 #define OPENVDB_TOOLS_LEVELSETUTIL_HAS_BEEN_INCLUDED
38 
39 #include <openvdb/Grid.h>
40 #include <openvdb/tree/LeafManager.h>
41 #include <tbb/blocked_range.h>
42 #include <tbb/parallel_reduce.h>
43 #include <limits>
44 
45 
46 namespace openvdb {
48 namespace OPENVDB_VERSION_NAME {
49 namespace tools {
50 
51 // MS Visual C++ requires this extra level of indirection in order to compile
52 // THIS MUST EXIST IN AN UNNAMED NAMESPACE IN ORDER TO COMPILE ON WINDOWS
53 namespace {
54 
55 template<typename GridType>
56 inline typename GridType::ValueType lsutilGridMax()
57 {
59 }
60 
61 template<typename GridType>
62 inline typename GridType::ValueType lsutilGridZero()
63 {
64  return zeroVal<typename GridType::ValueType>();
65 }
66 
67 } // unnamed namespace
68 
69 
71 
72 
87 template<class GridType>
88 inline void
90  GridType& grid,
91  typename GridType::ValueType cutoffDistance = lsutilGridMax<GridType>());
92 
93 
95 
96 
106 template<class GridType>
107 inline typename Grid<typename GridType::TreeType::template ValueConverter<bool>::Type>::Ptr
109  const GridType& grid,
110  typename GridType::ValueType iso = lsutilGridZero<GridType>());
111 
112 
114 
115 
120 template<class TreeType>
122 {
123 public:
125  typedef typename TreeType::ValueType ValueType;
126 
127  // LeafArray = openvdb::tree::LeafManager<TreeType> leafs(myTree)
129 
130  void runParallel();
131  void runSerial();
132 
133  const ValueType& minVoxel() const { return mMin; }
134  const ValueType& maxVoxel() const { return mMax; }
135 
136  inline MinMaxVoxel(const MinMaxVoxel<TreeType>&, tbb::split);
137  inline void operator()(const tbb::blocked_range<size_t>&);
138  inline void join(const MinMaxVoxel<TreeType>&);
139 
140 private:
141  LeafArray& mLeafArray;
142  ValueType mMin, mMax;
143 };
144 
145 
147 
148 
149 // Internal utility objects and implementation details
150 namespace internal {
151 
152 template<typename ValueType>
154 {
155 public:
156  FogVolumeOp(ValueType cutoffDistance)
157  : mWeight(ValueType(1.0) / cutoffDistance)
158  {
159  }
160 
161  // cutoff has to be < 0.0
162  template <typename LeafNodeType>
163  void operator()(LeafNodeType &leaf, size_t/*leafIndex*/) const
164  {
165  const ValueType zero = zeroVal<ValueType>();
166 
167  for (typename LeafNodeType::ValueAllIter iter = leaf.beginValueAll(); iter; ++iter) {
168  ValueType& value = const_cast<ValueType&>(iter.getValue());
169  if (value > zero) {
170  value = zero;
171  iter.setValueOff();
172  } else {
173  value = std::min(ValueType(1.0), value * mWeight);
174  iter.setValueOn(value > zero);
175  }
176  }
177  }
178 
179 private:
180  ValueType mWeight;
181 }; // class FogVolumeOp
182 
183 
184 template<typename TreeType>
186 {
187 public:
188  InteriorMaskOp(const TreeType& tree, typename TreeType::ValueType iso)
189  : mTree(tree)
190  , mIso(iso)
191  {
192  }
193 
194  template <typename LeafNodeType>
195  void operator()(LeafNodeType &leaf, size_t/*leafIndex*/) const
196  {
197  const Coord origin = leaf.getOrigin();
198  const typename TreeType::LeafNodeType* refLeafPt = mTree.probeConstLeaf(origin);
199 
200  if (refLeafPt != NULL) {
201 
202  const typename TreeType::LeafNodeType& refLeaf = *refLeafPt;
203  typename LeafNodeType::ValueAllIter iter = leaf.beginValueAll();
204 
205  for (; iter; ++iter) {
206  if (refLeaf.getValue(iter.pos()) < mIso) {
207  iter.setValueOn();
208  } else {
209  iter.setValueOff();
210  }
211  }
212  }
213  }
214 
215 private:
216  const TreeType& mTree;
217  typename TreeType::ValueType mIso;
218 }; // class InteriorMaskOp
219 
220 } // namespace internal
221 
222 
224 
225 
226 template <class TreeType>
228  : mLeafArray(leafs)
229  , mMin(std::numeric_limits<ValueType>::max())
230  , mMax(-mMin)
231 {
232 }
233 
234 
235 template <class TreeType>
236 inline
238  : mLeafArray(rhs.mLeafArray)
239  , mMin(rhs.mMin)
240  , mMax(rhs.mMax)
241 {
242 }
243 
244 
245 template <class TreeType>
246 void
248 {
249  tbb::parallel_reduce(mLeafArray.getRange(), *this);
250 }
251 
252 
253 template <class TreeType>
254 void
256 {
257  (*this)(mLeafArray.getRange());
258 }
259 
260 
261 template <class TreeType>
262 inline void
263 MinMaxVoxel<TreeType>::operator()(const tbb::blocked_range<size_t>& range)
264 {
265  typename TreeType::LeafNodeType::ValueOnCIter iter;
266 
267  for (size_t n = range.begin(); n < range.end(); ++n) {
268  iter = mLeafArray.leaf(n).cbeginValueOn();
269  for (; iter; ++iter) {
270  const ValueType value = iter.getValue();
271  mMin = std::min(mMin, value);
272  mMax = std::max(mMax, value);
273  }
274  }
275 }
276 
277 
278 template <class TreeType>
279 inline void
281 {
282  mMin = std::min(mMin, rhs.mMin);
283  mMax = std::max(mMax, rhs.mMax);
284 }
285 
286 
287 
289 
290 
291 template <class GridType>
292 inline void
293 sdfToFogVolume(GridType& grid, typename GridType::ValueType cutoffDistance)
294 {
295  typedef typename GridType::TreeType TreeType;
296  typedef typename GridType::ValueType ValueType;
297 
298  cutoffDistance = -std::abs(cutoffDistance);
299 
300  TreeType& tree = const_cast<TreeType&>(grid.tree());
301 
302  { // Transform all voxels (parallel, over leaf nodes)
303  tree::LeafManager<TreeType> leafs(tree);
304 
305  MinMaxVoxel<TreeType> minmax(leafs);
306  minmax.runParallel();
307 
308  // Clamp to the interior band width.
309  if (minmax.minVoxel() > cutoffDistance) {
310  cutoffDistance = minmax.minVoxel();
311  }
312 
313  leafs.foreach(internal::FogVolumeOp<ValueType>(cutoffDistance));
314  }
315 
316  // Transform all tile values (serial, but the iteration
317  // is constrained from descending into leaf nodes)
318  const ValueType zero = zeroVal<ValueType>();
319  typename TreeType::ValueAllIter iter(tree);
320  iter.setMaxDepth(TreeType::ValueAllIter::LEAF_DEPTH - 1);
321 
322  for ( ; iter; ++iter) {
323  ValueType& value = const_cast<ValueType&>(iter.getValue());
324 
325  if (value > zero) {
326  value = zero;
327  iter.setValueOff();
328  } else {
329  value = ValueType(1.0);
330  iter.setActiveState(true);
331  }
332  }
333 
334  // Update the tree background value.
335 
336  typename TreeType::Ptr newTree(new TreeType(/*background=*/zero));
337  newTree->merge(tree);
338  // This is faster than calling Tree::setBackground, since we only need
339  // to update the value that is returned for coordinates that don't fall
340  // inside an allocated node. All inactive tiles and voxels have already
341  // been updated in the previous step so the Tree::setBackground method
342  // will in this case do a redundant traversal of the tree to update the
343  // inactive values once more.
344 
345  //newTree->pruneInactive();
346  grid.setTree(newTree);
347 
348  grid.setGridClass(GRID_FOG_VOLUME);
349 }
350 
351 
353 
354 
355 template <class GridType>
357 sdfInteriorMask(const GridType& grid, typename GridType::ValueType iso)
358 {
359  typedef typename GridType::TreeType::template ValueConverter<bool>::Type BoolTreeType;
360  typedef Grid<BoolTreeType> BoolGridType;
361 
362  typename BoolGridType::Ptr maskGrid(BoolGridType::create(false));
363  maskGrid->setTransform(grid.transform().copy());
364  BoolTreeType& maskTree = maskGrid->tree();
365 
366  maskTree.topologyUnion(grid.tree());
367 
368  { // Evaluate voxels (parallel, over leaf nodes)
369 
370  tree::LeafManager<BoolTreeType> leafs(maskTree);
371 
373  }
374 
375  // Evaluate tile values (serial, but the iteration
376  // is constrained from descending into leaf nodes)
377 
379  typename BoolTreeType::ValueAllIter iter(maskTree);
380  iter.setMaxDepth(BoolTreeType::ValueAllIter::LEAF_DEPTH - 1);
381 
382  for ( ; iter; ++iter) {
383  iter.setActiveState(acc.getValue(iter.getCoord()) < iso);
384  }
385 
386  maskTree.pruneInactive();
387 
388  return maskGrid;
389 }
390 
391 } // namespace tools
392 } // namespace OPENVDB_VERSION_NAME
393 } // namespace openvdb
394 
395 #endif // OPENVDB_TOOLS_LEVELSETUTIL_HAS_BEEN_INCLUDED
396 
397 // Copyright (c) 2012-2013 DreamWorks Animation LLC
398 // All rights reserved. This software is distributed under the
399 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )