OpenVDB 7.0.0

PointMove.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
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
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
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
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 struct Cache
108 {
109 struct Leaf
110 {
112 void clear() {
113 vecData.clear();
114 mapData.clear();
115 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
127 explicit CachedDeformer(Cache& cache);
128
134 template <typename PointDataGridT, typename DeformerT, typename FilterT>
135 void evaluate(PointDataGridT& grid, DeformerT& deformer, const FilterT& filter,
136 bool threaded = true);
137
140 template <typename LeafT>
141 void reset(const LeafT& leaf, size_t idx);
142
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
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 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 , mFilter(filter) { }
198
199 void operator()(LeafT& leaf, size_t idx) const
200 {
201 DeformerT deformer(mDeformer);
202 deformer.reset(leaf, idx);
203
204 // determine source leaf node origin and offset in the source leaf vector
205
206 Coord sourceLeafOrigin = leaf.origin();
207
208 auto sourceHandle = AttributeWriteHandle<Vec3f>::create(leaf.attributeArray("P"));
209
210 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 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 Vec3d positionWS = mSourceTransform.indexToWorld(positionIS);
224 if (!useIndexSpace) {
225 deformer.apply(positionWS, iter);
226 }
227
228 // transform to index-space position of target grid
229
230 positionIS = mTargetTransform.worldToIndex(positionWS);
231
232 // determine target voxel and offset
233
234 Coord targetVoxel = Coord::round(positionIS);
235 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 sourceHandle->set(*iter, voxelPosition);
241
242 // determine target leaf node origin and offset in the target leaf vector
243
244 Coord targetLeafOrigin = targetVoxel & ~(LeafT::DIM - 1);
245 assert(mTargetLeafMap.find(targetLeafOrigin) != mTargetLeafMap.end());
246 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 mLocalMoveLeafMap[targetLeafOffset].emplace_back(targetOffset, *iter);
252 }
253 else {
254 mGlobalMoveLeafMap[targetLeafOffset].push_back(IndexTriple(
255 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 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 Index targetOffset = offsets[voxelOffset]++;
279 if (voxelOffset > 0) {
280 targetOffset += static_cast<Index>(leaf.getValue(voxelOffset - 1));
281 }
282 return targetOffset;
283 }
284
285
286 #if OPENVDB_ABI_VERSION_NUMBER >= 6
287
288
289 template <typename TreeT>
290 struct GlobalMovePointsOp
291 {
292 using LeafT = typename TreeT::LeafNodeType;
293 using LeafArrayT = std::vector<LeafT*>;
294 using LeafManagerT = typename tree::LeafManager<TreeT>;
295 using AttributeArrays = std::vector<AttributeArray*>;
296
297 GlobalMovePointsOp(LeafOffsetArray& offsetMap,
298 LeafManagerT& sourceLeafManager,
299 const Index attributeIndex,
300 const GlobalPointIndexMap& moveLeafMap,
301 const GlobalPointIndexIndices& moveLeafIndices)
302 : mOffsetMap(offsetMap)
303 , mSourceLeafManager(sourceLeafManager)
304 , mAttributeIndex(attributeIndex)
305 , mMoveLeafMap(moveLeafMap)
306 , mMoveLeafIndices(moveLeafIndices) { }
307
308 // A CopyIterator is designed to use the indices in a GlobalPointIndexMap for this leaf
309 // and match the interface required for AttributeArray::copyValues()
310 struct CopyIterator
311 {
312 CopyIterator(const LeafT& leaf, const IndexArray& sortedIndices,
313 const IndexTripleArray& moveIndices, IndexArray& offsets)
314 : mLeaf(leaf)
315 , mSortedIndices(sortedIndices)
316 , mMoveIndices(moveIndices)
317 , mOffsets(offsets) { }
318
319 operator bool() const { return bool(mIt); }
320
321 void reset(Index startIndex, Index endIndex)
322 {
323 mIndex = startIndex;
324 mEndIndex = endIndex;
325 this->advance();
326 }
327
328 CopyIterator& operator++()
329 {
330 this->advance();
331 return *this;
332 }
333
334 Index leafIndex(Index i) const
335 {
336 if (i < mSortedIndices.size()) {
337 return std::get<0>(this->leafIndexTriple(i));
338 }
339 return std::numeric_limits<Index>::max();
340 }
341
342 Index sourceIndex() const
343 {
344 assert(mIt);
345 return std::get<2>(*mIt);
346 }
347
348 Index targetIndex() const
349 {
350 assert(mIt);
351 return indexOffsetFromVoxel(std::get<1>(*mIt), mLeaf, mOffsets);
352 }
353
354 private:
355 void advance()
356 {
357 if (mIndex >= mEndIndex || mIndex >= mSortedIndices.size()) {
358 mIt = nullptr;
359 }
360 else {
361 mIt = &this->leafIndexTriple(mIndex);
362 }
363 ++mIndex;
364 }
365
366 const IndexTriple& leafIndexTriple(Index i) const
367 {
368 return mMoveIndices[mSortedIndices[i]];
369 }
370
371 private:
372 const LeafT& mLeaf;
373 Index mIndex;
374 Index mEndIndex;
375 const IndexArray& mSortedIndices;
376 const IndexTripleArray& mMoveIndices;
377 IndexArray& mOffsets;
378 const IndexTriple* mIt = nullptr;
379 }; // struct CopyIterator
380
381 void operator()(LeafT& leaf, size_t idx) const
382 {
383 const IndexTripleArray& moveIndices = mMoveLeafMap[idx];
384 if (moveIndices.empty()) return;
385 const IndexArray& sortedIndices = mMoveLeafIndices[idx];
386
387 // extract per-voxel offsets for this leaf
388
389 LeafIndexArray& offsets = mOffsetMap[idx];
390
391 // extract target array and ensure data is out-of-core and non-uniform
392
393 auto& targetArray = leaf.attributeArray(mAttributeIndex);
394 targetArray.loadData();
395 targetArray.expand();
396
397 // perform the copy
398
399 CopyIterator copyIterator(leaf, sortedIndices, moveIndices, offsets);
400
401 // use the sorted indices to track the index of the source leaf
402
403 Index sourceLeafIndex = copyIterator.leafIndex(0);
404 Index startIndex = 0;
405
406 for (size_t i = 1; i <= sortedIndices.size(); i++) {
407 Index endIndex = static_cast<Index>(i);
408 Index newSourceLeafIndex = copyIterator.leafIndex(endIndex);
409
410 // when it changes, do a batch-copy of all the indices that lie within this range
411 // TODO: this step could use nested parallelization for cases where there are a
412 // large number of points being moved per attribute
413
414 if (newSourceLeafIndex > sourceLeafIndex) {
415 copyIterator.reset(startIndex, endIndex);
416
417 const LeafT& sourceLeaf = mSourceLeafManager.leaf(sourceLeafIndex);
418 const auto& sourceArray = sourceLeaf.constAttributeArray(mAttributeIndex);
419 sourceArray.loadData();
420
421 targetArray.copyValuesUnsafe(sourceArray, copyIterator);
422
423 sourceLeafIndex = newSourceLeafIndex;
424 startIndex = endIndex;
425 }
426 }
427 }
428
429 private:
430 LeafOffsetArray& mOffsetMap;
431 LeafManagerT& mSourceLeafManager;
432 const Index mAttributeIndex;
433 const GlobalPointIndexMap& mMoveLeafMap;
434 const GlobalPointIndexIndices& mMoveLeafIndices;
435 }; // struct GlobalMovePointsOp
436
437
438 template <typename TreeT>
439 struct LocalMovePointsOp
440 {
441 using LeafT = typename TreeT::LeafNodeType;
442 using LeafArrayT = std::vector<LeafT*>;
443 using LeafManagerT = typename tree::LeafManager<TreeT>;
444 using AttributeArrays = std::vector<AttributeArray*>;
445
446 LocalMovePointsOp( LeafOffsetArray& offsetMap,
447 const LeafIndexArray& sourceIndices,
448 LeafManagerT& sourceLeafManager,
449 const Index attributeIndex,
450 const LocalPointIndexMap& moveLeafMap)
451 : mOffsetMap(offsetMap)
452 , mSourceIndices(sourceIndices)
453 , mSourceLeafManager(sourceLeafManager)
454 , mAttributeIndex(attributeIndex)
455 , mMoveLeafMap(moveLeafMap) { }
456
457 // A CopyIterator is designed to use the indices in a LocalPointIndexMap for this leaf
458 // and match the interface required for AttributeArray::copyValues()
459 struct CopyIterator
460 {
461 CopyIterator(const LeafT& leaf, const IndexPairArray& indices, IndexArray& offsets)
462 : mLeaf(leaf)
463 , mIndices(indices)
464 , mOffsets(offsets) { }
465
466 operator bool() const { return mIndex < static_cast<int>(mIndices.size()); }
467
468 CopyIterator& operator++() { ++mIndex; return *this; }
469
470 Index sourceIndex() const
471 {
472 return mIndices[mIndex].second;
473 }
474
475 Index targetIndex() const
476 {
477 return indexOffsetFromVoxel(mIndices[mIndex].first, mLeaf, mOffsets);
478 }
479
480 private:
481 const LeafT& mLeaf;
482 const IndexPairArray& mIndices;
483 IndexArray& mOffsets;
484 int mIndex = 0;
485 }; // struct CopyIterator
486
487 void operator()(LeafT& leaf, size_t idx) const
488 {
489 const IndexPairArray& moveIndices = mMoveLeafMap[idx];
490 if (moveIndices.empty()) return;
491
492 // extract per-voxel offsets for this leaf
493
494 LeafIndexArray& offsets = mOffsetMap[idx];
495
496 // extract source array that has the same origin as the target leaf
497
498 assert(idx < mSourceIndices.size());
499 const Index sourceLeafOffset(mSourceIndices[idx]);
500 LeafT& sourceLeaf = mSourceLeafManager.leaf(sourceLeafOffset);
501 const auto& sourceArray = sourceLeaf.constAttributeArray(mAttributeIndex);
502 sourceArray.loadData();
503
504 // extract target array and ensure data is out-of-core and non-uniform
505
506 auto& targetArray = leaf.attributeArray(mAttributeIndex);
507 targetArray.loadData();
508 targetArray.expand();
509
510 // perform the copy
511
512 CopyIterator copyIterator(leaf, moveIndices, offsets);
513 targetArray.copyValuesUnsafe(sourceArray, copyIterator);
514 }
515
516 private:
517 LeafOffsetArray& mOffsetMap;
518 const LeafIndexArray& mSourceIndices;
519 LeafManagerT& mSourceLeafManager;
520 const Index mAttributeIndex;
521 const LocalPointIndexMap& mMoveLeafMap;
522 }; // struct LocalMovePointsOp
523
524
525 #else
526
527
528 // The following infrastructure - ArrayProcessor, PerformTypedMoveOp, processTypedArray()
529 // is required to improve AttributeArray copying performance beyond using the virtual function
530 // AttributeArray::set(Index, AttributeArray&, Index). An ABI=6 addition to AttributeArray
531 // improves this by introducing an AttributeArray::copyValues() method to significantly
532 // simplify this logic without incurring the same virtual function cost.
533
534
536 template<typename ValueType, typename OpType>
537 struct ArrayProcessor {
538 static inline void call(OpType& op, const AttributeArray& array) {
539 #ifdef _MSC_VER
540 op.operator()<ValueType>(array);
541 #else
542 op.template operator()<ValueType>(array);
543 #endif
544 }
545 };
546
547
550 template<typename ArrayType, typename OpType>
551 bool
552 processTypedArray(const ArrayType& array, OpType& op)
553 {
554 using namespace openvdb;
555 using namespace openvdb::math;
556 if (array.template hasValueType<bool>()) ArrayProcessor<bool, OpType>::call(op, array);
557 else if (array.template hasValueType<int16_t>()) ArrayProcessor<int16_t, OpType>::call(op, array);
558 else if (array.template hasValueType<int32_t>()) ArrayProcessor<int32_t, OpType>::call(op, array);
559 else if (array.template hasValueType<int64_t>()) ArrayProcessor<int64_t, OpType>::call(op, array);
560 else if (array.template hasValueType<float>()) ArrayProcessor<float, OpType>::call(op, array);
561 else if (array.template hasValueType<double>()) ArrayProcessor<double, OpType>::call(op, array);
562 else if (array.template hasValueType<Vec3<int32_t>>()) ArrayProcessor<Vec3<int32_t>, OpType>::call(op, array);
563 else if (array.template hasValueType<Vec3<float>>()) ArrayProcessor<Vec3<float>, OpType>::call(op, array);
564 else if (array.template hasValueType<Vec3<double>>()) ArrayProcessor<Vec3<double>, OpType>::call(op, array);
565 else if (array.template hasValueType<GroupType>()) ArrayProcessor<GroupType, OpType>::call(op, array);
566 else if (array.template hasValueType<StringIndexType>()) ArrayProcessor<StringIndexType, OpType>::call(op, array);
567 else if (array.template hasValueType<Mat3<float>>()) ArrayProcessor<Mat3<float>, OpType>::call(op, array);
568 else if (array.template hasValueType<Mat3<double>>()) ArrayProcessor<Mat3<double>, OpType>::call(op, array);
569 else if (array.template hasValueType<Mat4<float>>()) ArrayProcessor<Mat4<float>, OpType>::call(op, array);
570 else if (array.template hasValueType<Mat4<double>>()) ArrayProcessor<Mat4<double>, OpType>::call(op, array);
571 else if (array.template hasValueType<Quat<float>>()) ArrayProcessor<Quat<float>, OpType>::call(op, array);
572 else if (array.template hasValueType<Quat<double>>()) ArrayProcessor<Quat<double>, OpType>::call(op, array);
573 else return false;
574 return true;
575 }
576
577
579 struct AttributeHandles
580 {
581 using HandleArray = std::vector<AttributeHandle<int>::Ptr>;
582
583 AttributeHandles(const size_t size)
584 : mHandles() { mHandles.reserve(size); }
585
586 AttributeArray& getArray(const Index leafOffset)
587 {
588 auto* handle = reinterpret_cast<AttributeWriteHandle<int>*>(mHandles[leafOffset].get());
589 assert(handle);
590 return handle->array();
591 }
592
593 const AttributeArray& getConstArray(const Index leafOffset) const
594 {
595 const auto* handle = mHandles[leafOffset].get();
596 assert(handle);
597 return handle->array();
598 }
599
600 template <typename ValueT>
601 AttributeHandle<ValueT>& getHandle(const Index leafOffset)
602 {
603 auto* handle = reinterpret_cast<AttributeHandle<ValueT>*>(mHandles[leafOffset].get());
604 assert(handle);
605 return *handle;
606 }
607
608 template <typename ValueT>
609 AttributeWriteHandle<ValueT>& getWriteHandle(const Index leafOffset)
610 {
611 auto* handle = reinterpret_cast<AttributeWriteHandle<ValueT>*>(mHandles[leafOffset].get());
612 assert(handle);
613 return *handle;
614 }
615
617 struct CacheHandleOp
618 {
619 CacheHandleOp(HandleArray& handles)
620 : mHandles(handles) { }
621
622 template<typename ValueT>
623 void operator()(const AttributeArray& array) const
624 {
625 auto* handleAsInt = reinterpret_cast<AttributeHandle<int>*>(
626 new AttributeHandle<ValueT>(array));
627 mHandles.emplace_back(handleAsInt);
628 }
629
630 private:
631 HandleArray& mHandles;
632 }; // struct CacheHandleOp
633
634 template <typename LeafRangeT>
635 void cache(const LeafRangeT& range, const Index attributeIndex)
636 {
637 using namespace openvdb::math;
638
639 mHandles.clear();
640 CacheHandleOp op(mHandles);
641
642 for (auto leaf = range.begin(); leaf; ++leaf) {
643 const auto& array = leaf->constAttributeArray(attributeIndex);
644 processTypedArray(array, op);
645 }
646 }
647
648 private:
649 HandleArray mHandles;
650 }; // struct AttributeHandles
651
652
653 template <typename TreeT>
654 struct GlobalMovePointsOp
655 {
656 using LeafT = typename TreeT::LeafNodeType;
657 using LeafArrayT = std::vector<LeafT*>;
658 using LeafManagerT = typename tree::LeafManager<TreeT>;
659
660 GlobalMovePointsOp(LeafOffsetArray& offsetMap,
661 AttributeHandles& targetHandles,
662 AttributeHandles& sourceHandles,
663 const Index attributeIndex,
664 const GlobalPointIndexMap& moveLeafMap,
665 const GlobalPointIndexIndices& moveLeafIndices)
666 : mOffsetMap(offsetMap)
667 , mTargetHandles(targetHandles)
668 , mSourceHandles(sourceHandles)
669 , mAttributeIndex(attributeIndex)
670 , mMoveLeafMap(moveLeafMap)
671 , mMoveLeafIndices(moveLeafIndices) { }
672
673 struct PerformTypedMoveOp
674 {
675 PerformTypedMoveOp(AttributeHandles& targetHandles, AttributeHandles& sourceHandles,
676 Index targetOffset, const LeafT& targetLeaf,
677 IndexArray& offsets, const IndexTripleArray& indices,
678 const IndexArray& sortedIndices)
679 : mTargetHandles(targetHandles)
680 , mSourceHandles(sourceHandles)
681 , mTargetOffset(targetOffset)
682 , mTargetLeaf(targetLeaf)
683 , mOffsets(offsets)
684 , mIndices(indices)
685 , mSortedIndices(sortedIndices) { }
686
687 template<typename ValueT>
688 void operator()(const AttributeArray&) const
689 {
690 auto& targetHandle = mTargetHandles.getWriteHandle<ValueT>(mTargetOffset);
691 targetHandle.expand();
692
693 for (const auto& index : mSortedIndices) {
694 const auto& it = mIndices[index];
695 const auto& sourceHandle = mSourceHandles.getHandle<ValueT>(std::get<0>(it));
696 const Index targetIndex = indexOffsetFromVoxel(std::get<1>(it), mTargetLeaf, mOffsets);
697 for (Index i = 0; i < sourceHandle.stride(); i++) {
698 ValueT sourceValue = sourceHandle.get(std::get<2>(it), i);
699 targetHandle.set(targetIndex, i, sourceValue);
700 }
701 }
702 }
703
704 private:
705 AttributeHandles& mTargetHandles;
706 AttributeHandles& mSourceHandles;
707 Index mTargetOffset;
708 const LeafT& mTargetLeaf;
709 IndexArray& mOffsets;
710 const IndexTripleArray& mIndices;
711 const IndexArray& mSortedIndices;
712 }; // struct PerformTypedMoveOp
713
714 void performMove(Index targetOffset, const LeafT& targetLeaf,
715 IndexArray& offsets, const IndexTripleArray& indices,
716 const IndexArray& sortedIndices) const
717 {
718 auto& targetArray = mTargetHandles.getArray(targetOffset);
719 targetArray.loadData();
720 targetArray.expand();
721
722 for (const auto& index : sortedIndices) {
723 const auto& it = indices[index];
724
725 const auto& sourceArray = mSourceHandles.getConstArray(std::get<0>(it));
726
727 const Index sourceOffset = std::get<2>(it);
728 const Index targetOffset = indexOffsetFromVoxel(std::get<1>(it), targetLeaf, offsets);
729
730 targetArray.set(targetOffset, sourceArray, sourceOffset);
731 }
732 }
733
734 void operator()(LeafT& leaf, size_t aIdx) const
735 {
736 const Index idx(static_cast<Index>(aIdx));
737 const auto& moveIndices = mMoveLeafMap[aIdx];
738 if (moveIndices.empty()) return;
739 const auto& sortedIndices = mMoveLeafIndices[aIdx];
740
741 // extract per-voxel offsets for this leaf
742
743 auto& offsets = mOffsetMap[aIdx];
744
745 const auto& array = leaf.constAttributeArray(mAttributeIndex);
746
747 PerformTypedMoveOp op(mTargetHandles, mSourceHandles, idx, leaf, offsets,
748 moveIndices, sortedIndices);
749 if (!processTypedArray(array, op)) {
750 this->performMove(idx, leaf, offsets, moveIndices, sortedIndices);
751 }
752 }
753
754 private:
755 LeafOffsetArray& mOffsetMap;
756 AttributeHandles& mTargetHandles;
757 AttributeHandles& mSourceHandles;
758 const Index mAttributeIndex;
759 const GlobalPointIndexMap& mMoveLeafMap;
760 const GlobalPointIndexIndices& mMoveLeafIndices;
761 }; // struct GlobalMovePointsOp
762
763
764 template <typename TreeT>
765 struct LocalMovePointsOp
766 {
767 using LeafT = typename TreeT::LeafNodeType;
768 using LeafArrayT = std::vector<LeafT*>;
769 using LeafManagerT = typename tree::LeafManager<TreeT>;
770
771 LocalMovePointsOp( LeafOffsetArray& offsetMap,
772 AttributeHandles& targetHandles,
773 const LeafIndexArray& sourceIndices,
774 AttributeHandles& sourceHandles,
775 const Index attributeIndex,
776 const LocalPointIndexMap& moveLeafMap)
777 : mOffsetMap(offsetMap)
778 , mTargetHandles(targetHandles)
779 , mSourceIndices(sourceIndices)
780 , mSourceHandles(sourceHandles)
781 , mAttributeIndex(attributeIndex)
782 , mMoveLeafMap(moveLeafMap) { }
783
784 struct PerformTypedMoveOp
785 {
786 PerformTypedMoveOp(AttributeHandles& targetHandles, AttributeHandles& sourceHandles,
787 Index targetOffset, Index sourceOffset, const LeafT& targetLeaf,
788 IndexArray& offsets, const IndexPairArray& indices)
789 : mTargetHandles(targetHandles)
790 , mSourceHandles(sourceHandles)
791 , mTargetOffset(targetOffset)
792 , mSourceOffset(sourceOffset)
793 , mTargetLeaf(targetLeaf)
794 , mOffsets(offsets)
795 , mIndices(indices) { }
796
797 template<typename ValueT>
798 void operator()(const AttributeArray&) const
799 {
800 auto& targetHandle = mTargetHandles.getWriteHandle<ValueT>(mTargetOffset);
801 const auto& sourceHandle = mSourceHandles.getHandle<ValueT>(mSourceOffset);
802
803 targetHandle.expand();
804
805 for (const auto& it : mIndices) {
806 const Index targetIndex = indexOffsetFromVoxel(it.first, mTargetLeaf, mOffsets);
807 for (Index i = 0; i < sourceHandle.stride(); i++) {
808 ValueT sourceValue = sourceHandle.get(it.second, i);
809 targetHandle.set(targetIndex, i, sourceValue);
810 }
811 }
812 }
813
814 private:
815 AttributeHandles& mTargetHandles;
816 AttributeHandles& mSourceHandles;
817 Index mTargetOffset;
818 Index mSourceOffset;
819 const LeafT& mTargetLeaf;
820 IndexArray& mOffsets;
821 const IndexPairArray& mIndices;
822 }; // struct PerformTypedMoveOp
823
824 template <typename ValueT>
825 void performTypedMove(Index sourceOffset, Index targetOffset, const LeafT& targetLeaf,
826 IndexArray& offsets, const IndexPairArray& indices) const
827 {
828 auto& targetHandle = mTargetHandles.getWriteHandle<ValueT>(targetOffset);
829 const auto& sourceHandle = mSourceHandles.getHandle<ValueT>(sourceOffset);
830
831 targetHandle.expand();
832
833 for (const auto& it : indices) {
834 const Index tgtOffset = indexOffsetFromVoxel(it.first, targetLeaf, offsets);
835 for (Index i = 0; i < sourceHandle.stride(); i++) {
836 ValueT sourceValue = sourceHandle.get(it.second, i);
837 targetHandle.set(tgtOffset, i, sourceValue);
838 }
839 }
840 }
841
842 void performMove(Index targetOffset, Index sourceOffset, const LeafT& targetLeaf,
843 IndexArray& offsets, const IndexPairArray& indices) const
844 {
845 auto& targetArray = mTargetHandles.getArray(targetOffset);
846 const auto& sourceArray = mSourceHandles.getConstArray(sourceOffset);
847
848 for (const auto& it : indices) {
849 const Index sourceOffset = it.second;
850 const Index targetOffset = indexOffsetFromVoxel(it.first, targetLeaf, offsets);
851
852 targetArray.set(targetOffset, sourceArray, sourceOffset);
853 }
854 }
855
856 void operator()(const LeafT& leaf, size_t aIdx) const
857 {
858 const Index idx(static_cast<Index>(aIdx));
859 const auto& moveIndices = mMoveLeafMap.at(aIdx);
860 if (moveIndices.empty()) return;
861
862 // extract target leaf and per-voxel offsets for this leaf
863
864 auto& offsets = mOffsetMap[aIdx];
865
866 // extract source leaf that has the same origin as the target leaf (if any)
867
868 assert(aIdx < mSourceIndices.size());
869 const Index sourceOffset(mSourceIndices[aIdx]);
870
871 const auto& array = leaf.constAttributeArray(mAttributeIndex);
872
873 PerformTypedMoveOp op(mTargetHandles, mSourceHandles,
874 idx, sourceOffset, leaf, offsets, moveIndices);
875 if (!processTypedArray(array, op)) {
876 this->performMove(idx, sourceOffset, leaf, offsets, moveIndices);
877 }
878 }
879
880 private:
881 LeafOffsetArray& mOffsetMap;
882 AttributeHandles& mTargetHandles;
883 const LeafIndexArray& mSourceIndices;
884 AttributeHandles& mSourceHandles;
885 const Index mAttributeIndex;
886 const LocalPointIndexMap& mMoveLeafMap;
887 }; // struct LocalMovePointsOp
888
889
890 #endif // OPENVDB_ABI_VERSION_NUMBER >= 6
891
892
893 } // namespace point_move_internal
894
895
897
898
899 template <typename PointDataGridT, typename DeformerT, typename FilterT>
900 inline void movePoints( PointDataGridT& points,
901 const math::Transform& transform,
902 DeformerT& deformer,
903 const FilterT& filter,
904 future::Advect* objectNotInUse,
905 bool threaded)
906 {
907 using LeafIndex = point_move_internal::LeafIndex;
908 using PointDataTreeT = typename PointDataGridT::TreeType;
909 using LeafT = typename PointDataTreeT::LeafNodeType;
910 using LeafManagerT = typename tree::LeafManager<PointDataTreeT>;
911
912 using namespace point_move_internal;
913
914 // this object is for future use only
915 assert(!objectNotInUse);
916 (void)objectNotInUse;
917
918 PointDataTreeT& tree = points.tree();
919
920 // early exit if no LeafNodes
921
922 PointDataTree::LeafCIter iter = tree.cbeginLeaf();
923
924 if (!iter) return;
925
926 // build voxel topology taking into account any point group deletion
927
928 auto newPoints = point_mask_internal::convertPointsToScalar<PointDataGrid>(
929 points, transform, filter, deformer, threaded);
930 auto& newTree = newPoints->tree();
931
932 // create leaf managers for both trees
933
934 LeafManagerT sourceLeafManager(tree);
935 LeafManagerT targetLeafManager(newTree);
936
937 // extract the existing attribute set
938 const auto& existingAttributeSet = points.tree().cbeginLeaf()->attributeSet();
939
940 // build a coord -> index map for looking up target leafs by origin and a faster
941 // unordered map for finding the source index from a target index
942
943 LeafMap targetLeafMap;
944 LeafIndexArray sourceIndices(targetLeafManager.leafCount(),
945 std::numeric_limits<LeafIndex>::max());
946
947 LeafOffsetArray offsetMap(targetLeafManager.leafCount());
948
949 {
950 LeafMap sourceLeafMap;
951 auto sourceRange = sourceLeafManager.leafRange();
952 for (auto leaf = sourceRange.begin(); leaf; ++leaf) {
953 sourceLeafMap.insert({leaf->origin(), LeafIndex(static_cast<LeafIndex>(leaf.pos()))});
954 }
955 auto targetRange = targetLeafManager.leafRange();
956 for (auto leaf = targetRange.begin(); leaf; ++leaf) {
957 targetLeafMap.insert({leaf->origin(), LeafIndex(static_cast<LeafIndex>(leaf.pos()))});
958 }
959
960 // acquire registry lock to avoid locking when appending attributes in parallel
961
962 AttributeArray::ScopedRegistryLock lock;
963
964 // perform four independent per-leaf operations in parallel
965 targetLeafManager.foreach(
966 [&](LeafT& leaf, size_t idx) {
967 // map frequency => cumulative histogram
968 auto* buffer = leaf.buffer().data();
969 for (Index i = 1; i < leaf.buffer().size(); i++) {
970 buffer[i] = buffer[i-1] + buffer[i];
971 }
972 // replace attribute set with a copy of the existing one
973 leaf.replaceAttributeSet(
974 new AttributeSet(existingAttributeSet, leaf.getLastValue(), &lock),
975 /*allowMismatchingDescriptors=*/true);
976 // store the index of the source leaf in a corresponding target leaf array
977 const auto it = sourceLeafMap.find(leaf.origin());
978 if (it != sourceLeafMap.end()) {
979 sourceIndices[idx] = it->second;
980 }
981 // allocate offset maps
982 offsetMap[idx].resize(LeafT::SIZE);
983 },
984 threaded);
985 }
986
987 // moving leaf
988
989 GlobalPointIndexMap globalMoveLeafMap(targetLeafManager.leafCount());
990 LocalPointIndexMap localMoveLeafMap(targetLeafManager.leafCount());
991
992 // build global and local move leaf maps and update local positions
993
994 if (filter.state() == index::ALL) {
995 NullFilter nullFilter;
996 BuildMoveMapsOp<DeformerT, PointDataTreeT, NullFilter> op(deformer,
997 globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
998 transform, points.transform(), nullFilter);
999 sourceLeafManager.foreach(op, threaded);
1000 } else {
1001 BuildMoveMapsOp<DeformerT, PointDataTreeT, FilterT> op(deformer,
1002 globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
1003 transform, points.transform(), filter);
1004 sourceLeafManager.foreach(op, threaded);
1005 }
1006
1007 // build a sorted index vector for each leaf that references the global move map
1008 // indices in order of their source leafs and voxels to ensure determinism in the
1009 // resulting point orders
1010
1011 GlobalPointIndexIndices globalMoveLeafIndices(globalMoveLeafMap.size());
1012
1013 targetLeafManager.foreach(
1014 [&](LeafT& /*leaf*/, size_t idx) {
1015 const IndexTripleArray& moveIndices = globalMoveLeafMap[idx];
1016 if (moveIndices.empty()) return;
1017
1018 IndexArray& sortedIndices = globalMoveLeafIndices[idx];
1019 sortedIndices.resize(moveIndices.size());
1020 std::iota(std::begin(sortedIndices), std::end(sortedIndices), 0);
1021 std::sort(std::begin(sortedIndices), std::end(sortedIndices),
1022 [&](int i, int j)
1023 {
1024 const Index& indexI0(std::get<0>(moveIndices[i]));
1025 const Index& indexJ0(std::get<0>(moveIndices[j]));
1026 if (indexI0 < indexJ0) return true;
1027 if (indexI0 > indexJ0) return false;
1028 return std::get<2>(moveIndices[i]) < std::get<2>(moveIndices[j]);
1029 }
1030 );
1031 },
1032 threaded);
1033
1034 #if OPENVDB_ABI_VERSION_NUMBER < 6
1035 // initialize attribute handles
1036 AttributeHandles sourceHandles(sourceLeafManager.leafCount());
1037 AttributeHandles targetHandles(targetLeafManager.leafCount());
1038 #endif
1039
1040 for (const auto& it : existingAttributeSet.descriptor().map()) {
1041
1042 const Index attributeIndex = static_cast<Index>(it.second);
1043
1044 // zero offsets
1045 targetLeafManager.foreach(
1046 [&offsetMap](const LeafT& /*leaf*/, size_t idx) {
1047 std::fill(offsetMap[idx].begin(), offsetMap[idx].end(), 0);
1048 },
1049 threaded);
1050
1051 #if OPENVDB_ABI_VERSION_NUMBER >= 6
1052
1053 // move points between leaf nodes
1054
1055 GlobalMovePointsOp<PointDataTreeT> globalMoveOp(offsetMap,
1056 sourceLeafManager, attributeIndex, globalMoveLeafMap, globalMoveLeafIndices);
1057 targetLeafManager.foreach(globalMoveOp, threaded);
1058
1059 // move points within leaf nodes
1060
1061 LocalMovePointsOp<PointDataTreeT> localMoveOp(offsetMap,
1062 sourceIndices, sourceLeafManager, attributeIndex, localMoveLeafMap);
1063 targetLeafManager.foreach(localMoveOp, threaded);
1064 #else
1065 // cache attribute handles
1066
1067 sourceHandles.cache(sourceLeafManager.leafRange(), attributeIndex);
1068 targetHandles.cache(targetLeafManager.leafRange(), attributeIndex);
1069
1070 // move points between leaf nodes
1071
1072 GlobalMovePointsOp<PointDataTreeT> globalMoveOp(offsetMap, targetHandles,
1073 sourceHandles, attributeIndex, globalMoveLeafMap, globalMoveLeafIndices);
1074 targetLeafManager.foreach(globalMoveOp, threaded);
1075
1076 // move points within leaf nodes
1077
1078 LocalMovePointsOp<PointDataTreeT> localMoveOp(offsetMap, targetHandles,
1079 sourceIndices, sourceHandles,
1080 attributeIndex, localMoveLeafMap);
1081 targetLeafManager.foreach(localMoveOp, threaded);
1082 #endif // OPENVDB_ABI_VERSION_NUMBER >= 6
1083 }
1084
1085 points.setTree(newPoints->treePtr());
1086 }
1087
1088
1089 template <typename PointDataGridT, typename DeformerT, typename FilterT>
1090 inline void movePoints( PointDataGridT& points,
1091 DeformerT& deformer,
1092 const FilterT& filter,
1093 future::Advect* objectNotInUse,
1094 bool threaded)
1095 {
1096 movePoints(points, points.transform(), deformer, filter, objectNotInUse, threaded);
1097 }
1098
1099
1101
1102
1103 template <typename T>
1104 CachedDeformer<T>::CachedDeformer(Cache& cache)
1105 : mCache(cache) { }
1106
1107
1108 template <typename T>
1109 template <typename PointDataGridT, typename DeformerT, typename FilterT>
1110 void CachedDeformer<T>::evaluate(PointDataGridT& grid, DeformerT& deformer, const FilterT& filter,
1111 bool threaded)
1112 {
1113 using TreeT = typename PointDataGridT::TreeType;
1114 using LeafT = typename TreeT::LeafNodeType;
1115 using LeafManagerT = typename tree::LeafManager<TreeT>;
1116 LeafManagerT leafManager(grid.tree());
1117
1118 // initialize cache
1119 auto& leafs = mCache.leafs;
1120 leafs.resize(leafManager.leafCount());
1121
1122 const auto& transform = grid.transform();
1123
1124 // insert deformed positions into the cache
1125
1126 auto cachePositionsOp = [&](const LeafT& leaf, size_t idx) {
1127
1128 const Index64 totalPointCount = leaf.pointCount();
1129 if (totalPointCount == 0) return;
1130
1131 // deformer is copied to ensure that it is unique per-thread
1132
1133 DeformerT newDeformer(deformer);
1134
1135 newDeformer.reset(leaf, idx);
1136
1137 auto handle = AttributeHandle<Vec3f>::create(leaf.constAttributeArray("P"));
1138
1139 auto& cache = leafs[idx];
1140 cache.clear();
1141
1142 // only insert into a vector directly if the filter evaluates all points
1143 // and all points are stored in active voxels
1144 const bool useVector = filter.state() == index::ALL &&
1145 (leaf.isDense() || (leaf.onPointCount() == leaf.pointCount()));
1146 if (useVector) {
1147 cache.vecData.resize(totalPointCount);
1148 }
1149
1150 for (auto iter = leaf.beginIndexOn(filter); iter; iter++) {
1151
1152 // extract index-space position and apply index-space deformation (if defined)
1153
1154 Vec3d position = handle->get(*iter) + iter.getCoord().asVec3d();
1155
1156 // if deformer is designed to be used in index-space, perform deformation prior
1157 // to transforming position to world-space, otherwise perform deformation afterwards
1158
1159 if (DeformerTraits<DeformerT>::IndexSpace) {
1160 newDeformer.apply(position, iter);
1161 position = transform.indexToWorld(position);
1162 }
1163 else {
1164 position = transform.indexToWorld(position);
1165 newDeformer.apply(position, iter);
1166 }
1167
1168 // insert new position into the cache
1169
1170 if (useVector) {
1171 cache.vecData[*iter] = static_cast<Vec3T>(position);
1172 }
1173 else {
1174 cache.mapData.insert({*iter, static_cast<Vec3T>(position)});
1175 }
1176 }
1177
1178 // store the total number of points to allow use of an expanded vector on access
1179
1180 if (!cache.mapData.empty()) {
1181 cache.totalSize = static_cast<Index>(totalPointCount);
1182 }
1183 };
1184
1185 leafManager.foreach(cachePositionsOp, threaded);
1186 }
1187
1188
1189 template <typename T>
1190 template <typename LeafT>
1191 void CachedDeformer<T>::reset(const LeafT& /*leaf*/, size_t idx)
1192 {
1193 if (idx >= mCache.leafs.size()) {
1194 if (mCache.leafs.empty()) {
1195 throw IndexError("No leafs in cache, perhaps CachedDeformer has not been evaluated?");
1196 } else {
1197 throw IndexError("Leaf index is out-of-range of cache leafs.");
1198 }
1199 }
1200 auto& cache = mCache.leafs[idx];
1201 if (!cache.mapData.empty()) {
1202 mLeafMap = &cache.mapData;
1203 mLeafVec = nullptr;
1204 }
1205 else {
1206 mLeafVec = &cache.vecData;
1207 mLeafMap = nullptr;
1208 }
1209 }
1210
1211
1212 template <typename T>
1213 template <typename IndexIterT>
1214 void CachedDeformer<T>::apply(Vec3d& position, const IndexIterT& iter) const
1215 {
1216 assert(*iter >= 0);
1217
1218 if (mLeafMap) {
1219 auto it = mLeafMap->find(*iter);
1220 if (it == mLeafMap->end()) return;
1221 position = static_cast<openvdb::Vec3d>(it->second);
1222 }
1223 else {
1224 assert(mLeafVec);
1225
1226 if (mLeafVec->empty()) return;
1227 assert(*iter < mLeafVec->size());
1228 position = static_cast<openvdb::Vec3d>((*mLeafVec)[*iter]);
1229 }
1230 }
1231
1232
1233 } // namespace points
1234 } // namespace OPENVDB_VERSION_NAME
1235 } // namespace openvdb
1236
1237 #endif // OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED
openvdb::v7_0::points::point_move_internal::BuildMoveMapsOp::LeafArrayT
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:181
openvdb::v7_0::points::point_move_internal::indexOffsetFromVoxel
Index indexOffsetFromVoxel(const Index voxelOffset, const LeafT &leaf, IndexArray &offsets)
Definition: PointMove.h:272
openvdb::v7_0::points::CachedDeformer::Cache::Leaf::mapData
LeafMapT mapData
Definition: PointMove.h:119
openvdb::v7_0::points::point_move_internal::GlobalMovePointsOp::CopyIterator::sourceIndex
Index sourceIndex() const
Definition: PointMove.h:342
openvdb::v7_0::math::Transform::indexToWorld
Vec3d indexToWorld(const Vec3d &xyz) const
Apply this transformation to the given coordinates.
Definition: Transform.h:108
openvdb::v7_0::points::point_move_internal::IndexTripleArray
tbb::concurrent_vector< IndexTriple > IndexTripleArray
Definition: PointMove.h:164
openvdb::v7_0::points::CachedDeformer::apply
void apply(Vec3d &position, const IndexIterT &iter) const
Retrieve the new position from the cache.
Definition: PointMove.h:1214
openvdb::v7_0::points::point_move_internal::LeafIndex
Index32 LeafIndex
Definition: PointMove.h:93
openvdb::v7_0::points::point_move_internal::GlobalMovePointsOp::operator()
void operator()(LeafT &leaf, size_t idx) const
Definition: PointMove.h:381
openvdb::v7_0::points::point_move_internal::GlobalMovePointsOp::CopyIterator::leafIndex
Index leafIndex(Index i) const
Definition: PointMove.h:334
openvdb::v7_0::points::point_move_internal::BuildMoveMapsOp::LeafManagerT
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:182
openvdb::v7_0::points::point_move_internal::BuildMoveMapsOp::BuildMoveMapsOp
BuildMoveMapsOp(const DeformerT &deformer, GlobalPointIndexMap &globalMoveLeafMap, LocalPointIndexMap &localMoveLeafMap, const LeafMap &targetLeafMap, const math::Transform &targetTransform, const math::Transform &sourceTransform, const FilterT &filter)
Definition: PointMove.h:184
openvdb::v7_0::points::point_move_internal::GlobalMovePointsOp::AttributeArrays
std::vector< AttributeArray * > AttributeArrays
Definition: PointMove.h:295
openvdb::v7_0::points::point_move_internal::LocalMovePointsOp::LeafManagerT
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:443
openvdb::v7_0::points::point_move_internal::LocalMovePointsOp::operator()
void operator()(LeafT &leaf, size_t idx) const
Definition: PointMove.h:487
openvdb::v7_0::points::point_move_internal::LocalMovePointsOp::LeafArrayT
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:442
openvdb::v7_0::points::CachedDeformer::Cache
Definition: PointMove.h:107
openvdb::v7_0::points::CachedDeformer::LeafMapT
std::unordered_map< LeafIndex, Vec3T > LeafMapT
Definition: PointMove.h:104
openvdb::v7_0::points::CachedDeformer::Cache::Leaf
Definition: PointMove.h:109
openvdb::v7_0::points::AttributeArray
Base class for storing attribute data.
Definition: AttributeArray.h:92
openvdb::v7_0::points::point_move_internal::GlobalPointIndexIndices
std::vector< IndexArray > GlobalPointIndexIndices
Definition: PointMove.h:166
openvdb::v7_0::points::CachedDeformer::Vec3T
typename math::Vec3< T > Vec3T
Definition: PointMove.h:102
openvdb::v7_0::points::DeformerTraits
Deformer Traits for optionally configuring deformers to be applied in index-space....
Definition: PointMask.h:76
openvdb::v7_0::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:25
PointMask.h
Methods for extracting masks from VDB Point grids.
openvdb::v7_0::points::point_move_internal::LocalMovePointsOp::CopyIterator
Definition: PointMove.h:459
openvdb::v7_0::math::Quat
Definition: Mat.h:169
openvdb::v7_0::points::point_move_internal::LocalMovePointsOp::CopyIterator::sourceIndex
Index sourceIndex() const
Definition: PointMove.h:470
openvdb::v7_0::points::point_move_internal::GlobalMovePointsOp::LeafManagerT
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:294
openvdb::v7_0::points::point_move_internal::LocalMovePointsOp::CopyIterator::targetIndex
Index targetIndex() const
Definition: PointMove.h:475
openvdb::v7_0::points::CachedDeformer::evaluate
void evaluate(PointDataGridT &grid, DeformerT &deformer, const FilterT &filter, bool threaded=true)
Definition: PointMove.h:1110
openvdb::v7_0::math::Coord::round
static Coord round(const Vec3< T > &xyz)
Return xyz rounded to the closest integer coordinates (cell centered conversion).
Definition: Coord.h:51
openvdb::v7_0::points::point_move_internal::LocalMovePointsOp::LocalMovePointsOp
LocalMovePointsOp(LeafOffsetArray &offsetMap, const LeafIndexArray &sourceIndices, LeafManagerT &sourceLeafManager, const Index attributeIndex, const LocalPointIndexMap &moveLeafMap)
Definition: PointMove.h:446
openvdb::v7_0::points::point_move_internal::BuildMoveMapsOp
Definition: PointMove.h:178
openvdb::v7_0::points::point_move_internal::LocalMovePointsOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:441
openvdb::v7_0::points::point_move_internal::LocalMovePointsOp::CopyIterator::CopyIterator
CopyIterator(const LeafT &leaf, const IndexPairArray &indices, IndexArray &offsets)
Definition: PointMove.h:461
openvdb::v7_0::points::point_move_internal::LocalMovePointsOp::AttributeArrays
std::vector< AttributeArray * > AttributeArrays
Definition: PointMove.h:444
openvdb::v7_0::points::point_move_internal::GlobalMovePointsOp::CopyIterator::targetIndex
Index targetIndex() const
Definition: PointMove.h:348
openvdb::v7_0::points::point_move_internal::LeafIndexArray
std::vector< LeafIndex > LeafIndexArray
Definition: PointMove.h:172
openvdb::v7_0::points::point_move_internal::GlobalMovePointsOp::CopyIterator::reset
void reset(Index startIndex, Index endIndex)
Definition: PointMove.h:321
openvdb::v7_0::math::Vec3d
Vec3< double > Vec3d
Definition: Vec3.h:662
openvdb::v7_0::points::point_move_internal::IndexPairArray
std::vector< IndexPair > IndexPairArray
Definition: PointMove.h:169
openvdb::v7_0::points::point_move_internal::LocalMovePointsOp
Definition: PointMove.h:439
openvdb::v7_0::points::point_move_internal::GlobalMovePointsOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:292
openvdb::v7_0::points::CachedDeformer::Cache::Leaf::clear
void clear()
clear data buffers and reset counter
Definition: PointMove.h:112
openvdb::v7_0::math::Mat4
4x4 -matrix class.
Definition: Mat3.h:22
openvdb::v7_0::points::CachedDeformer::LeafVecT
std::vector< Vec3T > LeafVecT
Definition: PointMove.h:103
openvdb::v7_0::points::point_move_internal::BuildMoveMapsOp::operator()
void operator()(LeafT &leaf, size_t idx) const
Definition: PointMove.h:199
PointDataGrid.h
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
openvdb::v7_0::points::point_move_internal::IndexPair
std::pair< Index, Index > IndexPair
Definition: PointMove.h:168
openvdb::v7_0::points::point_move_internal::IndexTriple
std::tuple< LeafIndex, Index, Index > IndexTriple
Definition: PointMove.h:163
openvdb::v7_0::tree::LeafIteratorBase
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels)
Definition: TreeIterator.h:1191
openvdb::v7_0::points::AttributeWriteHandle
Write-able version of AttributeHandle.
Definition: AttributeArray.h:920
openvdb::v7_0::points::point_move_internal::GlobalMovePointsOp::GlobalMovePointsOp
GlobalMovePointsOp(LeafOffsetArray &offsetMap, LeafManagerT &sourceLeafManager, const Index attributeIndex, const GlobalPointIndexMap &moveLeafMap, const GlobalPointIndexIndices &moveLeafIndices)
Definition: PointMove.h:297
openvdb::v7_0::math::Coord::asVec3d
Vec3d asVec3d() const
Definition: Coord.h:144
openvdb::v7_0::points::point_move_internal::GlobalMovePointsOp::CopyIterator
Definition: PointMove.h:310
openvdb::v7_0::points::AttributeHandle::create
static Ptr create(const AttributeArray &array, const bool collapseOnDestruction=true)
Definition: AttributeArray.h:2132
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:82
openvdb::v7_0::tools::composite::max
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:106
openvdb::v7_0::points::point_move_internal::GlobalMovePointsOp::LeafArrayT
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:293
openvdb::v7_0::points::CachedDeformer::Cache::leafs
std::vector< Leaf > leafs
Definition: PointMove.h:123
openvdb::v7_0::points::CachedDeformer::reset
void reset(const LeafT &leaf, size_t idx)
Definition: PointMove.h:1191
openvdb::v7_0::math::Vec3
Definition: Mat.h:170
openvdb::v7_0::points::CachedDeformer::Cache::Leaf::vecData
LeafVecT vecData
Definition: PointMove.h:118
openvdb::v7_0::points::point_move_internal::GlobalMovePointsOp
Definition: PointMove.h:290
openvdb::v7_0::points::future::Advect
Definition: PointMove.h:59
openvdb::v7_0::points::point_move_internal::LocalPointIndexMap
std::vector< IndexPairArray > LocalPointIndexMap
Definition: PointMove.h:170
openvdb::v7_0::points::point_move_internal::GlobalMovePointsOp::CopyIterator::CopyIterator
CopyIterator(const LeafT &leaf, const IndexArray &sortedIndices, const IndexTripleArray &moveIndices, IndexArray &offsets)
Definition: PointMove.h:312
openvdb::v7_0::math::Mat3
3x3 matrix class.
Definition: Mat3.h:28
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:154
openvdb::v7_0::points::AttributeArray::ScopedRegistryLock
Definition: AttributeArray.h:119
openvdb::v7_0::points::NullFilter
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:50
openvdb::v7_0::points::movePoints
void movePoints(PointDataGridT &points, const math::Transform &transform, DeformerT &deformer, const FilterT &filter=NullFilter(), future::Advect *objectNotInUse=nullptr, bool threaded=true)
Move points in a PointDataGrid using a custom deformer and a new transform.
Definition: PointMove.h:900
openvdb::v7_0::points::AttributeSet
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:35
openvdb::v7_0::points::point_move_internal::BuildMoveMapsOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:180
openvdb::v7_0::Index
Index32 Index
Definition: Types.h:31
openvdb::v7_0::IndexError
Definition: Exceptions.h:57
openvdb::v7_0::points::point_move_internal::IndexArray
std::vector< Index > IndexArray
Definition: PointMove.h:161
openvdb::v7_0::math::Transform
Definition: Transform.h:39
openvdb::v7_0::points::CachedDeformer
A Deformer that caches the resulting positions from evaluating another Deformer.
Definition: PointMove.h:98
openvdb::v7_0::points::point_move_internal::LeafOffsetArray
std::vector< LeafIndexArray > LeafOffsetArray
Definition: PointMove.h:173
openvdb::v7_0::points::point_move_internal::LocalMovePointsOp::CopyIterator::operator++
CopyIterator & operator++()
Definition: PointMove.h:468
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
Definition: IndexIterator.h:43
openvdb::v7_0::Index32
uint32_t Index32
Definition: Types.h:29
openvdb::v7_0::points::point_move_internal::LeafMap
std::unordered_map< Coord, LeafIndex > LeafMap
Definition: PointMove.h:174
openvdb
Definition: Exceptions.h:13
openvdb::v7_0::points::point_move_internal::GlobalMovePointsOp::CopyIterator::operator++
CopyIterator & operator++()
Definition: PointMove.h:328
openvdb::v7_0::Index64
uint64_t Index64
Definition: Types.h:30
openvdb.h
openvdb::v7_0::points::CachedDeformer::LeafIndex
point_move_internal::LeafIndex LeafIndex
Definition: PointMove.h:101
openvdb::v7_0::points::point_move_internal::GlobalPointIndexMap
std::vector< IndexTripleArray > GlobalPointIndexMap
Definition: PointMove.h:165