OpenVDB  1.1.0
ValueTransformer.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 //
41 
42 #ifndef OPENVDB_TOOLS_VALUETRANSFORMER_HAS_BEEN_INCLUDED
43 #define OPENVDB_TOOLS_VALUETRANSFORMER_HAS_BEEN_INCLUDED
44 
45 #include <tbb/parallel_for.h>
46 #include <tbb/parallel_reduce.h>
47 #include <openvdb/Types.h>
48 #include <openvdb/Grid.h>
49 
50 
51 namespace openvdb {
53 namespace OPENVDB_VERSION_NAME {
54 namespace tools {
55 
99 template<typename IterT, typename XformOp>
100 inline void foreach(const IterT& iter, XformOp& op,
101  bool threaded = true, bool shareOp = true);
102 
103 template<typename IterT, typename XformOp>
104 inline void foreach(const IterT& iter, const XformOp& op,
105  bool threaded = true, bool shareOp = true);
106 
107 
147 template<typename InIterT, typename OutGridT, typename XformOp>
148 inline void transformValues(const InIterT& inIter, OutGridT& outGrid,
149  XformOp& op, bool threaded = true, bool shareOp = true);
150 
151 #ifndef _MSC_VER
152 template<typename InIterT, typename OutGridT, typename XformOp>
153 inline void transformValues(const InIterT& inIter, OutGridT& outGrid,
154  const XformOp& op, bool threaded = true, bool shareOp = true);
155 #endif
156 
157 
159 
160 
161 namespace valxform {
162 
163 template<typename IterT, typename OpT>
165 {
166 public:
168 
169  SharedOpApplier(const IterT& iter, OpT& op): mIter(iter), mOp(op) {}
170 
171  void process(bool threaded = true)
172  {
173  IterRange range(mIter);
174  if (threaded) {
175  tbb::parallel_for(range, *this);
176  } else {
177  (*this)(range);
178  }
179  }
180 
181  void operator()(IterRange& r) const { for ( ; r; ++r) mOp(r.iterator()); }
182 
183 private:
184  IterT mIter;
185  OpT& mOp;
186 };
187 
188 
189 template<typename IterT, typename OpT>
191 {
192 public:
194 
195  CopyableOpApplier(const IterT& iter, const OpT& op): mIter(iter), mOp(op), mOrigOp(&op) {}
196 
197  // When splitting this task, give the subtask a copy of the original functor,
198  // not of this task's functor, which might have been modified arbitrarily.
200  mIter(other.mIter), mOp(*other.mOrigOp), mOrigOp(other.mOrigOp) {}
201 
202  void process(bool threaded = true)
203  {
204  IterRange range(mIter);
205  if (threaded) {
206  tbb::parallel_for(range, *this);
207  } else {
208  (*this)(range);
209  }
210  }
211 
212  void operator()(IterRange& r) const { for ( ; r; ++r) mOp(r.iterator()); }
213 
214 private:
215  IterT mIter;
216  OpT mOp; // copy of original functor
217  OpT const * const mOrigOp; // pointer to original functor
218 };
219 
220 } // namespace valxform
221 
222 
223 template<typename IterT, typename XformOp>
224 inline void
225 foreach(const IterT& iter, XformOp& op, bool threaded, bool shared)
226 {
227  if (shared) {
228  typename valxform::SharedOpApplier<IterT, XformOp> proc(iter, op);
229  proc.process(threaded);
230  } else {
231  typedef typename valxform::CopyableOpApplier<IterT, XformOp> Processor;
232  Processor proc(iter, op);
233  proc.process(threaded);
234  }
235 }
236 
237 template<typename IterT, typename XformOp>
238 inline void
239 foreach(const IterT& iter, const XformOp& op, bool threaded, bool /*shared*/)
240 {
241  // Const ops are shared across threads, not copied.
242  typename valxform::SharedOpApplier<IterT, const XformOp> proc(iter, op);
243  proc.process(threaded);
244 }
245 
246 
248 
249 
250 namespace valxform {
251 
252 template<typename InIterT, typename OutTreeT, typename OpT>
254 {
255 public:
256  typedef typename InIterT::TreeT InTreeT;
258  typedef typename OutTreeT::ValueType OutValueT;
259 
260  SharedOpTransformer(const InIterT& inIter, OutTreeT& outTree, OpT& op):
261  mIsRoot(true),
262  mInputIter(inIter),
263  mInputTree(inIter.getTree()),
264  mOutputTree(&outTree),
265  mOp(op)
266  {
267  if (static_cast<const void*>(mInputTree) == static_cast<void*>(mOutputTree)) {
268  OPENVDB_LOG_INFO("use tools::foreach(), not transformValues(),"
269  " to transform a grid in place");
270  }
271  }
272 
275  mIsRoot(false),
276  mInputIter(other.mInputIter),
277  mInputTree(other.mInputTree),
278  mOutputTree(new OutTreeT(zeroVal<OutValueT>())),
279  mOp(other.mOp)
280  {}
281 
283  {
284  // Delete the output tree only if it was allocated locally
285  // (the top-level output tree was supplied by the caller).
286  if (!mIsRoot) {
287  delete mOutputTree;
288  mOutputTree = NULL;
289  }
290  }
291 
292  void process(bool threaded = true)
293  {
294  if (!mInputTree || !mOutputTree) return;
295 
296  IterRange range(mInputIter);
297 
298  // Independently transform elements in the iterator range,
299  // either in parallel or serially.
300  if (threaded) {
301  tbb::parallel_reduce(range, *this);
302  } else {
303  (*this)(range);
304  }
305  }
306 
308  void operator()(IterRange& range) const
309  {
310  if (!mOutputTree) return;
311  typename tree::ValueAccessor<OutTreeT> outAccessor(*mOutputTree);
312  for ( ; range; ++range) {
313  mOp(range.iterator(), outAccessor);
314  }
315  }
316 
317  void join(const SharedOpTransformer& other)
318  {
319  if (mOutputTree && other.mOutputTree) {
320  mOutputTree->merge(*other.mOutputTree);
321  }
322  }
323 
324 private:
325  bool mIsRoot;
326  InIterT mInputIter;
327  const InTreeT* mInputTree;
328  OutTreeT* mOutputTree;
329  OpT& mOp;
330 }; // class SharedOpTransformer
331 
332 
333 template<typename InIterT, typename OutTreeT, typename OpT>
335 {
336 public:
337  typedef typename InIterT::TreeT InTreeT;
339  typedef typename OutTreeT::ValueType OutValueT;
340 
341  CopyableOpTransformer(const InIterT& inIter, OutTreeT& outTree, const OpT& op):
342  mIsRoot(true),
343  mInputIter(inIter),
344  mInputTree(inIter.getTree()),
345  mOutputTree(&outTree),
346  mOp(op),
347  mOrigOp(&op)
348  {
349  if (static_cast<const void*>(mInputTree) == static_cast<void*>(mOutputTree)) {
350  OPENVDB_LOG_INFO("use tools::foreach(), not transformValues(),"
351  " to transform a grid in place");
352  }
353  }
354 
355  // When splitting this task, give the subtask a copy of the original functor,
356  // not of this task's functor, which might have been modified arbitrarily.
358  mIsRoot(false),
359  mInputIter(other.mInputIter),
360  mInputTree(other.mInputTree),
361  mOutputTree(new OutTreeT(zeroVal<OutValueT>())),
362  mOp(*other.mOrigOp),
363  mOrigOp(other.mOrigOp)
364  {}
365 
367  {
368  // Delete the output tree only if it was allocated locally
369  // (the top-level output tree was supplied by the caller).
370  if (!mIsRoot) {
371  delete mOutputTree;
372  mOutputTree = NULL;
373  }
374  }
375 
376  void process(bool threaded = true)
377  {
378  if (!mInputTree || !mOutputTree) return;
379 
380  IterRange range(mInputIter);
381 
382  // Independently transform elements in the iterator range,
383  // either in parallel or serially.
384  if (threaded) {
385  tbb::parallel_reduce(range, *this);
386  } else {
387  (*this)(range);
388  }
389  }
390 
392  void operator()(IterRange& range)
393  {
394  if (!mOutputTree) return;
395  typename tree::ValueAccessor<OutTreeT> outAccessor(*mOutputTree);
396  for ( ; range; ++range) {
397  mOp(range.iterator(), outAccessor);
398  }
399  }
400 
401  void join(const CopyableOpTransformer& other)
402  {
403  if (mOutputTree && other.mOutputTree) {
404  mOutputTree->merge(*other.mOutputTree);
405  }
406  }
407 
408 private:
409  bool mIsRoot;
410  InIterT mInputIter;
411  const InTreeT* mInputTree;
412  OutTreeT* mOutputTree;
413  OpT mOp; // copy of original functor
414  OpT const * const mOrigOp; // pointer to original functor
415 }; // class CopyableOpTransformer
416 
417 } // namespace valxform
418 
419 
421 
422 
423 template<typename InIterT, typename OutGridT, typename XformOp>
424 inline void
425 transformValues(const InIterT& inIter, OutGridT& outGrid, XformOp& op,
426  bool threaded, bool shared)
427 {
428  typedef TreeAdapter<OutGridT> Adapter;
429  typedef typename Adapter::TreeType OutTreeT;
430  if (shared) {
432  Processor proc(inIter, Adapter::tree(outGrid), op);
433  proc.process(threaded);
434  } else {
436  Processor proc(inIter, Adapter::tree(outGrid), op);
437  proc.process(threaded);
438  }
439 }
440 
441 #ifndef _MSC_VER
442 template<typename InIterT, typename OutGridT, typename XformOp>
443 inline void
444 transformValues(const InIterT& inIter, OutGridT& outGrid, const XformOp& op,
445  bool threaded, bool /*share*/)
446 {
447  typedef TreeAdapter<OutGridT> Adapter;
448  typedef typename Adapter::TreeType OutTreeT;
449  // Const ops are shared across threads, not copied.
451  Processor proc(inIter, Adapter::tree(outGrid), op);
452  proc.process(threaded);
453 }
454 #endif
455 
456 } // namespace tools
457 } // namespace OPENVDB_VERSION_NAME
458 } // namespace openvdb
459 
460 #endif // OPENVDB_TOOLS_VALUETRANSFORMER_HAS_BEEN_INCLUDED
461 
462 // Copyright (c) 2012-2013 DreamWorks Animation LLC
463 // All rights reserved. This software is distributed under the
464 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )