OpenVDB: PointMask.h Source File

OpenVDB 7.0.0

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