@@ -27,22 +27,33 @@ OPENVDB_USE_VERSION_NAMESPACE
2727namespace OPENVDB_VERSION_NAME {
2828namespace points {
2929
30+ // / @brief Extract a Mask Tree from a Point Data Tree
31+ // / @param grid the PointDataGrid to extract the mask from.
32+ // / @param filter an optional index filter
33+ // / @param threaded enable or disable threading (threading is enabled by default)
34+ template <typename PointDataTreeT,
35+ typename MaskTreeT = typename PointDataTreeT::template ValueConverter<bool >::Type,
36+ typename FilterT = NullFilter>
37+ inline typename std::enable_if<std::is_base_of<TreeBase, PointDataTreeT>::value &&
38+ std::is_same<typename MaskTreeT::ValueType, bool >::value, typename MaskTreeT::Ptr>::type
39+ convertPointsToMask (const PointDataTreeT& tree,
40+ const FilterT& filter = NullFilter(),
41+ bool threaded = true );
3042
3143// / @brief Extract a Mask Grid from a Point Data Grid
3244// / @param grid the PointDataGrid to extract the mask from.
3345// / @param filter an optional index filter
3446// / @param threaded enable or disable threading (threading is enabled by default)
3547// / @note this method is only available for Bool Grids and Mask Grids
3648template <typename PointDataGridT,
37- typename MaskT = typename PointDataGridT::template ValueConverter<bool >::Type,
49+ typename MaskGridT = typename PointDataGridT::template ValueConverter<bool >::Type,
3850 typename FilterT = NullFilter>
39- inline typename std::enable_if<std::is_same< typename MaskT::ValueType, bool >::value,
40- typename MaskT ::Ptr>::type
51+ inline typename std::enable_if<std::is_base_of<GridBase, PointDataGridT >::value &&
52+ std::is_same< typename MaskGridT::ValueType, bool >::value, typename MaskGridT ::Ptr>::type
4153convertPointsToMask (const PointDataGridT& grid,
4254 const FilterT& filter = NullFilter(),
4355 bool threaded = true );
4456
45-
4657// / @brief Extract a Mask Grid from a Point Data Grid using a new transform
4758// / @param grid the PointDataGrid to extract the mask from.
4859// / @param transform target transform for the mask.
@@ -59,7 +70,6 @@ convertPointsToMask(const PointDataGridT& grid,
5970 const FilterT& filter = NullFilter(),
6071 bool threaded = true );
6172
62-
6373// / @brief No-op deformer (adheres to the deformer interface documented in PointMove.h)
6474struct NullDeformer
6575{
@@ -142,39 +152,42 @@ struct GridCombinerOp
142152
143153
144154// / @brief Compute scalar grid from PointDataGrid while evaluating the point filter
145- template <typename GridT , typename PointDataGridT , typename FilterT>
155+ template <typename TreeT , typename PointDataTreeT , typename FilterT>
146156struct PointsToScalarOp
147157{
148- using LeafT = typename GridT::TreeType ::LeafNodeType;
158+ using LeafT = typename TreeT ::LeafNodeType;
149159 using ValueT = typename LeafT::ValueType;
160+ // This method is also used by PointCount so ValueT may not be bool
161+ static constexpr bool IsBool =
162+ std::is_same<ValueT, bool >::value;
150163
151- PointsToScalarOp ( const PointDataGridT& grid,
152- const FilterT& filter)
153- : mPointDataAccessor (grid.getConstAccessor())
154- , mFilter (filter) { }
155-
156- void operator ()(LeafT& leaf, size_t /* idx*/ ) const {
164+ PointsToScalarOp (const PointDataTreeT& tree,
165+ const FilterT& filter)
166+ : mPointDataAccessor (tree)
167+ , mFilter (filter) {}
157168
169+ void operator ()(LeafT& leaf, size_t /* idx*/ ) const
170+ {
171+ // assumes matching topology
158172 const auto * const pointLeaf =
159173 mPointDataAccessor .probeConstLeaf (leaf.origin ());
160-
161- // assumes matching topology
162174 assert (pointLeaf);
163175
164176 for (auto value = leaf.beginValueOn (); value; ++value) {
165- const Index64 count = points::iterCount (
166- pointLeaf->beginIndexVoxel (value.getCoord (), mFilter ));
167- if (count > Index64 (0 )) {
168- value.setValue (ValueT (count));
169- } else {
170- // disable any empty voxels
171- value.setValueOn (false );
177+ const auto iter = pointLeaf->beginIndexVoxel (value.getCoord (), mFilter );
178+ if (IsBool) {
179+ if (!iter) value.setValueOn (false );
180+ }
181+ else {
182+ const Index64 count = points::iterCount (iter);
183+ if (count > Index64 (0 )) value.setValue (ValueT (count));
184+ else value.setValueOn (false );
172185 }
173186 }
174187 }
175188
176189private:
177- const typename PointDataGridT::ConstAccessor mPointDataAccessor ;
190+ const tree::ValueAccessor< const PointDataTreeT> mPointDataAccessor ;
178191 const FilterT& mFilter ;
179192}; // struct PointsToScalarOp
180193
@@ -251,56 +264,53 @@ struct PointsToTransformedScalarOp
251264}; // struct PointsToTransformedScalarOp
252265
253266
254- template <typename GridT , typename PointDataGridT , typename FilterT>
255- inline typename GridT ::Ptr convertPointsToScalar (
256- const PointDataGridT & points,
267+ template <typename TreeT , typename PointDataTreeT , typename FilterT>
268+ inline typename TreeT ::Ptr convertPointsToScalar (
269+ const PointDataTreeT & points,
257270 const FilterT& filter,
258271 bool threaded = true )
259272{
260273 using point_mask_internal::PointsToScalarOp;
261274
262- using GridTreeT = typename GridT::TreeType;
263- using ValueT = typename GridTreeT::ValueType;
275+ using ValueT = typename TreeT::ValueType;
264276
265- // copy the topology from the points grid
277+ // copy the topology from the points tree
266278
267- typename GridTreeT::Ptr tree (new GridTreeT (points.constTree (),
268- false , openvdb::TopologyCopy ()));
269- typename GridT::Ptr grid = GridT::create (tree);
270- grid->setTransform (points.transform ().copy ());
279+ typename TreeT::Ptr tree (new TreeT (/* background=*/ false ));
280+ tree->topologyUnion (points);
271281
272282 // early exit if no leaves
273283
274- if (points.constTree (). leafCount () == 0 ) return grid ;
284+ if (points.leafCount () == 0 ) return tree ;
275285
276286 // early exit if mask and no group logic
277287
278- if (std::is_same<ValueT, bool >::value && filter.state () == index::ALL) return grid ;
288+ if (std::is_same<ValueT, bool >::value && filter.state () == index::ALL) return tree ;
279289
280290 // evaluate point group filters to produce a subset of the generated mask
281291
282- tree::LeafManager<GridTreeT > leafManager (*tree);
292+ tree::LeafManager<TreeT > leafManager (*tree);
283293
284294 if (filter.state () == index::ALL) {
285295 NullFilter nullFilter;
286- PointsToScalarOp<GridT, PointDataGridT , NullFilter> pointsToScalarOp (
296+ PointsToScalarOp<TreeT, PointDataTreeT , NullFilter> pointsToScalarOp (
287297 points, nullFilter);
288298 leafManager.foreach (pointsToScalarOp, threaded);
289299 } else {
290300 // build mask from points in parallel only where filter evaluates to true
291- PointsToScalarOp<GridT, PointDataGridT , FilterT> pointsToScalarOp (
301+ PointsToScalarOp<TreeT, PointDataTreeT , FilterT> pointsToScalarOp (
292302 points, filter);
293303 leafManager.foreach (pointsToScalarOp, threaded);
294304 }
295305
296- return grid ;
306+ return tree ;
297307}
298308
299309
300310template <typename GridT, typename PointDataGridT, typename FilterT, typename DeformerT>
301311inline typename GridT::Ptr convertPointsToScalar (
302312 PointDataGridT& points,
303- const openvdb:: math::Transform& transform,
313+ const math::Transform& transform,
304314 const FilterT& filter,
305315 const DeformerT& deformer,
306316 bool threaded = true )
@@ -311,17 +321,21 @@ inline typename GridT::Ptr convertPointsToScalar(
311321 using CombinerOpT = GridCombinerOp<GridT>;
312322 using CombinableT = typename GridCombinerOp<GridT>::CombinableT;
313323
324+ typename GridT::Ptr grid = GridT::create ();
325+ grid->setTransform (transform.copy ());
326+
314327 // use the simpler method if the requested transform matches the existing one
315328
316- const openvdb:: math::Transform& pointsTransform = points.constTransform ();
329+ const math::Transform& pointsTransform = points.constTransform ();
317330
318331 if (transform == pointsTransform && std::is_same<NullDeformer, DeformerT>()) {
319- return convertPointsToScalar<GridT>(points, filter, threaded);
332+ using TreeT = typename GridT::TreeType;
333+ typename TreeT::Ptr tree =
334+ convertPointsToScalar<TreeT>(points.tree (), filter, threaded);
335+ grid->setTree (tree);
336+ return grid;
320337 }
321338
322- typename GridT::Ptr grid = GridT::create ();
323- grid->setTransform (transform.copy ());
324-
325339 // early exit if no leaves
326340
327341 if (points.constTree ().leafCount () == 0 ) return grid;
@@ -359,16 +373,36 @@ inline typename GridT::Ptr convertPointsToScalar(
359373// //////////////////////////////////////
360374
361375
362- template <typename PointDataGridT, typename MaskT, typename FilterT>
363- inline typename std::enable_if<std::is_same<typename MaskT::ValueType, bool >::value,
364- typename MaskT::Ptr>::type
376+ template <typename PointDataTreeT, typename MaskTreeT, typename FilterT>
377+ inline typename std::enable_if<std::is_base_of<TreeBase, PointDataTreeT>::value &&
378+ std::is_same<typename MaskTreeT::ValueType, bool >::value, typename MaskTreeT::Ptr>::type
379+ convertPointsToMask (const PointDataTreeT& tree,
380+ const FilterT& filter,
381+ bool threaded)
382+ {
383+ return point_mask_internal::convertPointsToScalar<MaskTreeT>(
384+ tree, filter, threaded);
385+ }
386+
387+
388+ template <typename PointDataGridT, typename MaskGridT, typename FilterT>
389+ inline typename std::enable_if<std::is_base_of<GridBase, PointDataGridT>::value &&
390+ std::is_same<typename MaskGridT::ValueType, bool >::value, typename MaskGridT::Ptr>::type
365391convertPointsToMask (
366392 const PointDataGridT& points,
367393 const FilterT& filter,
368394 bool threaded)
369395{
370- return point_mask_internal::convertPointsToScalar<MaskT>(
371- points, filter, threaded);
396+ using PointDataTreeT = typename PointDataGridT::TreeType;
397+ using MaskTreeT = typename MaskGridT::TreeType;
398+
399+ typename MaskTreeT::Ptr tree =
400+ convertPointsToMask<PointDataTreeT, MaskTreeT, FilterT>
401+ (points.tree (), filter, threaded);
402+
403+ typename MaskGridT::Ptr grid (new MaskGridT (tree));
404+ grid->setTransform (points.transform ().copy ());
405+ return grid;
372406}
373407
374408
0 commit comments