HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ValueTransformer.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 //
4 /// @file ValueTransformer.h
5 ///
6 /// @author Peter Cucka
7 ///
8 /// tools::foreach() and tools::transformValues() transform the values in a grid
9 /// by iterating over the grid with a user-supplied iterator and applying a
10 /// user-supplied functor at each step of the iteration. With tools::foreach(),
11 /// the transformation is done in-place on the input grid, whereas with
12 /// tools::transformValues(), transformed values are written to an output grid
13 /// (which can, for example, have a different value type than the input grid).
14 /// Both functions can optionally transform multiple values of the grid in parallel.
15 ///
16 /// tools::accumulate() can be used to accumulate the results of applying a functor
17 /// at each step of a grid iteration. (The functor is responsible for storing and
18 /// updating intermediate results.) When the iteration is done serially the behavior is
19 /// the same as with tools::foreach(), but when multiple values are processed in parallel,
20 /// an additional step is performed: when any two threads finish processing,
21 /// @c op.join(otherOp) is called on one thread's functor to allow it to coalesce
22 /// its intermediate result with the other thread's.
23 ///
24 /// Finally, tools::setValueOnMin(), tools::setValueOnMax(), tools::setValueOnSum()
25 /// and tools::setValueOnMult() are wrappers around Tree::modifyValue() (or
26 /// ValueAccessor::modifyValue()) for some commmon in-place operations.
27 /// These are typically significantly faster than calling getValue() followed by setValue().
28 
29 #ifndef OPENVDB_TOOLS_VALUETRANSFORMER_HAS_BEEN_INCLUDED
30 #define OPENVDB_TOOLS_VALUETRANSFORMER_HAS_BEEN_INCLUDED
31 
32 #include <algorithm> // for std::min(), std::max()
33 #include <tbb/parallel_for.h>
34 #include <tbb/parallel_reduce.h>
35 #include <openvdb/Types.h>
36 #include <openvdb/Grid.h>
37 #include <openvdb/openvdb.h>
38 
39 
40 namespace openvdb {
42 namespace OPENVDB_VERSION_NAME {
43 namespace tools {
44 
45 /// Iterate over a grid and at each step call @c op(iter).
46 /// @param iter an iterator over a grid or its tree (@c Grid::ValueOnCIter,
47 /// @c Tree::NodeIter, etc.)
48 /// @param op a functor of the form <tt>void op(const IterT&)</tt>, where @c IterT is
49 /// the type of @a iter
50 /// @param threaded if true, transform multiple values of the grid in parallel
51 /// @param shareOp if true and @a threaded is true, all threads use the same functor;
52 /// otherwise, each thread gets its own copy of the @e original functor
53 ///
54 /// @par Example:
55 /// Multiply all values (both set and unset) of a scalar, floating-point grid by two.
56 /// @code
57 /// struct Local {
58 /// static inline void op(const FloatGrid::ValueAllIter& iter) {
59 /// iter.setValue(*iter * 2);
60 /// }
61 /// };
62 /// FloatGrid grid = ...;
63 /// tools::foreach(grid.beginValueAll(), Local::op);
64 /// @endcode
65 ///
66 /// @par Example:
67 /// Rotate all active vectors of a vector grid by 45 degrees about the y axis.
68 /// @code
69 /// namespace {
70 /// struct MatMul {
71 /// math::Mat3s M;
72 /// MatMul(const math::Mat3s& mat): M(mat) {}
73 /// inline void operator()(const VectorGrid::ValueOnIter& iter) const {
74 /// iter.setValue(M.transform(*iter));
75 /// }
76 /// };
77 /// }
78 /// {
79 /// VectorGrid grid = ...;
80 /// tools::foreach(grid.beginValueOn(),
81 /// MatMul(math::rotation<math::Mat3s>(math::Y, M_PI_4)));
82 /// }
83 /// @endcode
84 ///
85 /// @note For more complex operations that require finer control over threading,
86 /// consider using @c tbb::parallel_for() or @c tbb::parallel_reduce() in conjunction
87 /// with a tree::IteratorRange that wraps a grid or tree iterator.
88 template<typename IterT, typename XformOp>
89 inline void foreach(const IterT& iter, XformOp& op,
90  bool threaded = true, bool shareOp = true);
91 
92 template<typename IterT, typename XformOp>
93 inline void foreach(const IterT& iter, const XformOp& op,
94  bool threaded = true, bool shareOp = true);
95 
96 
97 /// Iterate over a grid and at each step call <tt>op(iter, accessor)</tt> to
98 /// populate (via the accessor) the given output grid, whose @c ValueType
99 /// need not be the same as the input grid's.
100 /// @param inIter a non-<tt>const</tt> or (preferably) @c const iterator over an
101 /// input grid or its tree (@c Grid::ValueOnCIter, @c Tree::NodeIter, etc.)
102 /// @param outGrid an empty grid to be populated
103 /// @param op a functor of the form
104 /// <tt>void op(const InIterT&, OutGridT::ValueAccessor&)</tt>,
105 /// where @c InIterT is the type of @a inIter
106 /// @param threaded if true, transform multiple values of the input grid in parallel
107 /// @param shareOp if true and @a threaded is true, all threads use the same functor;
108 /// otherwise, each thread gets its own copy of the @e original functor
109 /// @param merge how to merge intermediate results from multiple threads (see Types.h)
110 ///
111 /// @par Example:
112 /// Populate a scalar floating-point grid with the lengths of the vectors from all
113 /// active voxels of a vector-valued input grid.
114 /// @code
115 /// struct Local {
116 /// static void op(
117 /// const Vec3fGrid::ValueOnCIter& iter,
118 /// FloatGrid::ValueAccessor& accessor)
119 /// {
120 /// if (iter.isVoxelValue()) { // set a single voxel
121 /// accessor.setValue(iter.getCoord(), iter->length());
122 /// } else { // fill an entire tile
123 /// CoordBBox bbox;
124 /// iter.getBoundingBox(bbox);
125 /// accessor.getTree()->fill(bbox, iter->length());
126 /// }
127 /// }
128 /// };
129 /// Vec3fGrid inGrid = ...;
130 /// FloatGrid outGrid;
131 /// tools::transformValues(inGrid.cbeginValueOn(), outGrid, Local::op);
132 /// @endcode
133 ///
134 /// @note For more complex operations that require finer control over threading,
135 /// consider using @c tbb::parallel_for() or @c tbb::parallel_reduce() in conjunction
136 /// with a tree::IteratorRange that wraps a grid or tree iterator.
137 template<typename InIterT, typename OutGridT, typename XformOp>
138 inline void transformValues(const InIterT& inIter, OutGridT& outGrid,
139  XformOp& op, bool threaded = true, bool shareOp = true,
141 
142 #ifndef _WIN32
143 template<typename InIterT, typename OutGridT, typename XformOp>
144 inline void transformValues(const InIterT& inIter, OutGridT& outGrid,
145  const XformOp& op, bool threaded = true, bool shareOp = true,
147 #endif
148 
149 
150 /// Iterate over a grid and at each step call @c op(iter). If threading is enabled,
151 /// call @c op.join(otherOp) to accumulate intermediate results from pairs of threads.
152 /// @param iter an iterator over a grid or its tree (@c Grid::ValueOnCIter,
153 /// @c Tree::NodeIter, etc.)
154 /// @param op a functor with a join method of the form <tt>void join(XformOp&)</tt>
155 /// and a call method of the form <tt>void op(const IterT&)</tt>,
156 /// where @c IterT is the type of @a iter
157 /// @param threaded if true, transform multiple values of the grid in parallel
158 /// @note If @a threaded is true, each thread gets its own copy of the @e original functor.
159 /// The order in which threads are joined is unspecified.
160 /// @note If @a threaded is false, the join method is never called.
161 ///
162 /// @par Example:
163 /// Compute the average of the active values of a scalar, floating-point grid
164 /// using the math::Stats class.
165 /// @code
166 /// namespace {
167 /// struct Average {
168 /// math::Stats stats;
169 ///
170 /// // Accumulate voxel and tile values into this functor's Stats object.
171 /// inline void operator()(const FloatGrid::ValueOnCIter& iter) {
172 /// if (iter.isVoxelValue()) stats.add(*iter);
173 /// else stats.add(*iter, iter.getVoxelCount());
174 /// }
175 ///
176 /// // Accumulate another functor's Stats object into this functor's.
177 /// inline void join(Average& other) { stats.add(other.stats); }
178 ///
179 /// // Return the cumulative result.
180 /// inline double average() const { return stats.mean(); }
181 /// };
182 /// }
183 /// {
184 /// FloatGrid grid = ...;
185 /// Average op;
186 /// tools::accumulate(grid.cbeginValueOn(), op);
187 /// double average = op.average();
188 /// }
189 /// @endcode
190 ///
191 /// @note For more complex operations that require finer control over threading,
192 /// consider using @c tbb::parallel_for() or @c tbb::parallel_reduce() in conjunction
193 /// with a tree::IteratorRange that wraps a grid or tree iterator.
194 template<typename IterT, typename XformOp>
195 inline void accumulate(const IterT& iter, XformOp& op, bool threaded = true);
196 
197 
198 /// @brief Set the value of the voxel at the given coordinates in @a tree to
199 /// the minimum of its current value and @a value, and mark the voxel as active.
200 /// @details This is typically significantly faster than calling getValue()
201 /// followed by setValueOn().
202 /// @note @a TreeT can be either a Tree or a ValueAccessor.
203 template<typename TreeT>
204 void setValueOnMin(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
205 
206 /// @brief Set the value of the voxel at the given coordinates in @a tree to
207 /// the maximum of its current value and @a value, and mark the voxel as active.
208 /// @details This is typically significantly faster than calling getValue()
209 /// followed by setValueOn().
210 /// @note @a TreeT can be either a Tree or a ValueAccessor.
211 template<typename TreeT>
212 void setValueOnMax(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
213 
214 /// @brief Set the value of the voxel at the given coordinates in @a tree to
215 /// the sum of its current value and @a value, and mark the voxel as active.
216 /// @details This is typically significantly faster than calling getValue()
217 /// followed by setValueOn().
218 /// @note @a TreeT can be either a Tree or a ValueAccessor.
219 template<typename TreeT>
220 void setValueOnSum(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
221 
222 /// @brief Set the value of the voxel at the given coordinates in @a tree to
223 /// the product of its current value and @a value, and mark the voxel as active.
224 /// @details This is typically significantly faster than calling getValue()
225 /// followed by setValueOn().
226 /// @note @a TreeT can be either a Tree or a ValueAccessor.
227 template<typename TreeT>
228 void setValueOnMult(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
229 
230 
231 ////////////////////////////////////////
232 
233 
234 namespace valxform {
235 
236 template<typename ValueType>
237 struct MinOp {
238  const ValueType val;
239  MinOp(const ValueType& v): val(v) {}
240  inline void operator()(ValueType& v) const { v = std::min<ValueType>(v, val); }
241 };
242 
243 template<typename ValueType>
244 struct MaxOp {
245  const ValueType val;
246  MaxOp(const ValueType& v): val(v) {}
247  inline void operator()(ValueType& v) const { v = std::max<ValueType>(v, val); }
248 };
249 
250 template<typename ValueType>
251 struct SumOp {
252  const ValueType val;
253  SumOp(const ValueType& v): val(v) {}
254  inline void operator()(ValueType& v) const { v += val; }
255 };
256 
257 template<>
258 struct SumOp<bool> {
259  using ValueType = bool;
260  const ValueType val;
261  SumOp(const ValueType& v): val(v) {}
262  inline void operator()(ValueType& v) const { v = v || val; }
263 };
264 
265 template<typename ValueType>
266 struct MultOp {
267  const ValueType val;
268  MultOp(const ValueType& v): val(v) {}
269  inline void operator()(ValueType& v) const { v *= val; }
270 };
271 
272 template<>
273 struct MultOp<bool> {
274  using ValueType = bool;
275  const ValueType val;
276  MultOp(const ValueType& v): val(v) {}
277  inline void operator()(ValueType& v) const { v = v && val; }
278 };
279 
280 }
281 
282 
283 template<typename TreeT>
284 void
285 setValueOnMin(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
286 {
287  tree.modifyValue(xyz, valxform::MinOp<typename TreeT::ValueType>(value));
288 }
289 
290 
291 template<typename TreeT>
292 void
293 setValueOnMax(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
294 {
295  tree.modifyValue(xyz, valxform::MaxOp<typename TreeT::ValueType>(value));
296 }
297 
298 
299 template<typename TreeT>
300 void
301 setValueOnSum(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
302 {
303  tree.modifyValue(xyz, valxform::SumOp<typename TreeT::ValueType>(value));
304 }
305 
306 
307 template<typename TreeT>
308 void
309 setValueOnMult(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
310 {
311  tree.modifyValue(xyz, valxform::MultOp<typename TreeT::ValueType>(value));
312 }
313 
314 
315 ////////////////////////////////////////
316 
317 
318 namespace valxform {
319 
320 template<typename IterT, typename OpT>
322 {
323 public:
325 
326  SharedOpApplier(const IterT& iter, OpT& op): mIter(iter), mOp(op) {}
327 
328  void process(bool threaded = true)
329  {
330  IterRange range(mIter);
331  if (threaded) {
332  tbb::parallel_for(range, *this);
333  } else {
334  (*this)(range);
335  }
336  }
337 
338  void operator()(IterRange& r) const { for ( ; r; ++r) mOp(r.iterator()); }
339 
340 private:
341  IterT mIter;
342  OpT& mOp;
343 };
344 
345 
346 template<typename IterT, typename OpT>
348 {
349 public:
351 
352  CopyableOpApplier(const IterT& iter, const OpT& op): mIter(iter), mOp(op), mOrigOp(&op) {}
353 
354  // When splitting this task, give the subtask a copy of the original functor,
355  // not of this task's functor, which might have been modified arbitrarily.
357  mIter(other.mIter), mOp(*other.mOrigOp), mOrigOp(other.mOrigOp) {}
358 
359  void process(bool threaded = true)
360  {
361  IterRange range(mIter);
362  if (threaded) {
363  tbb::parallel_for(range, *this);
364  } else {
365  (*this)(range);
366  }
367  }
368 
369  void operator()(IterRange& r) const { for ( ; r; ++r) mOp(r.iterator()); }
370 
371 private:
372  IterT mIter;
373  OpT mOp; // copy of original functor
374  OpT const * const mOrigOp; // pointer to original functor
375 };
376 
377 } // namespace valxform
378 
379 
380 template<typename IterT, typename XformOp>
381 inline void
382 foreach(const IterT& iter, XformOp& op, bool threaded, bool shared)
383 {
384  if (shared) {
385  typename valxform::SharedOpApplier<IterT, XformOp> proc(iter, op);
386  proc.process(threaded);
387  } else {
389  Processor proc(iter, op);
390  proc.process(threaded);
391  }
392 }
393 
394 template<typename IterT, typename XformOp>
395 inline void
396 foreach(const IterT& iter, const XformOp& op, bool threaded, bool /*shared*/)
397 {
398  // Const ops are shared across threads, not copied.
399  typename valxform::SharedOpApplier<IterT, const XformOp> proc(iter, op);
400  proc.process(threaded);
401 }
402 
403 
404 ////////////////////////////////////////
405 
406 
407 namespace valxform {
408 
409 template<typename InIterT, typename OutTreeT, typename OpT>
411 {
412 public:
413  using InTreeT = typename InIterT::TreeT;
415  using OutValueT = typename OutTreeT::ValueType;
416 
417  SharedOpTransformer(const InIterT& inIter, OutTreeT& outTree, OpT& op, MergePolicy merge):
418  mIsRoot(true),
419  mInputIter(inIter),
420  mInputTree(inIter.getTree()),
421  mOutputTree(&outTree),
422  mOp(op),
423  mMergePolicy(merge)
424  {
425  if (static_cast<const void*>(mInputTree) == static_cast<void*>(mOutputTree)) {
426  OPENVDB_LOG_INFO("use tools::foreach(), not transformValues(),"
427  " to transform a grid in place");
428  }
429  }
430 
431  /// Splitting constructor
433  mIsRoot(false),
434  mInputIter(other.mInputIter),
435  mInputTree(other.mInputTree),
436  mOutputTree(new OutTreeT(zeroVal<OutValueT>())),
437  mOp(other.mOp),
438  mMergePolicy(other.mMergePolicy)
439  {}
440 
442  {
443  // Delete the output tree only if it was allocated locally
444  // (the top-level output tree was supplied by the caller).
445  if (!mIsRoot) {
446  delete mOutputTree;
447  mOutputTree = nullptr;
448  }
449  }
450 
451  void process(bool threaded = true)
452  {
453  if (!mInputTree || !mOutputTree) return;
454 
455  IterRange range(mInputIter);
456 
457  // Independently transform elements in the iterator range,
458  // either in parallel or serially.
459  if (threaded) {
460  tbb::parallel_reduce(range, *this);
461  } else {
462  (*this)(range);
463  }
464  }
465 
466  /// Transform each element in the given range.
468  {
469  if (!mOutputTree) return;
470  typename tree::ValueAccessor<OutTreeT> outAccessor(*mOutputTree);
471  for ( ; range; ++range) {
472  mOp(range.iterator(), outAccessor);
473  }
474  }
475 
476  void join(const SharedOpTransformer& other)
477  {
478  if (mOutputTree && other.mOutputTree) {
479  mOutputTree->merge(*other.mOutputTree, mMergePolicy);
480  }
481  }
482 
483 private:
484  bool mIsRoot;
485  InIterT mInputIter;
486  const InTreeT* mInputTree;
487  OutTreeT* mOutputTree;
488  OpT& mOp;
489  MergePolicy mMergePolicy;
490 }; // class SharedOpTransformer
491 
492 
493 template<typename InIterT, typename OutTreeT, typename OpT>
495 {
496 public:
497  using InTreeT = typename InIterT::TreeT;
499  using OutValueT = typename OutTreeT::ValueType;
500 
501  CopyableOpTransformer(const InIterT& inIter, OutTreeT& outTree,
502  const OpT& op, MergePolicy merge):
503  mIsRoot(true),
504  mInputIter(inIter),
505  mInputTree(inIter.getTree()),
506  mOutputTree(&outTree),
507  mOp(op),
508  mOrigOp(&op),
509  mMergePolicy(merge)
510  {
511  if (static_cast<const void*>(mInputTree) == static_cast<void*>(mOutputTree)) {
512  OPENVDB_LOG_INFO("use tools::foreach(), not transformValues(),"
513  " to transform a grid in place");
514  }
515  }
516 
517  // When splitting this task, give the subtask a copy of the original functor,
518  // not of this task's functor, which might have been modified arbitrarily.
520  mIsRoot(false),
521  mInputIter(other.mInputIter),
522  mInputTree(other.mInputTree),
523  mOutputTree(new OutTreeT(zeroVal<OutValueT>())),
524  mOp(*other.mOrigOp),
525  mOrigOp(other.mOrigOp),
526  mMergePolicy(other.mMergePolicy)
527  {}
528 
530  {
531  // Delete the output tree only if it was allocated locally
532  // (the top-level output tree was supplied by the caller).
533  if (!mIsRoot) {
534  delete mOutputTree;
535  mOutputTree = nullptr;
536  }
537  }
538 
539  void process(bool threaded = true)
540  {
541  if (!mInputTree || !mOutputTree) return;
542 
543  IterRange range(mInputIter);
544 
545  // Independently transform elements in the iterator range,
546  // either in parallel or serially.
547  if (threaded) {
548  tbb::parallel_reduce(range, *this);
549  } else {
550  (*this)(range);
551  }
552  }
553 
554  /// Transform each element in the given range.
556  {
557  if (!mOutputTree) return;
558  typename tree::ValueAccessor<OutTreeT> outAccessor(*mOutputTree);
559  for ( ; range; ++range) {
560  mOp(range.iterator(), outAccessor);
561  }
562  }
563 
564  void join(const CopyableOpTransformer& other)
565  {
566  if (mOutputTree && other.mOutputTree) {
567  mOutputTree->merge(*other.mOutputTree, mMergePolicy);
568  }
569  }
570 
571 private:
572  bool mIsRoot;
573  InIterT mInputIter;
574  const InTreeT* mInputTree;
575  OutTreeT* mOutputTree;
576  OpT mOp; // copy of original functor
577  OpT const * const mOrigOp; // pointer to original functor
578  MergePolicy mMergePolicy;
579 }; // class CopyableOpTransformer
580 
581 } // namespace valxform
582 
583 
584 ////////////////////////////////////////
585 
586 
587 template<typename InIterT, typename OutGridT, typename XformOp>
588 inline void
589 transformValues(const InIterT& inIter, OutGridT& outGrid, XformOp& op,
590  bool threaded, bool shared, MergePolicy merge)
591 {
592  using Adapter = TreeAdapter<OutGridT>;
593  using OutTreeT = typename Adapter::TreeType;
594  if (shared) {
596  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
597  proc.process(threaded);
598  } else {
600  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
601  proc.process(threaded);
602  }
603 }
604 
605 #ifndef _WIN32
606 template<typename InIterT, typename OutGridT, typename XformOp>
607 inline void
608 transformValues(const InIterT& inIter, OutGridT& outGrid, const XformOp& op,
609  bool threaded, bool /*share*/, MergePolicy merge)
610 {
611  using Adapter = TreeAdapter<OutGridT>;
612  using OutTreeT = typename Adapter::TreeType;
613  // Const ops are shared across threads, not copied.
615  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
616  proc.process(threaded);
617 }
618 #endif
619 
620 
621 ////////////////////////////////////////
622 
623 
624 namespace valxform {
625 
626 template<typename IterT, typename OpT>
628 {
629 public:
631 
632  // The root task makes a const copy of the original functor (mOrigOp)
633  // and keeps a pointer to the original functor (mOp), which it then modifies.
634  // Each subtask keeps a const pointer to the root task's mOrigOp
635  // and makes and then modifies a non-const copy (mOp) of it.
636  OpAccumulator(const IterT& iter, OpT& op):
637  mIsRoot(true),
638  mIter(iter),
639  mOp(&op),
640  mOrigOp(new OpT(op))
641  {}
642 
643  // When splitting this task, give the subtask a copy of the original functor,
644  // not of this task's functor, which might have been modified arbitrarily.
646  mIsRoot(false),
647  mIter(other.mIter),
648  mOp(new OpT(*other.mOrigOp)),
649  mOrigOp(other.mOrigOp)
650  {}
651 
652  ~OpAccumulator() { if (mIsRoot) delete mOrigOp; else delete mOp; }
653 
654  void process(bool threaded = true)
655  {
656  IterRange range(mIter);
657  if (threaded) {
658  tbb::parallel_reduce(range, *this);
659  } else {
660  (*this)(range);
661  }
662  }
663 
664  void operator()(IterRange& r) { for ( ; r; ++r) (*mOp)(r.iterator()); }
665 
666  void join(OpAccumulator& other) { mOp->join(*other.mOp); }
667 
668 private:
669  const bool mIsRoot;
670  const IterT mIter;
671  OpT* mOp; // pointer to original functor, which might get modified
672  OpT const * const mOrigOp; // const copy of original functor
673 }; // class OpAccumulator
674 
675 } // namespace valxform
676 
677 
678 ////////////////////////////////////////
679 
680 
681 template<typename IterT, typename XformOp>
682 inline void
683 accumulate(const IterT& iter, XformOp& op, bool threaded)
684 {
685  typename valxform::OpAccumulator<IterT, XformOp> proc(iter, op);
686  proc.process(threaded);
687 }
688 
689 
690 ////////////////////////////////////////
691 
692 
693 // Explicit Template Instantiation
694 
695 #ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION
696 
697 #ifdef OPENVDB_INSTANTIATE_VALUETRANSFORMER
699 #endif
700 
701 #define _FUNCTION(TreeT) \
702  void setValueOnMin(TreeT&, const Coord&, const TreeT::ValueType&)
704 #undef _FUNCTION
705 
706 #define _FUNCTION(TreeT) \
707  void setValueOnMax(TreeT&, const Coord&, const TreeT::ValueType&)
709 #undef _FUNCTION
710 
711 #define _FUNCTION(TreeT) \
712  void setValueOnSum(TreeT&, const Coord&, const TreeT::ValueType&)
714 #undef _FUNCTION
715 
716 #define _FUNCTION(TreeT) \
717  void setValueOnMult(TreeT&, const Coord&, const TreeT::ValueType&)
719 #undef _FUNCTION
720 
721 #endif // OPENVDB_USE_EXPLICIT_INSTANTIATION
722 
723 
724 } // namespace tools
725 } // namespace OPENVDB_VERSION_NAME
726 } // namespace openvdb
727 
728 #endif // OPENVDB_TOOLS_VALUETRANSFORMER_HAS_BEEN_INCLUDED
void parallel_for(int64_t start, int64_t end, std::function< void(int64_t index)> &&task, parallel_options opt=parallel_options(0, Split_Y, 1))
Definition: parallel.h:127
CopyableOpTransformer(const InIterT &inIter, OutTreeT &outTree, const OpT &op, MergePolicy merge)
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:207
SharedOpTransformer(SharedOpTransformer &other, tbb::split)
Splitting constructor.
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:1064
void operator()(IterRange &range) const
Transform each element in the given range.
void setValueOnMax(TreeT &tree, const Coord &xyz, const typename TreeT::ValueType &value)
Set the value of the voxel at the given coordinates in tree to the maximum of its current value and v...
void setValueOnMult(TreeT &tree, const Coord &xyz, const typename TreeT::ValueType &value)
Set the value of the voxel at the given coordinates in tree to the product of its current value and v...
void setValueOnMin(TreeT &tree, const Coord &xyz, const typename TreeT::ValueType &value)
Set the value of the voxel at the given coordinates in tree to the minimum of its current value and v...
const GLdouble * v
Definition: glcorearb.h:837
void setValueOnSum(TreeT &tree, const Coord &xyz, const typename TreeT::ValueType &value)
Set the value of the voxel at the given coordinates in tree to the sum of its current value and value...
#define OPENVDB_VOLUME_TREE_INSTANTIATE(Function)
Definition: version.h:155
void operator()(IterRange &range)
Transform each element in the given range.
GLuint GLfloat * val
Definition: glcorearb.h:1608
void accumulate(const IterT &iter, XformOp &op, bool threaded=true)
void transformValues(const InIterT &inIter, OutGridT &outGrid, XformOp &op, bool threaded=true, bool shareOp=true, MergePolicy merge=MERGE_ACTIVE_STATES)
class OCIOEXPORT Processor
#define OPENVDB_LOG_INFO(mesg)
Definition: logging.h:276
GLenum GLint * range
Definition: glcorearb.h:1925
Definition: core.h:1131
void OIIO_UTIL_API split(string_view str, std::vector< string_view > &result, string_view sep=string_view(), int maxsplit=-1)
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:69
GLboolean r
Definition: glcorearb.h:1222
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:119
SharedOpTransformer(const InIterT &inIter, OutTreeT &outTree, OpT &op, MergePolicy merge)