OpenVDB  0.104.0
ValueTransformer.h
Go to the documentation of this file.
1 
2 //
3 // Copyright (c) 2012 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 
149 template<typename InIterT, typename OutGridT, typename XformOp>
150 inline void transformValues(const InIterT& inIter, OutGridT& outGrid,
151  XformOp& op, bool threaded = true, bool shareOp = true);
152 
153 #ifndef _MSC_VER
154 template<typename InIterT, typename OutGridT, typename XformOp>
155 inline void transformValues(const InIterT& inIter, OutGridT& outGrid,
156  const XformOp& op, bool threaded = true, bool shareOp = true);
157 #endif
158 
159 
161 
162 
163 namespace valxform {
164 
165 
166 template<typename IterT, typename OpT>
168 {
169 public:
171 
172  SharedOpApplier(const IterT& iter, OpT& op): mIter(iter), mOp(op) {}
173 
174  void process(bool threaded = true)
175  {
176  IterRange range(mIter);
177  if (threaded) {
178  tbb::parallel_for(range, *this);
179  } else {
180  (*this)(range);
181  }
182  }
183 
184  void operator()(IterRange& r) const { for ( ; r; ++r) mOp(r.iterator()); }
185 
186 private:
187  IterT mIter;
188  OpT& mOp;
189 };
190 
191 
192 template<typename IterT, typename OpT>
194 {
195 public:
197 
198  CopyableOpApplier(const IterT& iter, const OpT& op): mIter(iter), mOp(op), mOrigOp(&op) {}
199 
200  // When splitting this task, give the subtask a copy of the original functor,
201  // not of this task's functor, which might have been modified arbitrarily.
203  mIter(other.mIter), mOp(*other.mOrigOp), mOrigOp(other.mOrigOp) {}
204 
205  void process(bool threaded = true)
206  {
207  IterRange range(mIter);
208  if (threaded) {
209  tbb::parallel_for(range, *this);
210  } else {
211  (*this)(range);
212  }
213  }
214 
215  void operator()(IterRange& r) const { for ( ; r; ++r) mOp(r.iterator()); }
216 
217 private:
218  IterT mIter;
219  OpT mOp; // copy of original functor
220  const OpT* mOrigOp; // pointer to original functor
221 };
222 
223 } // namespace valxform
224 
225 
226 template<typename IterT, typename XformOp>
227 inline void
228 foreach(const IterT& iter, XformOp& op, bool threaded, bool shared)
229 {
230  if (shared) {
231  typename valxform::SharedOpApplier<IterT, XformOp> proc(iter, op);
232  proc.process(threaded);
233  } else {
234  typedef typename valxform::CopyableOpApplier<IterT, XformOp> Processor;
235  Processor proc(iter, op);
236  proc.process(threaded);
237  }
238 }
239 
240 template<typename IterT, typename XformOp>
241 inline void
242 foreach(const IterT& iter, const XformOp& op, bool threaded, bool /*shared*/)
243 {
244  // Const ops are shared across threads, not copied.
245  typename valxform::SharedOpApplier<IterT, const XformOp> proc(iter, op);
246  proc.process(threaded);
247 }
248 
249 
251 
252 
253 namespace valxform {
254 
255 template<typename InIterT, typename OutTreeT, typename OpT>
257 {
258 public:
259  typedef typename InIterT::TreeT InTreeT;
261  typedef typename OutTreeT::ValueType OutValueT;
262 
263  SharedOpTransformer(const InIterT& inIter, OutTreeT& outTree, OpT& op):
264  mIsRoot(true),
265  mInputIter(inIter),
266  mInputTree(inIter.getTree()),
267  mOutputTree(&outTree),
268  mOp(op)
269  {
270  if (static_cast<const void*>(mInputTree) == static_cast<void*>(mOutputTree)) {
271  OPENVDB_LOG_INFO("use tools::foreach(), not transformValues(),"
272  " to transform a grid in place");
273  }
274  }
275 
278  mIsRoot(false),
279  mInputIter(other.mInputIter),
280  mInputTree(other.mInputTree),
281  mOutputTree(new OutTreeT(zeroVal<OutValueT>())),
282  mOp(other.mOp)
283  {}
284 
286  {
287  // Delete the output tree only if it was allocated locally
288  // (the top-level output tree was supplied by the caller).
289  if (!mIsRoot) {
290  delete mOutputTree;
291  mOutputTree = NULL;
292  }
293  }
294 
295  void process(bool threaded = true)
296  {
297  if (!mInputTree || !mOutputTree) return;
298 
299  IterRange range(mInputIter);
300 
301  // Independently transform elements in the iterator range,
302  // either in parallel or serially.
303  if (threaded) {
304  tbb::parallel_reduce(range, *this);
305  } else {
306  (*this)(range);
307  }
308  }
309 
311  void operator()(IterRange& range) const
312  {
313  if (!mOutputTree) return;
314  typename tree::ValueAccessor<OutTreeT> outAccessor(*mOutputTree);
315  for ( ; range; ++range) {
316  mOp(range.iterator(), outAccessor);
317  }
318  }
319 
320  void join(const SharedOpTransformer& other)
321  {
322  if (mOutputTree && other.mOutputTree) {
323  mOutputTree->merge(*other.mOutputTree);
324  }
325  }
326 
327 private:
328  bool mIsRoot;
329  InIterT mInputIter;
330  const InTreeT* mInputTree;
331  OutTreeT* mOutputTree;
332  OpT& mOp;
333 };
334 
335 } // namespace valxform
336 
337 
339 
340 
341 template<typename InIterT, typename OutGridT, typename XformOp>
342 inline void
343 transformValues(const InIterT& inIter, OutGridT& outGrid, XformOp& op,
344  bool threaded, bool /*shareOp*/)
345 {
347 
348  typedef TreeAdapter<OutGridT> Adapter;
349  typedef typename Adapter::TreeType OutTreeT;
351  Processor proc(inIter, Adapter::tree(outGrid), op);
352  proc.process(threaded);
353 }
354 
355 #ifndef _MSC_VER
356 template<typename InIterT, typename OutGridT, typename XformOp>
357 inline void
358 transformValues(const InIterT& inIter, OutGridT& outGrid, const XformOp& op,
359  bool threaded, bool /*shareOp*/)
360 {
361  typedef TreeAdapter<OutGridT> Adapter;
362  typedef typename Adapter::TreeType OutTreeT;
364  Processor proc(inIter, Adapter::tree(outGrid), op);
365  proc.process(threaded);
366 }
367 #endif
368 
369 } // namespace tools
370 } // namespace OPENVDB_VERSION_NAME
371 } // namespace openvdb
372 
373 #endif // OPENVDB_TOOLS_VALUETRANSFORMER_HAS_BEEN_INCLUDED
374 
375 // Copyright (c) 2012 DreamWorks Animation LLC
376 // All rights reserved. This software is distributed under the
377 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )