GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/points/PointMove.h
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 189 190 99.5%
Functions: 48 113 42.5%
Branches: 351 1139 30.8%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 /// @author Dan Bailey
5 ///
6 /// @file PointMove.h
7 ///
8 /// @brief Ability to move VDB Points using a custom deformer.
9 ///
10 /// Deformers used when moving points are in world space by default and must adhere
11 /// to the interface described in the example below:
12 /// @code
13 /// struct MyDeformer
14 /// {
15 /// // A reset is performed on each leaf in turn before the points in that leaf are
16 /// // deformed. A leaf and leaf index (standard leaf traversal order) are supplied as
17 /// // the arguments, which matches the functor interface for LeafManager::foreach().
18 /// template <typename LeafNoteType>
19 /// void reset(LeafNoteType& leaf, size_t idx);
20 ///
21 /// // Evaluate the deformer and modify the given position to generate the deformed
22 /// // position. An index iterator is supplied as the argument to allow querying the
23 /// // point offset or containing voxel coordinate.
24 /// template <typename IndexIterT>
25 /// void apply(Vec3d& position, const IndexIterT& iter) const;
26 /// };
27 /// @endcode
28 ///
29 /// @note The DeformerTraits struct (defined in PointMask.h) can be used to configure
30 /// a deformer to evaluate in index space.
31
32 #ifndef OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED
33 #define OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED
34
35 #include <openvdb/openvdb.h>
36
37 #include <openvdb/points/PointDataGrid.h>
38 #include <openvdb/points/PointMask.h>
39
40 #include <tbb/concurrent_vector.h>
41
42 #include <algorithm>
43 #include <iterator> // for std::begin(), std::end()
44 #include <map>
45 #include <numeric> // for std::iota()
46 #include <tuple>
47 #include <unordered_map>
48 #include <vector>
49
50 class TestPointMove;
51
52
53 namespace openvdb {
54 OPENVDB_USE_VERSION_NAMESPACE
55 namespace OPENVDB_VERSION_NAME {
56 namespace points {
57
58 // dummy object for future use
59 namespace future { struct Advect { }; }
60
61
62 /// @brief Move points in a PointDataGrid using a custom deformer
63 /// @param points the PointDataGrid containing the points to be moved.
64 /// @param deformer a custom deformer that defines how to move the points.
65 /// @param filter an optional index filter
66 /// @param objectNotInUse for future use, this object is currently ignored
67 /// @param threaded enable or disable threading (threading is enabled by default)
68 template <typename PointDataGridT, typename DeformerT, typename FilterT = NullFilter>
69 inline void movePoints(PointDataGridT& points,
70 DeformerT& deformer,
71 const FilterT& filter = NullFilter(),
72 future::Advect* objectNotInUse = nullptr,
73 bool threaded = true);
74
75
76 /// @brief Move points in a PointDataGrid using a custom deformer and a new transform
77 /// @param points the PointDataGrid containing the points to be moved.
78 /// @param transform target transform to use for the resulting points.
79 /// @param deformer a custom deformer that defines how to move the points.
80 /// @param filter an optional index filter
81 /// @param objectNotInUse for future use, this object is currently ignored
82 /// @param threaded enable or disable threading (threading is enabled by default)
83 template <typename PointDataGridT, typename DeformerT, typename FilterT = NullFilter>
84 inline void movePoints(PointDataGridT& points,
85 const math::Transform& transform,
86 DeformerT& deformer,
87 const FilterT& filter = NullFilter(),
88 future::Advect* objectNotInUse = nullptr,
89 bool threaded = true);
90
91
92 // define leaf index in use as 32-bit
93 namespace point_move_internal { using LeafIndex = Index32; }
94
95
96 /// @brief A Deformer that caches the resulting positions from evaluating another Deformer
97 template <typename T>
98 class CachedDeformer
99 {
100 public:
101 using LeafIndex = point_move_internal::LeafIndex;
102 using Vec3T = typename math::Vec3<T>;
103 using LeafVecT = std::vector<Vec3T>;
104 using LeafMapT = std::unordered_map<LeafIndex, Vec3T>;
105
106 // Internal data cache to allow the deformer to offer light-weight copying
107
1/2
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
3 struct Cache
108 {
109 2360 struct Leaf
110 {
111 /// @brief clear data buffers and reset counter
112 void clear() {
113 vecData.clear();
114 mapData.clear();
115 2324 totalSize = 0;
116 }
117
118 LeafVecT vecData;
119 LeafMapT mapData;
120 Index totalSize = 0;
121 }; // struct Leaf
122
123 std::vector<Leaf> leafs;
124 }; // struct Cache
125
126 /// Cache is expected to be persistent for the lifetime of the CachedDeformer
127 explicit CachedDeformer(Cache& cache);
128
129 /// Caches the result of evaluating the supplied point grid using the deformer and filter
130 /// @param grid the points to be moved
131 /// @param deformer the deformer to apply to the points
132 /// @param filter the point filter to use when evaluating the points
133 /// @param threaded enable or disable threading (threading is enabled by default)
134 template <typename PointDataGridT, typename DeformerT, typename FilterT>
135 void evaluate(PointDataGridT& grid, DeformerT& deformer, const FilterT& filter,
136 bool threaded = true);
137
138 /// Stores pointers to the vector or map and optionally expands the map into a vector
139 /// @throw IndexError if idx is out-of-range of the leafs in the cache
140 template <typename LeafT>
141 void reset(const LeafT& leaf, size_t idx);
142
143 /// Retrieve the new position from the cache
144 template <typename IndexIterT>
145 void apply(Vec3d& position, const IndexIterT& iter) const;
146
147 private:
148 friend class ::TestPointMove;
149
150 Cache& mCache;
151 const LeafVecT* mLeafVec = nullptr;
152 const LeafMapT* mLeafMap = nullptr;
153 }; // class CachedDeformer
154
155
156 ////////////////////////////////////////
157
158
159 namespace point_move_internal {
160
161 using IndexArray = std::vector<Index>;
162
163 using IndexTriple = std::tuple<LeafIndex, Index, Index>;
164 using IndexTripleArray = tbb::concurrent_vector<IndexTriple>;
165 using GlobalPointIndexMap = std::vector<IndexTripleArray>;
166 using GlobalPointIndexIndices = std::vector<IndexArray>;
167
168 using IndexPair = std::pair<Index, Index>;
169 using IndexPairArray = std::vector<IndexPair>;
170 using LocalPointIndexMap = std::vector<IndexPairArray>;
171
172 using LeafIndexArray = std::vector<LeafIndex>;
173 using LeafOffsetArray = std::vector<LeafIndexArray>;
174 using LeafMap = std::unordered_map<Coord, LeafIndex>;
175
176
177 template <typename DeformerT, typename TreeT, typename FilterT>
178 struct BuildMoveMapsOp
179 {
180 using LeafT = typename TreeT::LeafNodeType;
181 using LeafArrayT = std::vector<LeafT*>;
182 using LeafManagerT = typename tree::LeafManager<TreeT>;
183
184 38 BuildMoveMapsOp(const DeformerT& deformer,
185 GlobalPointIndexMap& globalMoveLeafMap,
186 LocalPointIndexMap& localMoveLeafMap,
187 const LeafMap& targetLeafMap,
188 const math::Transform& targetTransform,
189 const math::Transform& sourceTransform,
190 const FilterT& filter)
191 : mDeformer(deformer)
192 , mGlobalMoveLeafMap(globalMoveLeafMap)
193 , mLocalMoveLeafMap(localMoveLeafMap)
194 , mTargetLeafMap(targetLeafMap)
195 , mTargetTransform(targetTransform)
196 , mSourceTransform(sourceTransform)
197 38 , mFilter(filter) { }
198
199 6124 void operator()(LeafT& leaf, size_t idx) const
200 {
201
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
4834 DeformerT deformer(mDeformer);
202
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
4732 deformer.reset(leaf, idx);
203
204 // determine source leaf node origin and offset in the source leaf vector
205
206 6124 Coord sourceLeafOrigin = leaf.origin();
207
208
3/6
✓ Branch 1 taken 3062 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3062 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3062 times.
✗ Branch 8 not taken.
12196 auto sourceHandle = AttributeWriteHandle<Vec3f>::create(leaf.attributeArray("P"));
209
210
4/5
✓ Branch 0 taken 5491261 times.
✓ Branch 1 taken 3062 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 17 times.
✓ Branch 4 taken 26 times.
21971288 for (auto iter = leaf.beginIndexOn(mFilter); iter; iter++) {
211
212 const bool useIndexSpace = DeformerTraits<DeformerT>::IndexSpace;
213
214 // extract index-space position and apply index-space deformation (if applicable)
215
216
2/4
✓ Branch 1 taken 5491278 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 5491278 times.
✗ Branch 6 not taken.
10982556 Vec3d positionIS = sourceHandle->get(*iter) + iter.getCoord().asVec3d();
217 if (useIndexSpace) {
218 deformer.apply(positionIS, iter);
219 }
220
221 // transform to world-space position and apply world-space deformation (if applicable)
222
223
1/2
✓ Branch 1 taken 5491278 times.
✗ Branch 2 not taken.
10982556 Vec3d positionWS = mSourceTransform.indexToWorld(positionIS);
224 if (!useIndexSpace) {
225
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
7674268 deformer.apply(positionWS, iter);
226 }
227
228 // transform to index-space position of target grid
229
230
1/2
✓ Branch 1 taken 5491278 times.
✗ Branch 2 not taken.
10982556 positionIS = mTargetTransform.worldToIndex(positionWS);
231
232 // determine target voxel and offset
233
234 10982556 Coord targetVoxel = Coord::round(positionIS);
235 10982556 Index targetOffset = LeafT::coordToOffset(targetVoxel);
236
237 // set new local position in source transform space (if point has been deformed)
238
239 Vec3d voxelPosition(positionIS - targetVoxel.asVec3d());
240
1/2
✓ Branch 2 taken 5491278 times.
✗ Branch 3 not taken.
10982556 sourceHandle->set(*iter, voxelPosition);
241
242 // determine target leaf node origin and offset in the target leaf vector
243
244 10982556 Coord targetLeafOrigin = targetVoxel & ~(LeafT::DIM - 1);
245
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5491278 times.
10982556 assert(mTargetLeafMap.find(targetLeafOrigin) != mTargetLeafMap.end());
246
3/4
✓ Branch 1 taken 5491278 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 491191 times.
✓ Branch 4 taken 5000087 times.
10982556 const LeafIndex targetLeafOffset(mTargetLeafMap.at(targetLeafOrigin));
247
248 // insert into move map based on whether point ends up in a new leaf node or not
249
250 if (targetLeafOrigin == sourceLeafOrigin) {
251
1/2
✓ Branch 2 taken 41680 times.
✗ Branch 3 not taken.
83360 mLocalMoveLeafMap[targetLeafOffset].emplace_back(targetOffset, *iter);
252 }
253 else {
254
1/4
✓ Branch 2 taken 5449598 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
10899196 mGlobalMoveLeafMap[targetLeafOffset].push_back(IndexTriple(
255 10899196 LeafIndex(static_cast<LeafIndex>(idx)), targetOffset, *iter));
256 }
257 }
258 }
259
260 private:
261 const DeformerT& mDeformer;
262 GlobalPointIndexMap& mGlobalMoveLeafMap;
263 LocalPointIndexMap& mLocalMoveLeafMap;
264 const LeafMap& mTargetLeafMap;
265 const math::Transform& mTargetTransform;
266 const math::Transform& mSourceTransform;
267 const FilterT& mFilter;
268 }; // struct BuildMoveMapsOp
269
270 template <typename LeafT>
271 inline Index
272 9328518 indexOffsetFromVoxel(const Index voxelOffset, const LeafT& leaf, IndexArray& offsets)
273 {
274 // compute the target point index by summing the point index of the previous
275 // voxel with the current number of points added to this voxel, tracked by the
276 // offsets array
277
278
2/2
✓ Branch 0 taken 9293419 times.
✓ Branch 1 taken 35099 times.
9328518 Index targetOffset = offsets[voxelOffset]++;
279
2/2
✓ Branch 0 taken 9293419 times.
✓ Branch 1 taken 35099 times.
9328518 if (voxelOffset > 0) {
280 9293419 targetOffset += static_cast<Index>(leaf.getValue(voxelOffset - 1));
281 }
282 9328518 return targetOffset;
283 }
284
285
286 template <typename TreeT>
287 struct GlobalMovePointsOp
288 {
289 using LeafT = typename TreeT::LeafNodeType;
290 using LeafArrayT = std::vector<LeafT*>;
291 using LeafManagerT = typename tree::LeafManager<TreeT>;
292 using AttributeArrays = std::vector<AttributeArray*>;
293
294 90 GlobalMovePointsOp(LeafOffsetArray& offsetMap,
295 LeafManagerT& sourceLeafManager,
296 const Index attributeIndex,
297 const GlobalPointIndexMap& moveLeafMap,
298 const GlobalPointIndexIndices& moveLeafIndices)
299 : mOffsetMap(offsetMap)
300 , mSourceLeafManager(sourceLeafManager)
301 , mAttributeIndex(attributeIndex)
302 , mMoveLeafMap(moveLeafMap)
303 90 , mMoveLeafIndices(moveLeafIndices) { }
304
305 // A CopyIterator is designed to use the indices in a GlobalPointIndexMap for this leaf
306 // and match the interface required for AttributeArray::copyValues()
307 struct CopyIterator
308 {
309 4866 CopyIterator(const LeafT& leaf, const IndexArray& sortedIndices,
310 const IndexTripleArray& moveIndices, IndexArray& offsets)
311 : mLeaf(leaf)
312 , mSortedIndices(sortedIndices)
313 , mMoveIndices(moveIndices)
314 4866 , mOffsets(offsets) { }
315
316
2/2
✓ Branch 0 taken 9281752 times.
✓ Branch 1 taken 14545 times.
9296297 operator bool() const { return bool(mIt); }
317
318 void reset(Index startIndex, Index endIndex)
319 {
320 14545 mIndex = startIndex;
321 14545 mEndIndex = endIndex;
322 14545 this->advance();
323 }
324
325 CopyIterator& operator++()
326 {
327 9281752 this->advance();
328 9281752 return *this;
329 }
330
331 9286618 Index leafIndex(Index i) const
332 {
333
2/2
✓ Branch 0 taken 9281752 times.
✓ Branch 1 taken 4866 times.
9286618 if (i < mSortedIndices.size()) {
334 9281752 return std::get<0>(this->leafIndexTriple(i));
335 }
336 return std::numeric_limits<Index>::max();
337 }
338
339 Index sourceIndex() const
340 {
341 assert(mIt);
342 9281719 return std::get<2>(*mIt);
343 }
344
345 9281752 Index targetIndex() const
346 {
347
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9281752 times.
9281752 assert(mIt);
348 9281752 return indexOffsetFromVoxel(std::get<1>(*mIt), mLeaf, mOffsets);
349 }
350
351 private:
352 9296297 void advance()
353 {
354
3/4
✓ Branch 0 taken 9281752 times.
✓ Branch 1 taken 14545 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9281752 times.
9296297 if (mIndex >= mEndIndex || mIndex >= mSortedIndices.size()) {
355 14545 mIt = nullptr;
356 }
357 else {
358 9281752 mIt = &this->leafIndexTriple(mIndex);
359 }
360 9296297 ++mIndex;
361 9296297 }
362
363 const IndexTriple& leafIndexTriple(Index i) const
364 {
365 18563504 return mMoveIndices[mSortedIndices[i]];
366 }
367
368 private:
369 const LeafT& mLeaf;
370 Index mIndex;
371 Index mEndIndex;
372 const IndexArray& mSortedIndices;
373 const IndexTripleArray& mMoveIndices;
374 IndexArray& mOffsets;
375 const IndexTriple* mIt = nullptr;
376 }; // struct CopyIterator
377
378 4994 void operator()(LeafT& leaf, size_t idx) const
379 {
380 4994 const IndexTripleArray& moveIndices = mMoveLeafMap[idx];
381
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 4866 times.
4994 if (moveIndices.empty()) return;
382 4866 const IndexArray& sortedIndices = mMoveLeafIndices[idx];
383
384 // extract per-voxel offsets for this leaf
385
386 4866 LeafIndexArray& offsets = mOffsetMap[idx];
387
388 // extract target array and ensure data is out-of-core and non-uniform
389
390 4866 auto& targetArray = leaf.attributeArray(mAttributeIndex);
391 4866 targetArray.loadData();
392 4866 targetArray.expand();
393
394 // perform the copy
395
396 CopyIterator copyIterator(leaf, sortedIndices, moveIndices, offsets);
397
398 // use the sorted indices to track the index of the source leaf
399
400 4866 Index sourceLeafIndex = copyIterator.leafIndex(0);
401 Index startIndex = 0;
402
403
2/2
✓ Branch 0 taken 9281752 times.
✓ Branch 1 taken 4866 times.
9286618 for (size_t i = 1; i <= sortedIndices.size(); i++) {
404 9281752 Index endIndex = static_cast<Index>(i);
405 9281752 Index newSourceLeafIndex = copyIterator.leafIndex(endIndex);
406
407 // when it changes, do a batch-copy of all the indices that lie within this range
408 // TODO: this step could use nested parallelization for cases where there are a
409 // large number of points being moved per attribute
410
411
2/2
✓ Branch 0 taken 14545 times.
✓ Branch 1 taken 9267207 times.
9281752 if (newSourceLeafIndex > sourceLeafIndex) {
412 copyIterator.reset(startIndex, endIndex);
413
414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14545 times.
14545 const LeafT& sourceLeaf = mSourceLeafManager.leaf(sourceLeafIndex);
415 14545 const auto& sourceArray = sourceLeaf.constAttributeArray(mAttributeIndex);
416 14545 sourceArray.loadData();
417
418 14545 targetArray.copyValuesUnsafe(sourceArray, copyIterator);
419
420 sourceLeafIndex = newSourceLeafIndex;
421 startIndex = endIndex;
422 }
423 }
424 }
425
426 private:
427 LeafOffsetArray& mOffsetMap;
428 LeafManagerT& mSourceLeafManager;
429 const Index mAttributeIndex;
430 const GlobalPointIndexMap& mMoveLeafMap;
431 const GlobalPointIndexIndices& mMoveLeafIndices;
432 }; // struct GlobalMovePointsOp
433
434
435 template <typename TreeT>
436 struct LocalMovePointsOp
437 {
438 using LeafT = typename TreeT::LeafNodeType;
439 using LeafArrayT = std::vector<LeafT*>;
440 using LeafManagerT = typename tree::LeafManager<TreeT>;
441 using AttributeArrays = std::vector<AttributeArray*>;
442
443 90 LocalMovePointsOp( LeafOffsetArray& offsetMap,
444 const LeafIndexArray& sourceIndices,
445 LeafManagerT& sourceLeafManager,
446 const Index attributeIndex,
447 const LocalPointIndexMap& moveLeafMap)
448 : mOffsetMap(offsetMap)
449 , mSourceIndices(sourceIndices)
450 , mSourceLeafManager(sourceLeafManager)
451 , mAttributeIndex(attributeIndex)
452 90 , mMoveLeafMap(moveLeafMap) { }
453
454 // A CopyIterator is designed to use the indices in a LocalPointIndexMap for this leaf
455 // and match the interface required for AttributeArray::copyValues()
456 struct CopyIterator
457 {
458 184 CopyIterator(const LeafT& leaf, const IndexPairArray& indices, IndexArray& offsets)
459 : mLeaf(leaf)
460 , mIndices(indices)
461 184 , mOffsets(offsets) { }
462
463
2/2
✓ Branch 0 taken 46766 times.
✓ Branch 1 taken 184 times.
46950 operator bool() const { return mIndex < static_cast<int>(mIndices.size()); }
464
465 46766 CopyIterator& operator++() { ++mIndex; return *this; }
466
467 Index sourceIndex() const
468 {
469 46730 return mIndices[mIndex].second;
470 }
471
472 46766 Index targetIndex() const
473 {
474 46766 return indexOffsetFromVoxel(mIndices[mIndex].first, mLeaf, mOffsets);
475 }
476
477 private:
478 const LeafT& mLeaf;
479 const IndexPairArray& mIndices;
480 IndexArray& mOffsets;
481 int mIndex = 0;
482 }; // struct CopyIterator
483
484 4994 void operator()(LeafT& leaf, size_t idx) const
485 {
486
2/2
✓ Branch 0 taken 4810 times.
✓ Branch 1 taken 184 times.
4994 const IndexPairArray& moveIndices = mMoveLeafMap[idx];
487
2/2
✓ Branch 0 taken 4810 times.
✓ Branch 1 taken 184 times.
4994 if (moveIndices.empty()) return;
488
489 // extract per-voxel offsets for this leaf
490
491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
184 LeafIndexArray& offsets = mOffsetMap[idx];
492
493 // extract source array that has the same origin as the target leaf
494
495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
184 assert(idx < mSourceIndices.size());
496 184 const Index sourceLeafOffset(mSourceIndices[idx]);
497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 184 times.
184 LeafT& sourceLeaf = mSourceLeafManager.leaf(sourceLeafOffset);
498 184 const auto& sourceArray = sourceLeaf.constAttributeArray(mAttributeIndex);
499 184 sourceArray.loadData();
500
501 // extract target array and ensure data is out-of-core and non-uniform
502
503 184 auto& targetArray = leaf.attributeArray(mAttributeIndex);
504 184 targetArray.loadData();
505 184 targetArray.expand();
506
507 // perform the copy
508
509 CopyIterator copyIterator(leaf, moveIndices, offsets);
510 184 targetArray.copyValuesUnsafe(sourceArray, copyIterator);
511 }
512
513 private:
514 LeafOffsetArray& mOffsetMap;
515 const LeafIndexArray& mSourceIndices;
516 LeafManagerT& mSourceLeafManager;
517 const Index mAttributeIndex;
518 const LocalPointIndexMap& mMoveLeafMap;
519 }; // struct LocalMovePointsOp
520
521
522 } // namespace point_move_internal
523
524
525 ////////////////////////////////////////
526
527
528 template <typename PointDataGridT, typename DeformerT, typename FilterT>
529 76 inline void movePoints( PointDataGridT& points,
530 const math::Transform& transform,
531 DeformerT& deformer,
532 const FilterT& filter,
533 future::Advect* objectNotInUse,
534 bool threaded)
535 {
536 using LeafIndex = point_move_internal::LeafIndex;
537 using PointDataTreeT = typename PointDataGridT::TreeType;
538 using LeafT = typename PointDataTreeT::LeafNodeType;
539 using LeafManagerT = typename tree::LeafManager<PointDataTreeT>;
540
541 using namespace point_move_internal;
542
543 // this object is for future use only
544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
76 assert(!objectNotInUse);
545 (void)objectNotInUse;
546
547 PointDataTreeT& tree = points.tree();
548
549 // early exit if no LeafNodes
550
551 auto iter = tree.cbeginLeaf();
552
553
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
76 if (!iter) return;
554
555 // build voxel topology taking into account any point group deletion
556
557 76 auto newPoints = point_mask_internal::convertPointsToScalar<PointDataGridT>(
558 points, transform, filter, deformer, threaded);
559 auto& newTree = newPoints->tree();
560
561 // create leaf managers for both trees
562
563
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
152 LeafManagerT sourceLeafManager(tree);
564
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
152 LeafManagerT targetLeafManager(newTree);
565
566 // extract the existing attribute set
567
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
76 const auto& existingAttributeSet = points.tree().cbeginLeaf()->attributeSet();
568
569 // build a coord -> index map for looking up target leafs by origin and a faster
570 // unordered map for finding the source index from a target index
571
572 LeafMap targetLeafMap;
573
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
76 LeafIndexArray sourceIndices(targetLeafManager.leafCount(),
574
2/4
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
76 std::numeric_limits<LeafIndex>::max());
575
576
1/4
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
152 LeafOffsetArray offsetMap(targetLeafManager.leafCount());
577
578 {
579 LeafMap sourceLeafMap;
580 auto sourceRange = sourceLeafManager.leafRange();
581
2/2
✓ Branch 1 taken 3062 times.
✓ Branch 2 taken 38 times.
6200 for (auto leaf = sourceRange.begin(); leaf; ++leaf) {
582
1/2
✓ Branch 1 taken 3062 times.
✗ Branch 2 not taken.
6124 sourceLeafMap.insert({leaf->origin(), LeafIndex(static_cast<LeafIndex>(leaf.pos()))});
583 }
584 auto targetRange = targetLeafManager.leafRange();
585
2/2
✓ Branch 1 taken 2489 times.
✓ Branch 2 taken 38 times.
5054 for (auto leaf = targetRange.begin(); leaf; ++leaf) {
586
1/2
✓ Branch 1 taken 2489 times.
✗ Branch 2 not taken.
4978 targetLeafMap.insert({leaf->origin(), LeafIndex(static_cast<LeafIndex>(leaf.pos()))});
587 }
588
589 // acquire registry lock to avoid locking when appending attributes in parallel
590
591
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
76 AttributeArray::ScopedRegistryLock lock;
592
593 // perform four independent per-leaf operations in parallel
594
2/6
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 38 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
76 targetLeafManager.foreach(
595 7467 [&](LeafT& leaf, size_t idx) {
596 // map frequency => cumulative histogram
597 2489 auto* buffer = leaf.buffer().data();
598
22/52
✓ Branch 0 taken 4599 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 4599 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 511 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 2044 times.
✓ Branch 9 taken 4 times.
✓ Branch 10 taken 511 times.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 2555 times.
✓ Branch 13 taken 5 times.
✓ Branch 14 taken 3066 times.
✓ Branch 15 taken 6 times.
✓ Branch 16 taken 4088 times.
✓ Branch 17 taken 8 times.
✓ Branch 18 taken 12264 times.
✓ Branch 19 taken 24 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 3066 times.
✓ Branch 33 taken 6 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 1234576 times.
✓ Branch 51 taken 2416 times.
1274368 for (Index i = 1; i < leaf.buffer().size(); i++) {
599 1271879 buffer[i] = buffer[i-1] + buffer[i];
600 }
601 // replace attribute set with a copy of the existing one
602 2489 leaf.replaceAttributeSet(
603
11/52
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 22 taken 4 times.
✗ Branch 23 not taken.
✓ Branch 27 taken 1 times.
✗ Branch 28 not taken.
✓ Branch 32 taken 5 times.
✗ Branch 33 not taken.
✓ Branch 37 taken 6 times.
✗ Branch 38 not taken.
✓ Branch 42 taken 8 times.
✗ Branch 43 not taken.
✓ Branch 47 taken 24 times.
✗ Branch 48 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✓ Branch 82 taken 6 times.
✗ Branch 83 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 107 not taken.
✗ Branch 108 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✓ Branch 127 taken 2416 times.
✗ Branch 128 not taken.
2489 new AttributeSet(existingAttributeSet, leaf.getLastValue(), &lock),
604 /*allowMismatchingDescriptors=*/true);
605 // store the index of the source leaf in a corresponding target leaf array
606
17/52
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 3 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 2 times.
✓ Branch 15 taken 4 times.
✓ Branch 16 taken 4 times.
✓ Branch 17 taken 4 times.
✓ Branch 18 taken 24 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 6 times.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 2136 times.
✓ Branch 51 taken 280 times.
2489 const auto it = sourceLeafMap.find(leaf.origin());
607
17/52
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 3 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 2 times.
✓ Branch 15 taken 4 times.
✓ Branch 16 taken 4 times.
✓ Branch 17 taken 4 times.
✓ Branch 18 taken 24 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 6 times.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 2136 times.
✓ Branch 51 taken 280 times.
2489 if (it != sourceLeafMap.end()) {
608 2192 sourceIndices[idx] = it->second;
609 }
610 // allocate offset maps
611 2489 offsetMap[idx].resize(LeafT::SIZE);
612 },
613 threaded);
614 }
615
616 // moving leaf
617
618
2/4
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 38 times.
✗ Branch 5 not taken.
152 GlobalPointIndexMap globalMoveLeafMap(targetLeafManager.leafCount());
619
3/5
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
152 LocalPointIndexMap localMoveLeafMap(targetLeafManager.leafCount());
620
621 // build global and local move leaf maps and update local positions
622
623 if (filter.state() == index::ALL) {
624 NullFilter nullFilter;
625 BuildMoveMapsOp<DeformerT, PointDataTreeT, NullFilter> op(deformer,
626 globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
627 transform, points.transform(), nullFilter);
628
1/2
✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
58 sourceLeafManager.foreach(op, threaded);
629 } else {
630 BuildMoveMapsOp<DeformerT, PointDataTreeT, FilterT> op(deformer,
631 globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
632 transform, points.transform(), filter);
633
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
18 sourceLeafManager.foreach(op, threaded);
634 }
635
636 // build a sorted index vector for each leaf that references the global move map
637 // indices in order of their source leafs and voxels to ensure determinism in the
638 // resulting point orders
639
640
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
76 GlobalPointIndexIndices globalMoveLeafIndices(globalMoveLeafMap.size());
641
642
1/2
✓ Branch 1 taken 38 times.
✗ Branch 2 not taken.
76 targetLeafManager.foreach(
643 4925 [&](LeafT& /*leaf*/, size_t idx) {
644 const IndexTripleArray& moveIndices = globalMoveLeafMap[idx];
645
18/52
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 4 times.
✓ Branch 14 taken 4 times.
✓ Branch 15 taken 2 times.
✓ Branch 16 taken 4 times.
✓ Branch 17 taken 4 times.
✓ Branch 18 taken 24 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✓ Branch 33 taken 6 times.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 2387 times.
✓ Branch 51 taken 29 times.
2489 if (moveIndices.empty()) return;
646
647 IndexArray& sortedIndices = globalMoveLeafIndices[idx];
648 2436 sortedIndices.resize(moveIndices.size());
649 2436 std::iota(std::begin(sortedIndices), std::end(sortedIndices), 0);
650 2436 std::sort(std::begin(sortedIndices), std::end(sortedIndices),
651 69917894 [&](int i, int j)
652 {
653 89703025 const Index& indexI0(std::get<0>(moveIndices[i]));
654 89703025 const Index& indexJ0(std::get<0>(moveIndices[j]));
655
8/52
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 25647088 times.
✓ Branch 19 taken 14566865 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 46630534 times.
✓ Branch 51 taken 2858508 times.
89703025 if (indexI0 < indexJ0) return true;
656
9/52
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 23353873 times.
✓ Branch 19 taken 2293215 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✓ Branch 50 taken 46564013 times.
✓ Branch 51 taken 66521 times.
72277650 if (indexI0 > indexJ0) return false;
657 69917894 return std::get<2>(moveIndices[i]) < std::get<2>(moveIndices[j]);
658 }
659 );
660 },
661 threaded);
662
663
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 38 times.
256 for (const auto& it : existingAttributeSet.descriptor().map()) {
664
665 180 const Index attributeIndex = static_cast<Index>(it.second);
666
667 // zero offsets
668
1/2
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
180 targetLeafManager.foreach(
669 9988 [&offsetMap](const LeafT& /*leaf*/, size_t idx) {
670 4994 std::fill(offsetMap[idx].begin(), offsetMap[idx].end(), 0);
671 },
672 threaded);
673
674 // move points between leaf nodes
675
676 GlobalMovePointsOp<PointDataTreeT> globalMoveOp(offsetMap,
677 sourceLeafManager, attributeIndex, globalMoveLeafMap, globalMoveLeafIndices);
678
1/2
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
180 targetLeafManager.foreach(globalMoveOp, threaded);
679
680 // move points within leaf nodes
681
682 LocalMovePointsOp<PointDataTreeT> localMoveOp(offsetMap,
683 sourceIndices, sourceLeafManager, attributeIndex, localMoveLeafMap);
684
1/2
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
180 targetLeafManager.foreach(localMoveOp, threaded);
685 }
686
687
2/6
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 38 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
152 points.setTree(newPoints->treePtr());
688 }
689
690
691 template <typename PointDataGridT, typename DeformerT, typename FilterT>
692 inline void movePoints( PointDataGridT& points,
693 DeformerT& deformer,
694 const FilterT& filter,
695 future::Advect* objectNotInUse,
696 bool threaded)
697 {
698
21/66
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 1 times.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✓ Branch 49 taken 1 times.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✓ Branch 55 taken 1 times.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
35 movePoints(points, points.transform(), deformer, filter, objectNotInUse, threaded);
699 25 }
700
701
702 ////////////////////////////////////////
703
704
705 template <typename T>
706 14 CachedDeformer<T>::CachedDeformer(Cache& cache)
707 14 : mCache(cache) { }
708
709
710 template <typename T>
711 template <typename PointDataGridT, typename DeformerT, typename FilterT>
712 30 void CachedDeformer<T>::evaluate(PointDataGridT& grid, DeformerT& deformer, const FilterT& filter,
713 bool threaded)
714 {
715 using TreeT = typename PointDataGridT::TreeType;
716 using LeafT = typename TreeT::LeafNodeType;
717 using LeafManagerT = typename tree::LeafManager<TreeT>;
718 60 LeafManagerT leafManager(grid.tree());
719
720 // initialize cache
721
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
30 auto& leafs = mCache.leafs;
722
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
30 leafs.resize(leafManager.leafCount());
723
724 const auto& transform = grid.transform();
725
726 // insert deformed positions into the cache
727
728 4757 auto cachePositionsOp = [&](const LeafT& leaf, size_t idx) {
729
730 const Index64 totalPointCount = leaf.pointCount();
731
9/32
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 2303 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 3 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 3 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
2365 if (totalPointCount == 0) return;
732
733 // deformer is copied to ensure that it is unique per-thread
734
735
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 DeformerT newDeformer(deformer);
736
737 newDeformer.reset(leaf, idx);
738
739
28/103
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 41 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 41 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 23 not taken.
✓ Branch 24 taken 3 times.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✓ Branch 31 taken 3 times.
✗ Branch 32 not taken.
✓ Branch 33 taken 3 times.
✗ Branch 34 not taken.
✗ Branch 36 not taken.
✓ Branch 37 taken 3 times.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 40 taken 3 times.
✗ Branch 41 not taken.
✓ Branch 42 taken 1 times.
✓ Branch 43 taken 2 times.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✓ Branch 65 taken 2303 times.
✗ Branch 66 not taken.
✓ Branch 68 taken 2303 times.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✓ Branch 71 taken 2303 times.
✓ Branch 73 taken 3 times.
✗ Branch 74 not taken.
✓ Branch 76 taken 3 times.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✓ Branch 79 taken 3 times.
✓ Branch 81 taken 3 times.
✗ Branch 82 not taken.
✓ Branch 84 taken 3 times.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✓ Branch 87 taken 3 times.
✓ Branch 89 taken 3 times.
✗ Branch 90 not taken.
✓ Branch 92 taken 3 times.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✓ Branch 95 taken 3 times.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 108 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
7095 auto handle = AttributeHandle<Vec3f>::create(leaf.constAttributeArray("P"));
740
741 auto& cache = leafs[idx];
742 cache.clear();
743
744 // only insert into a vector directly if the filter evaluates all points
745 // and all points are stored in active voxels
746
8/48
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 2303 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 3 times.
✗ Branch 35 not taken.
✓ Branch 36 taken 3 times.
✗ Branch 37 not taken.
✓ Branch 38 taken 3 times.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
2330 const bool useVector = filter.state() == index::ALL &&
747
14/64
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 3 times.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 41 taken 2303 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 2303 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 3 times.
✗ Branch 47 not taken.
✓ Branch 48 taken 3 times.
✗ Branch 49 not taken.
✓ Branch 51 taken 3 times.
✗ Branch 52 not taken.
✓ Branch 53 taken 3 times.
✗ Branch 54 not taken.
✓ Branch 56 taken 3 times.
✗ Branch 57 not taken.
✓ Branch 58 taken 3 times.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
4642 (leaf.isDense() || (leaf.onPointCount() == leaf.pointCount()));
748 if (useVector) {
749
7/32
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 25 taken 2303 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 3 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 3 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 3 times.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
2321 cache.vecData.resize(totalPointCount);
750 }
751
752
18/50
✓ Branch 0 taken 5003 times.
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 40 taken 3827080 times.
✓ Branch 41 taken 2303 times.
✓ Branch 42 taken 4 times.
✓ Branch 43 taken 3 times.
✓ Branch 44 taken 4 times.
✓ Branch 45 taken 3 times.
✓ Branch 46 taken 4 times.
✓ Branch 47 taken 3 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
7666584 for (auto iter = leaf.beginIndexOn(filter); iter; iter++) {
753
754 // extract index-space position and apply index-space deformation (if defined)
755
756
27/96
✓ Branch 1 taken 5003 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 5003 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 5003 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 4 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 4 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 4 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 4 times.
✗ Branch 32 not taken.
✓ Branch 35 taken 4 times.
✗ Branch 36 not taken.
✓ Branch 38 taken 4 times.
✗ Branch 39 not taken.
✓ Branch 41 taken 4 times.
✗ Branch 42 not taken.
✓ Branch 45 taken 4 times.
✗ Branch 46 not taken.
✓ Branch 48 taken 4 times.
✗ Branch 49 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✓ Branch 81 taken 3827080 times.
✗ Branch 82 not taken.
✓ Branch 85 taken 3827080 times.
✗ Branch 86 not taken.
✓ Branch 88 taken 3827080 times.
✗ Branch 89 not taken.
✓ Branch 91 taken 4 times.
✗ Branch 92 not taken.
✓ Branch 95 taken 4 times.
✗ Branch 96 not taken.
✓ Branch 98 taken 4 times.
✗ Branch 99 not taken.
✓ Branch 101 taken 4 times.
✗ Branch 102 not taken.
✓ Branch 105 taken 4 times.
✗ Branch 106 not taken.
✓ Branch 108 taken 4 times.
✗ Branch 109 not taken.
✓ Branch 111 taken 4 times.
✗ Branch 112 not taken.
✓ Branch 115 taken 4 times.
✗ Branch 116 not taken.
✓ Branch 118 taken 4 times.
✗ Branch 119 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✗ Branch 131 not taken.
✗ Branch 132 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✗ Branch 141 not taken.
✗ Branch 142 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 155 not taken.
✗ Branch 156 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
3832108 Vec3d position = handle->get(*iter) + iter.getCoord().asVec3d();
757
758 // if deformer is designed to be used in index-space, perform deformation prior
759 // to transforming position to world-space, otherwise perform deformation afterwards
760
761 if (DeformerTraits<DeformerT>::IndexSpace) {
762 newDeformer.apply(position, iter);
763 position = transform.indexToWorld(position);
764 }
765 else {
766
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5000 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
3832100 position = transform.indexToWorld(position);
767 4 newDeformer.apply(position, iter);
768 }
769
770 // insert new position into the cache
771
772
8/32
✗ Branch 0 not taken.
✓ Branch 1 taken 5003 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 3827080 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 4 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 4 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 4 times.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
3832107 if (useVector) {
773 3827104 cache.vecData[*iter] = static_cast<Vec3T>(position);
774 }
775 else {
776
2/56
✓ Branch 2 taken 5003 times.
✗ Branch 3 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
5004 cache.mapData.insert({*iter, static_cast<Vec3T>(position)});
777 }
778 }
779
780 // store the total number of points to allow use of an expanded vector on access
781
782
11/32
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 2303 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 3 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 3 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
2365 if (!cache.mapData.empty()) {
783 36 cache.totalSize = static_cast<Index>(totalPointCount);
784 }
785 };
786
787
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
30 leafManager.foreach(cachePositionsOp, threaded);
788 30 }
789
790
791 template <typename T>
792 template <typename LeafT>
793 4718 void CachedDeformer<T>::reset(const LeafT& /*leaf*/, size_t idx)
794 {
795
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4714 times.
4718 if (idx >= mCache.leafs.size()) {
796
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
2 if (mCache.leafs.empty()) {
797
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
4 throw IndexError("No leafs in cache, perhaps CachedDeformer has not been evaluated?");
798 } else {
799 throw IndexError("Leaf index is out-of-range of cache leafs.");
800 }
801 }
802 auto& cache = mCache.leafs[idx];
803
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 4643 times.
4716 if (!cache.mapData.empty()) {
804 72 mLeafMap = &cache.mapData;
805 72 mLeafVec = nullptr;
806 }
807 else {
808 4644 mLeafVec = &cache.vecData;
809 4644 mLeafMap = nullptr;
810 }
811 4716 }
812
813
814 template <typename T>
815 template <typename IndexIterT>
816 7674212 void CachedDeformer<T>::apply(Vec3d& position, const IndexIterT& iter) const
817 {
818 7674208 assert(*iter >= 0);
819
820 7674212 if (mLeafMap) {
821 20009 auto it = mLeafMap->find(*iter);
822 20009 if (it == mLeafMap->end()) return;
823 10007 position = static_cast<openvdb::Vec3d>(it->second);
824 }
825 else {
826 7654203 assert(mLeafVec);
827
828 7654203 if (mLeafVec->empty()) return;
829 7654194 assert(*iter < mLeafVec->size());
830 7654194 position = static_cast<openvdb::Vec3d>((*mLeafVec)[*iter]);
831 }
832 }
833
834
835 } // namespace points
836 } // namespace OPENVDB_VERSION_NAME
837 } // namespace openvdb
838
839 #endif // OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED
840