OpenVDB  6.2.1
PointMask.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 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 
36 
37 #ifndef OPENVDB_POINTS_POINT_MASK_HAS_BEEN_INCLUDED
38 #define OPENVDB_POINTS_POINT_MASK_HAS_BEEN_INCLUDED
39 
40 #include <openvdb/openvdb.h>
41 #include <openvdb/tools/ValueTransformer.h> // valxform::SumOp
42 
43 #include "PointDataGrid.h"
44 #include "IndexFilter.h"
45 
46 #include <tbb/combinable.h>
47 
48 #include <type_traits>
49 #include <vector>
50 
51 
52 namespace openvdb {
54 namespace OPENVDB_VERSION_NAME {
55 namespace points {
56 
57 
63 template <typename PointDataGridT,
64  typename MaskT = typename PointDataGridT::template ValueConverter<bool>::Type,
65  typename FilterT = NullFilter>
66 inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
67  typename MaskT::Ptr>::type
68 convertPointsToMask(const PointDataGridT& grid,
69  const FilterT& filter = NullFilter(),
70  bool threaded = true);
71 
72 
79 template <typename PointDataGridT,
80  typename MaskT = typename PointDataGridT::template ValueConverter<bool>::Type,
81  typename FilterT = NullFilter>
82 inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
83  typename MaskT::Ptr>::type
84 convertPointsToMask(const PointDataGridT& grid,
85  const openvdb::math::Transform& transform,
86  const FilterT& filter = NullFilter(),
87  bool threaded = true);
88 
89 
92 {
93  template <typename LeafT>
94  void reset(LeafT&, size_t /*idx*/ = 0) { }
95 
96  template <typename IterT>
97  void apply(Vec3d&, IterT&) const { }
98 };
99 
102 template <typename DeformerT>
104 {
105  static const bool IndexSpace = false;
106 };
107 
108 
110 
111 
112 namespace point_mask_internal {
113 
114 template <typename LeafT>
115 void voxelSum(LeafT& leaf, const Index offset, const typename LeafT::ValueType& value)
116 {
117  leaf.modifyValue(offset, tools::valxform::SumOp<typename LeafT::ValueType>(value));
118 }
119 
120 // overload PointDataLeaf access to use setOffsetOn(), as modifyValue()
121 // is intentionally disabled to avoid accidental usage
122 
123 template <typename T, Index Log2Dim>
125  const typename PointDataLeafNode<T, Log2Dim>::ValueType& value)
126 {
127  leaf.setOffsetOn(offset, leaf.getValue(offset) + value);
128 }
129 
130 
133 template<typename GridT>
135 {
136  using CombinableT = typename tbb::combinable<GridT>;
137 
138  using TreeT = typename GridT::TreeType;
139  using LeafT = typename TreeT::LeafNodeType;
140  using ValueType = typename TreeT::ValueType;
142 
143  GridCombinerOp(GridT& grid)
144  : mTree(grid.tree()) {}
145 
146  void operator()(const GridT& grid)
147  {
148  for (auto leaf = grid.tree().beginLeaf(); leaf; ++leaf) {
149  auto* newLeaf = mTree.probeLeaf(leaf->origin());
150  if (!newLeaf) {
151  // if the leaf doesn't yet exist in the new tree, steal it
152  auto& tree = const_cast<GridT&>(grid).tree();
153  mTree.addLeaf(tree.template stealNode<LeafT>(leaf->origin(),
154  zeroVal<ValueType>(), false));
155  }
156  else {
157  // otherwise increment existing values
158  for (auto iter = leaf->cbeginValueOn(); iter; ++iter) {
159  voxelSum(*newLeaf, iter.offset(), ValueType(*iter));
160  }
161  }
162  }
163  }
164 
165 private:
166  TreeT& mTree;
167 }; // struct GridCombinerOp
168 
169 
171 template <typename GridT, typename PointDataGridT, typename FilterT>
173 {
174  using LeafT = typename GridT::TreeType::LeafNodeType;
175  using ValueT = typename LeafT::ValueType;
176 
177  PointsToScalarOp( const PointDataGridT& grid,
178  const FilterT& filter)
179  : mPointDataAccessor(grid.getConstAccessor())
180  , mFilter(filter) { }
181 
182  void operator()(LeafT& leaf, size_t /*idx*/) const {
183 
184  const auto* const pointLeaf =
185  mPointDataAccessor.probeConstLeaf(leaf.origin());
186 
187  // assumes matching topology
188  assert(pointLeaf);
189 
190  for (auto value = leaf.beginValueOn(); value; ++value) {
191  const Index64 count = points::iterCount(
192  pointLeaf->beginIndexVoxel(value.getCoord(), mFilter));
193  if (count > Index64(0)) {
194  value.setValue(ValueT(count));
195  } else {
196  // disable any empty voxels
197  value.setValueOn(false);
198  }
199  }
200  }
201 
202 private:
203  const typename PointDataGridT::ConstAccessor mPointDataAccessor;
204  const FilterT& mFilter;
205 }; // struct PointsToScalarOp
206 
207 
210 template <typename GridT, typename PointDataGridT, typename FilterT, typename DeformerT>
212 {
213  using PointDataLeafT = typename PointDataGridT::TreeType::LeafNodeType;
214  using ValueT = typename GridT::TreeType::ValueType;
217 
219  const math::Transform& sourceTransform,
220  const FilterT& filter,
221  const DeformerT& deformer,
222  CombinableT& combinable)
223  : mTargetTransform(targetTransform)
224  , mSourceTransform(sourceTransform)
225  , mFilter(filter)
226  , mDeformer(deformer)
227  , mCombinable(combinable) { }
228 
229  void operator()(const PointDataLeafT& leaf, size_t idx) const
230  {
231  DeformerT deformer(mDeformer);
232 
233  auto& grid = mCombinable.local();
234  auto& countTree = grid.tree();
236 
237  deformer.reset(leaf, idx);
238 
239  auto handle = HandleT::create(leaf.constAttributeArray("P"));
240 
241  for (auto iter = leaf.beginIndexOn(mFilter); iter; iter++) {
242 
243  // extract index-space position
244 
245  Vec3d position = handle->get(*iter) + iter.getCoord().asVec3d();
246 
247  // if deformer is designed to be used in index-space, perform deformation prior
248  // to transforming position to world-space, otherwise perform deformation afterwards
249 
251  deformer.template apply<decltype(iter)>(position, iter);
252  position = mSourceTransform.indexToWorld(position);
253  }
254  else {
255  position = mSourceTransform.indexToWorld(position);
256  deformer.template apply<decltype(iter)>(position, iter);
257  }
258 
259  // determine coord of target grid
260 
261  const Coord ijk = mTargetTransform.worldToIndexCellCentered(position);
262 
263  // increment count in target voxel
264 
265  auto* newLeaf = accessor.touchLeaf(ijk);
266  assert(newLeaf);
267  voxelSum(*newLeaf, newLeaf->coordToOffset(ijk), ValueT(1));
268  }
269  }
270 
271 private:
272  const openvdb::math::Transform& mTargetTransform;
273  const openvdb::math::Transform& mSourceTransform;
274  const FilterT& mFilter;
275  const DeformerT& mDeformer;
276  CombinableT& mCombinable;
277 }; // struct PointsToTransformedScalarOp
278 
279 
280 template<typename GridT, typename PointDataGridT, typename FilterT>
281 inline typename GridT::Ptr convertPointsToScalar(
282  const PointDataGridT& points,
283  const FilterT& filter,
284  bool threaded = true)
285 {
287 
288  using GridTreeT = typename GridT::TreeType;
289  using ValueT = typename GridTreeT::ValueType;
290 
291  // copy the topology from the points grid
292 
293  typename GridTreeT::Ptr tree(new GridTreeT(points.constTree(),
294  false, openvdb::TopologyCopy()));
295  typename GridT::Ptr grid = GridT::create(tree);
296  grid->setTransform(points.transform().copy());
297 
298  // early exit if no leaves
299 
300  if (points.constTree().leafCount() == 0) return grid;
301 
302  // early exit if mask and no group logic
303 
304  if (std::is_same<ValueT, bool>::value && filter.state() == index::ALL) return grid;
305 
306  // evaluate point group filters to produce a subset of the generated mask
307 
308  tree::LeafManager<GridTreeT> leafManager(*tree);
309 
310  if (filter.state() == index::ALL) {
311  NullFilter nullFilter;
313  points, nullFilter);
314  leafManager.foreach(pointsToScalarOp, threaded);
315  } else {
316  // build mask from points in parallel only where filter evaluates to true
318  points, filter);
319  leafManager.foreach(pointsToScalarOp, threaded);
320  }
321 
322  return grid;
323 }
324 
325 
326 template<typename GridT, typename PointDataGridT, typename FilterT, typename DeformerT>
327 inline typename GridT::Ptr convertPointsToScalar(
328  PointDataGridT& points,
329  const openvdb::math::Transform& transform,
330  const FilterT& filter,
331  const DeformerT& deformer,
332  bool threaded = true)
333 {
336 
337  using CombinerOpT = GridCombinerOp<GridT>;
338  using CombinableT = typename GridCombinerOp<GridT>::CombinableT;
339 
340  // use the simpler method if the requested transform matches the existing one
341 
342  const openvdb::math::Transform& pointsTransform = points.constTransform();
343 
344  if (transform == pointsTransform && std::is_same<NullDeformer, DeformerT>()) {
345  return convertPointsToScalar<GridT>(points, filter, threaded);
346  }
347 
348  typename GridT::Ptr grid = GridT::create();
349  grid->setTransform(transform.copy());
350 
351  // early exit if no leaves
352 
353  if (points.constTree().leafCount() == 0) return grid;
354 
355  // compute mask grids in parallel using new transform
356 
357  CombinableT combiner;
358 
359  tree::LeafManager<typename PointDataGridT::TreeType> leafManager(points.tree());
360 
361  if (filter.state() == index::ALL) {
362  NullFilter nullFilter;
364  transform, pointsTransform, nullFilter, deformer, combiner);
365  leafManager.foreach(pointsToScalarOp, threaded);
366  } else {
368  transform, pointsTransform, filter, deformer, combiner);
369  leafManager.foreach(pointsToScalarOp, threaded);
370  }
371 
372  // combine the mask grids into one
373 
374  CombinerOpT combineOp(*grid);
375  combiner.combine_each(combineOp);
376 
377  return grid;
378 }
379 
380 
381 } // namespace point_mask_internal
382 
383 
385 
386 
387 template<typename PointDataGridT, typename MaskT, typename FilterT>
388 inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
389  typename MaskT::Ptr>::type
391  const PointDataGridT& points,
392  const FilterT& filter,
393  bool threaded)
394 {
395  return point_mask_internal::convertPointsToScalar<MaskT>(
396  points, filter, threaded);
397 }
398 
399 
400 template<typename PointDataGridT, typename MaskT, typename FilterT>
401 inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
402  typename MaskT::Ptr>::type
404  const PointDataGridT& points,
405  const openvdb::math::Transform& transform,
406  const FilterT& filter,
407  bool threaded)
408 {
409  // This is safe because the PointDataGrid can only be modified by the deformer
411  auto& nonConstPoints = const_cast<typename AdapterT::NonConstGridType&>(points);
412 
413  NullDeformer deformer;
414  return point_mask_internal::convertPointsToScalar<MaskT>(
415  nonConstPoints, transform, filter, deformer, threaded);
416 }
417 
418 
420 
421 
422 // deprecated functions
423 
424 
425 template <typename PointDataGridT,
426  typename MaskT = typename PointDataGridT::template ValueConverter<bool>::Type>
428 inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
429  typename MaskT::Ptr>::type
430 convertPointsToMask(const PointDataGridT& grid,
431  const std::vector<Name>& includeGroups,
432  const std::vector<Name>& excludeGroups)
433 {
434  auto leaf = grid.tree().cbeginLeaf();
435  if (!leaf) return MaskT::create();
436  MultiGroupFilter filter(includeGroups, excludeGroups, leaf->attributeSet());
437  return convertPointsToMask(grid, filter);
438 }
439 
440 
441 template <typename PointDataGridT,
442  typename MaskT = typename PointDataGridT::template ValueConverter<bool>::Type>
444 inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool>::value,
445  typename MaskT::Ptr>::type
446 convertPointsToMask(const PointDataGridT& grid,
447  const openvdb::math::Transform& transform,
448  const std::vector<Name>& includeGroups,
449  const std::vector<Name>& excludeGroups)
450 {
451  auto leaf = grid.tree().cbeginLeaf();
452  if (!leaf) return MaskT::create();
453  MultiGroupFilter filter(includeGroups, excludeGroups, leaf->attributeSet());
454  return convertPointsToMask(grid, transform, filter);
455 }
456 
457 
458 } // namespace points
459 } // namespace OPENVDB_VERSION_NAME
460 } // namespace openvdb
461 
462 #endif // OPENVDB_POINTS_POINT_MASK_HAS_BEEN_INCLUDED
463 
464 // Copyright (c) DreamWorks Animation LLC
465 // All rights reserved. This software is distributed under the
466 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
Definition: ValueTransformer.h:277
typename GridT::TreeType::LeafNodeType LeafT
Definition: PointMask.h:174
PointsToTransformedScalarOp(const math::Transform &targetTransform, const math::Transform &sourceTransform, const FilterT &filter, const DeformerT &deformer, CombinableT &combinable)
Definition: PointMask.h:218
#define OPENVDB_DEPRECATED
Definition: Platform.h:69
typename LeafT::ValueType ValueT
Definition: PointMask.h:175
void operator()(const PointDataLeafT &leaf, size_t idx) const
Definition: PointMask.h:229
Combines multiple grids into one by stealing leaf nodes and summing voxel values This class is design...
Definition: PointMask.h:134
Compute scalar grid from PointDataGrid while evaluating the point filter.
Definition: PointMask.h:172
Definition: IndexFilter.h:164
LeafNodeT * touchLeaf(const Coord &xyz)
Return a pointer to the leaf node that contains voxel (x, y, z). If no such node exists, create one, but preserve the values and active states of all voxels.
Definition: ValueAccessor.h:386
void operator()(const GridT &grid)
Definition: PointMask.h:146
Index32 Index
Definition: Types.h:61
OPENVDB_DEPRECATED std::enable_if< std::is_same< typename MaskT::ValueType, bool >::value, typename MaskT::Ptr >::type convertPointsToMask(const PointDataGridT &grid, const openvdb::math::Transform &transform, const std::vector< Name > &includeGroups, const std::vector< Name > &excludeGroups)
Definition: PointMask.h:446
Compute scalar grid from PointDataGrid using a different transform and while evaluating the point fil...
Definition: PointMask.h:211
Vec3< double > Vec3d
Definition: Vec3.h:689
typename TreeT::ValueType ValueType
Definition: PointMask.h:140
Index filters primarily designed to be used with a FilterIndexIter.
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:750
void apply(Vec3d &, IterT &) const
Definition: PointMask.h:97
typename PointDataGridT::TreeType::LeafNodeType PointDataLeafT
Definition: PointMask.h:213
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:128
typename GridCombinerOp< GridT >::CombinableT CombinableT
Definition: PointMask.h:216
typename tbb::combinable< GridT > CombinableT
Definition: PointMask.h:136
Definition: PointDataGrid.h:212
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:77
Deformer Traits for optionally configuring deformers to be applied in index-space. The default is world-space.
Definition: PointMask.h:103
typename GridT::TreeType::ValueType ValueT
Definition: PointMask.h:214
void reset(LeafT &, size_t=0)
Definition: PointMask.h:94
Definition: Exceptions.h:40
void voxelSum(PointDataLeafNode< T, Log2Dim > &leaf, const Index offset, const typename PointDataLeafNode< T, Log2Dim >::ValueType &value)
Definition: PointMask.h:124
T ValueType
Definition: PointDataGrid.h:270
uint64_t Index64
Definition: Types.h:60
Definition: AttributeArray.h:873
GridT::Ptr convertPointsToScalar(PointDataGridT &points, const openvdb::math::Transform &transform, const FilterT &filter, const DeformerT &deformer, bool threaded=true)
Definition: PointMask.h:327
This class manages a linear array of pointers to a given tree&#39;s leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109
typename GridT::TreeType TreeT
Definition: PointMask.h:138
Definition: IndexIterator.h:70
Definition: ValueAccessor.h:220
Definition: Transform.h:66
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
This adapter allows code that is templated on a Tree type to accept either a Tree type or a Grid type...
Definition: Grid.h:1076
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:1094
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:180
void setOffsetOn(Index offset, const ValueType &val)
Definition: PointDataGrid.h:1143
No-op deformer (adheres to the deformer interface documented in PointMove.h)
Definition: PointMask.h:91
GridCombinerOp(GridT &grid)
Definition: PointMask.h:143
void operator()(LeafT &leaf, size_t) const
Definition: PointMask.h:182
PointsToScalarOp(const PointDataGridT &grid, const FilterT &filter)
Definition: PointMask.h:177
typename TreeT::LeafNodeType LeafT
Definition: PointMask.h:139
void foreach(const LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager.
Definition: LeafManager.h:523
Index64 iterCount(const IterT &iter)
Count up the number of times the iterator can iterate.
Definition: IndexIterator.h:341