OpenVDB: PointMask.h Source File

OpenVDB 6.1.0

PointMask.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2018 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 {
53 OPENVDB_USE_VERSION_NAMESPACE
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
91 struct NullDeformer
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>
103 struct DeformerTraits
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>
124 void voxelSum(PointDataLeafNode<T, Log2Dim>& leaf, const Index offset,
125 const typename PointDataLeafNode<T, Log2Dim>::ValueType& value)
126 {
127 leaf.setOffsetOn(offset, leaf.getValue(offset) + value);
128 }
129
130
133 template<typename GridT>
134 struct GridCombinerOp
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;
141 using SumOp = tools::valxform::SumOp<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>
172 struct PointsToScalarOp
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>
211 struct PointsToTransformedScalarOp
212 {
213 using PointDataLeafT = typename PointDataGridT::TreeType::LeafNodeType;
214 using ValueT = typename GridT::TreeType::ValueType;
215 using HandleT = AttributeHandle<Vec3f>;
216 using CombinableT = typename GridCombinerOp<GridT>::CombinableT;
217
218 PointsToTransformedScalarOp(const math::Transform& targetTransform,
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();
235 tree::ValueAccessor<typename GridT::TreeType> accessor(countTree);
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
250 if (DeformerTraits<DeformerT>::IndexSpace) {
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 {
286 using point_mask_internal::PointsToScalarOp;
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;
312 PointsToScalarOp<GridT, PointDataGridT, NullFilter> pointsToScalarOp(
313 points, nullFilter);
314 leafManager.foreach(pointsToScalarOp, threaded);
315 } else {
316 // build mask from points in parallel only where filter evaluates to true
317 PointsToScalarOp<GridT, PointDataGridT, FilterT> pointsToScalarOp(
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 {
334 using point_mask_internal::PointsToTransformedScalarOp;
335 using point_mask_internal::GridCombinerOp;
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;
363 PointsToTransformedScalarOp<GridT, PointDataGridT, NullFilter, DeformerT> pointsToScalarOp(
364 transform, pointsTransform, nullFilter, deformer, combiner);
365 leafManager.foreach(pointsToScalarOp, threaded);
366 } else {
367 PointsToTransformedScalarOp<GridT, PointDataGridT, FilterT, DeformerT> pointsToScalarOp(
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
390 convertPointsToMask(
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
403 convertPointsToMask(
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
410 using AdapterT = TreeAdapter<typename PointDataGridT::TreeType>;
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>
427 OPENVDB_DEPRECATED
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>
443 OPENVDB_DEPRECATED
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) 2012-2018 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/ )
openvdb::v6_1::points::PointDataLeafNode
Definition: PointDataGrid.h:212
openvdb::v6_1::points::point_mask_internal::PointsToScalarOp::PointsToScalarOp
PointsToScalarOp(const PointDataGridT &grid, const FilterT &filter)
Definition: PointMask.h:177
openvdb::v6_1::points::PointDataLeafNode::setOffsetOn
void setOffsetOn(Index offset, const ValueType &val)
Definition: PointDataGrid.h:1135
OPENVDB_DEPRECATED
#define OPENVDB_DEPRECATED
Definition: Platform.h:69
openvdb::v6_1::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:386
openvdb::v6_1::points::NullDeformer
No-op deformer (adheres to the deformer interface documented in PointMove.h)
Definition: PointMask.h:91
ValueTransformer.h
openvdb.h
openvdb::v6_1::points::AttributeHandle
Definition: AttributeArray.h:846
openvdb::v6_1::tree::ValueAccessor
Definition: ValueAccessor.h:220
openvdb::v6_1::points::point_mask_internal::GridCombinerOp::operator()
void operator()(const GridT &grid)
Definition: PointMask.h:146
openvdb::v6_1::points::point_mask_internal::PointsToScalarOp::ValueT
typename LeafT::ValueType ValueT
Definition: PointMask.h:175
openvdb::v6_1::points::NullFilter
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:77
openvdb::v6_1::points::point_mask_internal::PointsToTransformedScalarOp::CombinableT
typename GridCombinerOp< GridT >::CombinableT CombinableT
Definition: PointMask.h:216
openvdb::v6_1::points::NullDeformer::reset
void reset(LeafT &, size_t=0)
Definition: PointMask.h:94
openvdb::v6_1::tools::valxform::SumOp
Definition: ValueTransformer.h:277
openvdb::v6_1::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:109
IndexFilter.h
Index filters primarily designed to be used with a FilterIndexIter.
openvdb::v6_1::points::point_mask_internal::GridCombinerOp::ValueType
typename TreeT::ValueType ValueType
Definition: PointMask.h:140
openvdb::v6_1::math::Vec3d
Vec3< double > Vec3d
Definition: Vec3.h:689
openvdb::v6_1::points::point_mask_internal::voxelSum
void voxelSum(PointDataLeafNode< T, Log2Dim > &leaf, const Index offset, const typename PointDataLeafNode< T, Log2Dim >::ValueType &value)
Definition: PointMask.h:124
openvdb::v6_1::points::point_mask_internal::GridCombinerOp::CombinableT
typename tbb::combinable< GridT > CombinableT
Definition: PointMask.h:136
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:125
openvdb::v6_1::tree::LeafNode::getValue
const ValueType & getValue(const Coord &xyz) const
Return the value of the voxel at the given coordinates.
Definition: LeafNode.h:1087
openvdb::v6_1::Index
Index32 Index
Definition: Types.h:61
openvdb::v6_1::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:523
openvdb::v6_1::Index64
uint64_t Index64
Definition: Types.h:60
openvdb::v6_1::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:327
openvdb::v6_1::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:134
openvdb
Definition: Exceptions.h:40
openvdb::v6_1::points::point_mask_internal::PointsToTransformedScalarOp::ValueT
typename GridT::TreeType::ValueType ValueT
Definition: PointMask.h:214
openvdb::v6_1::math::Transform
Definition: Transform.h:66
openvdb::v6_1::points::point_mask_internal::GridCombinerOp::TreeT
typename GridT::TreeType TreeT
Definition: PointMask.h:138
openvdb::v6_1::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:52
openvdb::v6_1::points::index::ALL
Definition: IndexIterator.h:70
openvdb::v6_1::points::NullDeformer::apply
void apply(Vec3d &, IterT &) const
Definition: PointMask.h:97
openvdb::v6_1::points::point_mask_internal::PointsToTransformedScalarOp::PointDataLeafT
typename PointDataGridT::TreeType::LeafNodeType PointDataLeafT
Definition: PointMask.h:213
PointDataGrid.h
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
openvdb::v6_1::TopologyCopy
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:750
openvdb::v6_1::points::DeformerTraits
Deformer Traits for optionally configuring deformers to be applied in index-space....
Definition: PointMask.h:103
openvdb::v6_1::points::point_mask_internal::PointsToTransformedScalarOp
Compute scalar grid from PointDataGrid using a different transform and while evaluating the point fil...
Definition: PointMask.h:211
openvdb::v6_1::points::point_mask_internal::PointsToScalarOp::LeafT
typename GridT::TreeType::LeafNodeType LeafT
Definition: PointMask.h:174
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:177
openvdb::v6_1::points::point_mask_internal::PointsToTransformedScalarOp::operator()
void operator()(const PointDataLeafT &leaf, size_t idx) const
Definition: PointMask.h:229
openvdb::v6_1::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:218
openvdb::v6_1::points::point_mask_internal::PointsToScalarOp
Compute scalar grid from PointDataGrid while evaluating the point filter.
Definition: PointMask.h:172
openvdb::v6_1::points::point_mask_internal::GridCombinerOp::GridCombinerOp
GridCombinerOp(GridT &grid)
Definition: PointMask.h:143
openvdb::v6_1::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:446
openvdb::v6_1::points::point_mask_internal::GridCombinerOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition: PointMask.h:139
openvdb::v6_1::points::MultiGroupFilter
Definition: IndexFilter.h:163
openvdb::v6_1::points::point_mask_internal::PointsToScalarOp::operator()
void operator()(LeafT &leaf, size_t) const
Definition: PointMask.h:182
openvdb::v6_1::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:1036
openvdb::v6_1::points::PointDataLeafNode::ValueType
T ValueType
Definition: PointDataGrid.h:270
openvdb::v6_1::points::iterCount
Index64 iterCount(const IterT &iter)
Count up the number of times the iterator can iterate.
Definition: IndexIterator.h:341