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 
38 
39 namespace openvdb {
41 namespace OPENVDB_VERSION_NAME {
42 namespace tools {
43 
44 /// Iterate over a grid and at each step call @c op(iter).
45 /// @param iter an iterator over a grid or its tree (@c Grid::ValueOnCIter,
46 /// @c Tree::NodeIter, etc.)
47 /// @param op a functor of the form <tt>void op(const IterT&)</tt>, where @c IterT is
48 /// the type of @a iter
49 /// @param threaded if true, transform multiple values of the grid in parallel
50 /// @param shareOp if true and @a threaded is true, all threads use the same functor;
51 /// otherwise, each thread gets its own copy of the @e original functor
52 ///
53 /// @par Example:
54 /// Multiply all values (both set and unset) of a scalar, floating-point grid by two.
55 /// @code
56 /// struct Local {
57 /// static inline void op(const FloatGrid::ValueAllIter& iter) {
58 /// iter.setValue(*iter * 2);
59 /// }
60 /// };
61 /// FloatGrid grid = ...;
62 /// tools::foreach(grid.beginValueAll(), Local::op);
63 /// @endcode
64 ///
65 /// @par Example:
66 /// Rotate all active vectors of a vector grid by 45 degrees about the y axis.
67 /// @code
68 /// namespace {
69 /// struct MatMul {
70 /// math::Mat3s M;
71 /// MatMul(const math::Mat3s& mat): M(mat) {}
72 /// inline void operator()(const VectorGrid::ValueOnIter& iter) const {
73 /// iter.setValue(M.transform(*iter));
74 /// }
75 /// };
76 /// }
77 /// {
78 /// VectorGrid grid = ...;
79 /// tools::foreach(grid.beginValueOn(),
80 /// MatMul(math::rotation<math::Mat3s>(math::Y, M_PI_4)));
81 /// }
82 /// @endcode
83 ///
84 /// @note For more complex operations that require finer control over threading,
85 /// consider using @c tbb::parallel_for() or @c tbb::parallel_reduce() in conjunction
86 /// with a tree::IteratorRange that wraps a grid or tree iterator.
87 template<typename IterT, typename XformOp>
88 inline void foreach(const IterT& iter, XformOp& op,
89  bool threaded = true, bool shareOp = true);
90 
91 template<typename IterT, typename XformOp>
92 inline void foreach(const IterT& iter, const XformOp& op,
93  bool threaded = true, bool shareOp = true);
94 
95 
96 /// Iterate over a grid and at each step call <tt>op(iter, accessor)</tt> to
97 /// populate (via the accessor) the given output grid, whose @c ValueType
98 /// need not be the same as the input grid's.
99 /// @param inIter a non-<tt>const</tt> or (preferably) @c const iterator over an
100 /// input grid or its tree (@c Grid::ValueOnCIter, @c Tree::NodeIter, etc.)
101 /// @param outGrid an empty grid to be populated
102 /// @param op a functor of the form
103 /// <tt>void op(const InIterT&, OutGridT::ValueAccessor&)</tt>,
104 /// where @c InIterT is the type of @a inIter
105 /// @param threaded if true, transform multiple values of the input grid in parallel
106 /// @param shareOp if true and @a threaded is true, all threads use the same functor;
107 /// otherwise, each thread gets its own copy of the @e original functor
108 /// @param merge how to merge intermediate results from multiple threads (see Types.h)
109 ///
110 /// @par Example:
111 /// Populate a scalar floating-point grid with the lengths of the vectors from all
112 /// active voxels of a vector-valued input grid.
113 /// @code
114 /// struct Local {
115 /// static void op(
116 /// const Vec3fGrid::ValueOnCIter& iter,
117 /// FloatGrid::ValueAccessor& accessor)
118 /// {
119 /// if (iter.isVoxelValue()) { // set a single voxel
120 /// accessor.setValue(iter.getCoord(), iter->length());
121 /// } else { // fill an entire tile
122 /// CoordBBox bbox;
123 /// iter.getBoundingBox(bbox);
124 /// accessor.getTree()->fill(bbox, iter->length());
125 /// }
126 /// }
127 /// };
128 /// Vec3fGrid inGrid = ...;
129 /// FloatGrid outGrid;
130 /// tools::transformValues(inGrid.cbeginValueOn(), outGrid, Local::op);
131 /// @endcode
132 ///
133 /// @note For more complex operations that require finer control over threading,
134 /// consider using @c tbb::parallel_for() or @c tbb::parallel_reduce() in conjunction
135 /// with a tree::IteratorRange that wraps a grid or tree iterator.
136 template<typename InIterT, typename OutGridT, typename XformOp>
137 inline void transformValues(const InIterT& inIter, OutGridT& outGrid,
138  XformOp& op, bool threaded = true, bool shareOp = true,
140 
141 #ifndef _MSC_VER
142 template<typename InIterT, typename OutGridT, typename XformOp>
143 inline void transformValues(const InIterT& inIter, OutGridT& outGrid,
144  const XformOp& op, bool threaded = true, bool shareOp = true,
146 #endif
147 
148 
149 /// Iterate over a grid and at each step call @c op(iter). If threading is enabled,
150 /// call @c op.join(otherOp) to accumulate intermediate results from pairs of threads.
151 /// @param iter an iterator over a grid or its tree (@c Grid::ValueOnCIter,
152 /// @c Tree::NodeIter, etc.)
153 /// @param op a functor with a join method of the form <tt>void join(XformOp&)</tt>
154 /// and a call method of the form <tt>void op(const IterT&)</tt>,
155 /// where @c IterT is the type of @a iter
156 /// @param threaded if true, transform multiple values of the grid in parallel
157 /// @note If @a threaded is true, each thread gets its own copy of the @e original functor.
158 /// The order in which threads are joined is unspecified.
159 /// @note If @a threaded is false, the join method is never called.
160 ///
161 /// @par Example:
162 /// Compute the average of the active values of a scalar, floating-point grid
163 /// using the math::Stats class.
164 /// @code
165 /// namespace {
166 /// struct Average {
167 /// math::Stats stats;
168 ///
169 /// // Accumulate voxel and tile values into this functor's Stats object.
170 /// inline void operator()(const FloatGrid::ValueOnCIter& iter) {
171 /// if (iter.isVoxelValue()) stats.add(*iter);
172 /// else stats.add(*iter, iter.getVoxelCount());
173 /// }
174 ///
175 /// // Accumulate another functor's Stats object into this functor's.
176 /// inline void join(Average& other) { stats.add(other.stats); }
177 ///
178 /// // Return the cumulative result.
179 /// inline double average() const { return stats.mean(); }
180 /// };
181 /// }
182 /// {
183 /// FloatGrid grid = ...;
184 /// Average op;
185 /// tools::accumulate(grid.cbeginValueOn(), op);
186 /// double average = op.average();
187 /// }
188 /// @endcode
189 ///
190 /// @note For more complex operations that require finer control over threading,
191 /// consider using @c tbb::parallel_for() or @c tbb::parallel_reduce() in conjunction
192 /// with a tree::IteratorRange that wraps a grid or tree iterator.
193 template<typename IterT, typename XformOp>
194 inline void accumulate(const IterT& iter, XformOp& op, bool threaded = true);
195 
196 
197 /// @brief Set the value of the voxel at the given coordinates in @a tree to
198 /// the minimum of its current value and @a value, and mark the voxel as active.
199 /// @details This is typically significantly faster than calling getValue()
200 /// followed by setValueOn().
201 /// @note @a TreeT can be either a Tree or a ValueAccessor.
202 template<typename TreeT>
203 inline void setValueOnMin(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
204 
205 /// @brief Set the value of the voxel at the given coordinates in @a tree to
206 /// the maximum of its current value and @a value, and mark the voxel as active.
207 /// @details This is typically significantly faster than calling getValue()
208 /// followed by setValueOn().
209 /// @note @a TreeT can be either a Tree or a ValueAccessor.
210 template<typename TreeT>
211 inline void setValueOnMax(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
212 
213 /// @brief Set the value of the voxel at the given coordinates in @a tree to
214 /// the sum of its current value and @a value, and mark the voxel as active.
215 /// @details This is typically significantly faster than calling getValue()
216 /// followed by setValueOn().
217 /// @note @a TreeT can be either a Tree or a ValueAccessor.
218 template<typename TreeT>
219 inline void setValueOnSum(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
220 
221 /// @brief Set the value of the voxel at the given coordinates in @a tree to
222 /// the product of its current value and @a value, and mark the voxel as active.
223 /// @details This is typically significantly faster than calling getValue()
224 /// followed by setValueOn().
225 /// @note @a TreeT can be either a Tree or a ValueAccessor.
226 template<typename TreeT>
227 inline void setValueOnMult(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value);
228 
229 
230 ////////////////////////////////////////
231 
232 
233 namespace valxform {
234 
235 template<typename ValueType>
236 struct MinOp {
237  const ValueType val;
238  MinOp(const ValueType& v): val(v) {}
239  inline void operator()(ValueType& v) const { v = std::min<ValueType>(v, val); }
240 };
241 
242 template<typename ValueType>
243 struct MaxOp {
244  const ValueType val;
245  MaxOp(const ValueType& v): val(v) {}
246  inline void operator()(ValueType& v) const { v = std::max<ValueType>(v, val); }
247 };
248 
249 template<typename ValueType>
250 struct SumOp {
251  const ValueType val;
252  SumOp(const ValueType& v): val(v) {}
253  inline void operator()(ValueType& v) const { v += val; }
254 };
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 }
273 
274 
275 template<typename TreeT>
276 inline void
277 setValueOnMin(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
278 {
279  tree.modifyValue(xyz, valxform::MinOp<typename TreeT::ValueType>(value));
280 }
281 
282 
283 template<typename TreeT>
284 inline void
285 setValueOnMax(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
286 {
287  tree.modifyValue(xyz, valxform::MaxOp<typename TreeT::ValueType>(value));
288 }
289 
290 
291 template<typename TreeT>
292 inline void
293 setValueOnSum(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
294 {
295  tree.modifyValue(xyz, valxform::SumOp<typename TreeT::ValueType>(value));
296 }
297 
298 
299 template<typename TreeT>
300 inline void
301 setValueOnMult(TreeT& tree, const Coord& xyz, const typename TreeT::ValueType& value)
302 {
303  tree.modifyValue(xyz, valxform::MultOp<typename TreeT::ValueType>(value));
304 }
305 
306 
307 ////////////////////////////////////////
308 
309 
310 namespace valxform {
311 
312 template<typename IterT, typename OpT>
314 {
315 public:
317 
318  SharedOpApplier(const IterT& iter, OpT& op): mIter(iter), mOp(op) {}
319 
320  void process(bool threaded = true)
321  {
322  IterRange range(mIter);
323  if (threaded) {
324  tbb::parallel_for(range, *this);
325  } else {
326  (*this)(range);
327  }
328  }
329 
330  void operator()(IterRange& r) const { for ( ; r; ++r) mOp(r.iterator()); }
331 
332 private:
333  IterT mIter;
334  OpT& mOp;
335 };
336 
337 
338 template<typename IterT, typename OpT>
340 {
341 public:
343 
344  CopyableOpApplier(const IterT& iter, const OpT& op): mIter(iter), mOp(op), mOrigOp(&op) {}
345 
346  // When splitting this task, give the subtask a copy of the original functor,
347  // not of this task's functor, which might have been modified arbitrarily.
349  mIter(other.mIter), mOp(*other.mOrigOp), mOrigOp(other.mOrigOp) {}
350 
351  void process(bool threaded = true)
352  {
353  IterRange range(mIter);
354  if (threaded) {
355  tbb::parallel_for(range, *this);
356  } else {
357  (*this)(range);
358  }
359  }
360 
361  void operator()(IterRange& r) const { for ( ; r; ++r) mOp(r.iterator()); }
362 
363 private:
364  IterT mIter;
365  OpT mOp; // copy of original functor
366  OpT const * const mOrigOp; // pointer to original functor
367 };
368 
369 } // namespace valxform
370 
371 
372 template<typename IterT, typename XformOp>
373 inline void
374 foreach(const IterT& iter, XformOp& op, bool threaded, bool shared)
375 {
376  if (shared) {
377  typename valxform::SharedOpApplier<IterT, XformOp> proc(iter, op);
378  proc.process(threaded);
379  } else {
380  using Processor = typename valxform::CopyableOpApplier<IterT, XformOp>;
381  Processor proc(iter, op);
382  proc.process(threaded);
383  }
384 }
385 
386 template<typename IterT, typename XformOp>
387 inline void
388 foreach(const IterT& iter, const XformOp& op, bool threaded, bool /*shared*/)
389 {
390  // Const ops are shared across threads, not copied.
391  typename valxform::SharedOpApplier<IterT, const XformOp> proc(iter, op);
392  proc.process(threaded);
393 }
394 
395 
396 ////////////////////////////////////////
397 
398 
399 namespace valxform {
400 
401 template<typename InIterT, typename OutTreeT, typename OpT>
403 {
404 public:
405  using InTreeT = typename InIterT::TreeT;
407  using OutValueT = typename OutTreeT::ValueType;
408 
409  SharedOpTransformer(const InIterT& inIter, OutTreeT& outTree, OpT& op, MergePolicy merge):
410  mIsRoot(true),
411  mInputIter(inIter),
412  mInputTree(inIter.getTree()),
413  mOutputTree(&outTree),
414  mOp(op),
415  mMergePolicy(merge)
416  {
417  if (static_cast<const void*>(mInputTree) == static_cast<void*>(mOutputTree)) {
418  OPENVDB_LOG_INFO("use tools::foreach(), not transformValues(),"
419  " to transform a grid in place");
420  }
421  }
422 
423  /// Splitting constructor
425  mIsRoot(false),
426  mInputIter(other.mInputIter),
427  mInputTree(other.mInputTree),
428  mOutputTree(new OutTreeT(zeroVal<OutValueT>())),
429  mOp(other.mOp),
430  mMergePolicy(other.mMergePolicy)
431  {}
432 
434  {
435  // Delete the output tree only if it was allocated locally
436  // (the top-level output tree was supplied by the caller).
437  if (!mIsRoot) {
438  delete mOutputTree;
439  mOutputTree = nullptr;
440  }
441  }
442 
443  void process(bool threaded = true)
444  {
445  if (!mInputTree || !mOutputTree) return;
446 
447  IterRange range(mInputIter);
448 
449  // Independently transform elements in the iterator range,
450  // either in parallel or serially.
451  if (threaded) {
452  tbb::parallel_reduce(range, *this);
453  } else {
454  (*this)(range);
455  }
456  }
457 
458  /// Transform each element in the given range.
460  {
461  if (!mOutputTree) return;
462  typename tree::ValueAccessor<OutTreeT> outAccessor(*mOutputTree);
463  for ( ; range; ++range) {
464  mOp(range.iterator(), outAccessor);
465  }
466  }
467 
468  void join(const SharedOpTransformer& other)
469  {
470  if (mOutputTree && other.mOutputTree) {
471  mOutputTree->merge(*other.mOutputTree, mMergePolicy);
472  }
473  }
474 
475 private:
476  bool mIsRoot;
477  InIterT mInputIter;
478  const InTreeT* mInputTree;
479  OutTreeT* mOutputTree;
480  OpT& mOp;
481  MergePolicy mMergePolicy;
482 }; // class SharedOpTransformer
483 
484 
485 template<typename InIterT, typename OutTreeT, typename OpT>
487 {
488 public:
489  using InTreeT = typename InIterT::TreeT;
491  using OutValueT = typename OutTreeT::ValueType;
492 
493  CopyableOpTransformer(const InIterT& inIter, OutTreeT& outTree,
494  const OpT& op, MergePolicy merge):
495  mIsRoot(true),
496  mInputIter(inIter),
497  mInputTree(inIter.getTree()),
498  mOutputTree(&outTree),
499  mOp(op),
500  mOrigOp(&op),
501  mMergePolicy(merge)
502  {
503  if (static_cast<const void*>(mInputTree) == static_cast<void*>(mOutputTree)) {
504  OPENVDB_LOG_INFO("use tools::foreach(), not transformValues(),"
505  " to transform a grid in place");
506  }
507  }
508 
509  // When splitting this task, give the subtask a copy of the original functor,
510  // not of this task's functor, which might have been modified arbitrarily.
512  mIsRoot(false),
513  mInputIter(other.mInputIter),
514  mInputTree(other.mInputTree),
515  mOutputTree(new OutTreeT(zeroVal<OutValueT>())),
516  mOp(*other.mOrigOp),
517  mOrigOp(other.mOrigOp),
518  mMergePolicy(other.mMergePolicy)
519  {}
520 
522  {
523  // Delete the output tree only if it was allocated locally
524  // (the top-level output tree was supplied by the caller).
525  if (!mIsRoot) {
526  delete mOutputTree;
527  mOutputTree = nullptr;
528  }
529  }
530 
531  void process(bool threaded = true)
532  {
533  if (!mInputTree || !mOutputTree) return;
534 
535  IterRange range(mInputIter);
536 
537  // Independently transform elements in the iterator range,
538  // either in parallel or serially.
539  if (threaded) {
540  tbb::parallel_reduce(range, *this);
541  } else {
542  (*this)(range);
543  }
544  }
545 
546  /// Transform each element in the given range.
548  {
549  if (!mOutputTree) return;
550  typename tree::ValueAccessor<OutTreeT> outAccessor(*mOutputTree);
551  for ( ; range; ++range) {
552  mOp(range.iterator(), outAccessor);
553  }
554  }
555 
556  void join(const CopyableOpTransformer& other)
557  {
558  if (mOutputTree && other.mOutputTree) {
559  mOutputTree->merge(*other.mOutputTree, mMergePolicy);
560  }
561  }
562 
563 private:
564  bool mIsRoot;
565  InIterT mInputIter;
566  const InTreeT* mInputTree;
567  OutTreeT* mOutputTree;
568  OpT mOp; // copy of original functor
569  OpT const * const mOrigOp; // pointer to original functor
570  MergePolicy mMergePolicy;
571 }; // class CopyableOpTransformer
572 
573 } // namespace valxform
574 
575 
576 ////////////////////////////////////////
577 
578 
579 template<typename InIterT, typename OutGridT, typename XformOp>
580 inline void
581 transformValues(const InIterT& inIter, OutGridT& outGrid, XformOp& op,
582  bool threaded, bool shared, MergePolicy merge)
583 {
584  using Adapter = TreeAdapter<OutGridT>;
585  using OutTreeT = typename Adapter::TreeType;
586  if (shared) {
588  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
589  proc.process(threaded);
590  } else {
592  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
593  proc.process(threaded);
594  }
595 }
596 
597 #ifndef _MSC_VER
598 template<typename InIterT, typename OutGridT, typename XformOp>
599 inline void
600 transformValues(const InIterT& inIter, OutGridT& outGrid, const XformOp& op,
601  bool threaded, bool /*share*/, MergePolicy merge)
602 {
603  using Adapter = TreeAdapter<OutGridT>;
604  using OutTreeT = typename Adapter::TreeType;
605  // Const ops are shared across threads, not copied.
607  Processor proc(inIter, Adapter::tree(outGrid), op, merge);
608  proc.process(threaded);
609 }
610 #endif
611 
612 
613 ////////////////////////////////////////
614 
615 
616 namespace valxform {
617 
618 template<typename IterT, typename OpT>
620 {
621 public:
623 
624  // The root task makes a const copy of the original functor (mOrigOp)
625  // and keeps a pointer to the original functor (mOp), which it then modifies.
626  // Each subtask keeps a const pointer to the root task's mOrigOp
627  // and makes and then modifies a non-const copy (mOp) of it.
628  OpAccumulator(const IterT& iter, OpT& op):
629  mIsRoot(true),
630  mIter(iter),
631  mOp(&op),
632  mOrigOp(new OpT(op))
633  {}
634 
635  // When splitting this task, give the subtask a copy of the original functor,
636  // not of this task's functor, which might have been modified arbitrarily.
638  mIsRoot(false),
639  mIter(other.mIter),
640  mOp(new OpT(*other.mOrigOp)),
641  mOrigOp(other.mOrigOp)
642  {}
643 
644  ~OpAccumulator() { if (mIsRoot) delete mOrigOp; else delete mOp; }
645 
646  void process(bool threaded = true)
647  {
648  IterRange range(mIter);
649  if (threaded) {
650  tbb::parallel_reduce(range, *this);
651  } else {
652  (*this)(range);
653  }
654  }
655 
656  void operator()(IterRange& r) { for ( ; r; ++r) (*mOp)(r.iterator()); }
657 
658  void join(OpAccumulator& other) { mOp->join(*other.mOp); }
659 
660 private:
661  const bool mIsRoot;
662  const IterT mIter;
663  OpT* mOp; // pointer to original functor, which might get modified
664  OpT const * const mOrigOp; // const copy of original functor
665 }; // class OpAccumulator
666 
667 } // namespace valxform
668 
669 
670 ////////////////////////////////////////
671 
672 
673 template<typename IterT, typename XformOp>
674 inline void
675 accumulate(const IterT& iter, XformOp& op, bool threaded)
676 {
677  typename valxform::OpAccumulator<IterT, XformOp> proc(iter, op);
678  proc.process(threaded);
679 }
680 
681 } // namespace tools
682 } // namespace OPENVDB_VERSION_NAME
683 } // namespace openvdb
684 
685 #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:153
GLenum GLint * range
Definition: glew.h:3500
GLuint const GLfloat * val
Definition: glew.h:2794
CopyableOpTransformer(const InIterT &inIter, OutTreeT &outTree, const OpT &op, MergePolicy merge)
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:166
const GLdouble * v
Definition: glew.h:1391
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:1068
void operator()(IterRange &range) const
Transform each element in the given range.
void OIIO_API split(string_view str, std::vector< string_view > &result, string_view sep=string_view(), int maxsplit=-1)
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...
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...
void operator()(IterRange &range)
Transform each element in the given range.
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)
#define OPENVDB_LOG_INFO(mesg)
Definition: logging.h:273
GLdouble GLdouble GLdouble r
Definition: glew.h:1406
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:59
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:112
GLsizei const GLfloat * value
Definition: glew.h:1849
SharedOpTransformer(const InIterT &inIter, OutTreeT &outTree, OpT &op, MergePolicy merge)