OpenVDB: PointMove.h Source File

OpenVDB 8.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 op.template operator()<ValueType>(array);
540 }
541 };
542
543
546 template<typename ArrayType, typename OpType>
547 bool
548 processTypedArray(const ArrayType& array, OpType& op)
549 {
550 using namespace openvdb;
551 using namespace openvdb::math;
552 if (array.template hasValueType<bool>()) ArrayProcessor<bool, OpType>::call(op, array);
553 else if (array.template hasValueType<int16_t>()) ArrayProcessor<int16_t, OpType>::call(op, array);
554 else if (array.template hasValueType<int32_t>()) ArrayProcessor<int32_t, OpType>::call(op, array);
555 else if (array.template hasValueType<int64_t>()) ArrayProcessor<int64_t, OpType>::call(op, array);
556 else if (array.template hasValueType<float>()) ArrayProcessor<float, OpType>::call(op, array);
557 else if (array.template hasValueType<double>()) ArrayProcessor<double, OpType>::call(op, array);
558 else if (array.template hasValueType<Vec3<int32_t>>()) ArrayProcessor<Vec3<int32_t>, OpType>::call(op, array);
559 else if (array.template hasValueType<Vec3<float>>()) ArrayProcessor<Vec3<float>, OpType>::call(op, array);
560 else if (array.template hasValueType<Vec3<double>>()) ArrayProcessor<Vec3<double>, OpType>::call(op, array);
561 else if (array.template hasValueType<GroupType>()) ArrayProcessor<GroupType, OpType>::call(op, array);
562 else if (array.template hasValueType<Index>()) ArrayProcessor<Index, OpType>::call(op, array);
563 else if (array.template hasValueType<Mat3<float>>()) ArrayProcessor<Mat3<float>, OpType>::call(op, array);
564 else if (array.template hasValueType<Mat3<double>>()) ArrayProcessor<Mat3<double>, OpType>::call(op, array);
565 else if (array.template hasValueType<Mat4<float>>()) ArrayProcessor<Mat4<float>, OpType>::call(op, array);
566 else if (array.template hasValueType<Mat4<double>>()) ArrayProcessor<Mat4<double>, OpType>::call(op, array);
567 else if (array.template hasValueType<Quat<float>>()) ArrayProcessor<Quat<float>, OpType>::call(op, array);
568 else if (array.template hasValueType<Quat<double>>()) ArrayProcessor<Quat<double>, OpType>::call(op, array);
569 else return false;
570 return true;
571 }
572
573
575 struct AttributeHandles
576 {
577 using HandleArray = std::vector<AttributeHandle<int>::Ptr>;
578
579 AttributeHandles(const size_t size)
580 : mHandles() { mHandles.reserve(size); }
581
582 AttributeArray& getArray(const Index leafOffset)
583 {
584 auto* handle = reinterpret_cast<AttributeWriteHandle<int>*>(mHandles[leafOffset].get());
585 assert(handle);
586 return handle->array();
587 }
588
589 const AttributeArray& getConstArray(const Index leafOffset) const
590 {
591 const auto* handle = mHandles[leafOffset].get();
592 assert(handle);
593 return handle->array();
594 }
595
596 template <typename ValueT>
597 AttributeHandle<ValueT>& getHandle(const Index leafOffset)
598 {
599 auto* handle = reinterpret_cast<AttributeHandle<ValueT>*>(mHandles[leafOffset].get());
600 assert(handle);
601 return *handle;
602 }
603
604 template <typename ValueT>
605 AttributeWriteHandle<ValueT>& getWriteHandle(const Index leafOffset)
606 {
607 auto* handle = reinterpret_cast<AttributeWriteHandle<ValueT>*>(mHandles[leafOffset].get());
608 assert(handle);
609 return *handle;
610 }
611
613 struct CacheHandleOp
614 {
615 CacheHandleOp(HandleArray& handles)
616 : mHandles(handles) { }
617
618 template<typename ValueT>
619 void operator()(const AttributeArray& array) const
620 {
621 auto* handleAsInt = reinterpret_cast<AttributeHandle<int>*>(
622 new AttributeHandle<ValueT>(array));
623 mHandles.emplace_back(handleAsInt);
624 }
625
626 private:
627 HandleArray& mHandles;
628 }; // struct CacheHandleOp
629
630 template <typename LeafRangeT>
631 void cache(const LeafRangeT& range, const Index attributeIndex)
632 {
633 using namespace openvdb::math;
634
635 mHandles.clear();
636 CacheHandleOp op(mHandles);
637
638 for (auto leaf = range.begin(); leaf; ++leaf) {
639 const auto& array = leaf->constAttributeArray(attributeIndex);
640 processTypedArray(array, op);
641 }
642 }
643
644 private:
645 HandleArray mHandles;
646 }; // struct AttributeHandles
647
648
649 template <typename TreeT>
650 struct GlobalMovePointsOp
651 {
652 using LeafT = typename TreeT::LeafNodeType;
653 using LeafArrayT = std::vector<LeafT*>;
654 using LeafManagerT = typename tree::LeafManager<TreeT>;
655
656 GlobalMovePointsOp(LeafOffsetArray& offsetMap,
657 AttributeHandles& targetHandles,
658 AttributeHandles& sourceHandles,
659 const Index attributeIndex,
660 const GlobalPointIndexMap& moveLeafMap,
661 const GlobalPointIndexIndices& moveLeafIndices)
662 : mOffsetMap(offsetMap)
663 , mTargetHandles(targetHandles)
664 , mSourceHandles(sourceHandles)
665 , mAttributeIndex(attributeIndex)
666 , mMoveLeafMap(moveLeafMap)
667 , mMoveLeafIndices(moveLeafIndices) { }
668
669 struct PerformTypedMoveOp
670 {
671 PerformTypedMoveOp(AttributeHandles& targetHandles, AttributeHandles& sourceHandles,
672 Index targetOffset, const LeafT& targetLeaf,
673 IndexArray& offsets, const IndexTripleArray& indices,
674 const IndexArray& sortedIndices)
675 : mTargetHandles(targetHandles)
676 , mSourceHandles(sourceHandles)
677 , mTargetOffset(targetOffset)
678 , mTargetLeaf(targetLeaf)
679 , mOffsets(offsets)
680 , mIndices(indices)
681 , mSortedIndices(sortedIndices) { }
682
683 template<typename ValueT>
684 void operator()(const AttributeArray&) const
685 {
686 auto& targetHandle = mTargetHandles.getWriteHandle<ValueT>(mTargetOffset);
687 targetHandle.expand();
688
689 for (const auto& index : mSortedIndices) {
690 const auto& it = mIndices[index];
691 const auto& sourceHandle = mSourceHandles.getHandle<ValueT>(std::get<0>(it));
692 const Index targetIndex = indexOffsetFromVoxel(std::get<1>(it), mTargetLeaf, mOffsets);
693 for (Index i = 0; i < sourceHandle.stride(); i++) {
694 ValueT sourceValue = sourceHandle.get(std::get<2>(it), i);
695 targetHandle.set(targetIndex, i, sourceValue);
696 }
697 }
698 }
699
700 private:
701 AttributeHandles& mTargetHandles;
702 AttributeHandles& mSourceHandles;
703 Index mTargetOffset;
704 const LeafT& mTargetLeaf;
705 IndexArray& mOffsets;
706 const IndexTripleArray& mIndices;
707 const IndexArray& mSortedIndices;
708 }; // struct PerformTypedMoveOp
709
710 void performMove(Index targetOffset, const LeafT& targetLeaf,
711 IndexArray& offsets, const IndexTripleArray& indices,
712 const IndexArray& sortedIndices) const
713 {
714 auto& targetArray = mTargetHandles.getArray(targetOffset);
715 targetArray.loadData();
716 targetArray.expand();
717
718 for (const auto& index : sortedIndices) {
719 const auto& it = indices[index];
720
721 const auto& sourceArray = mSourceHandles.getConstArray(std::get<0>(it));
722
723 const Index sourceOffset = std::get<2>(it);
724 const Index targetOffset = indexOffsetFromVoxel(std::get<1>(it), targetLeaf, offsets);
725
726 targetArray.set(targetOffset, sourceArray, sourceOffset);
727 }
728 }
729
730 void operator()(LeafT& leaf, size_t aIdx) const
731 {
732 const Index idx(static_cast<Index>(aIdx));
733 const auto& moveIndices = mMoveLeafMap[aIdx];
734 if (moveIndices.empty()) return;
735 const auto& sortedIndices = mMoveLeafIndices[aIdx];
736
737 // extract per-voxel offsets for this leaf
738
739 auto& offsets = mOffsetMap[aIdx];
740
741 const auto& array = leaf.constAttributeArray(mAttributeIndex);
742
743 PerformTypedMoveOp op(mTargetHandles, mSourceHandles, idx, leaf, offsets,
744 moveIndices, sortedIndices);
745 if (!processTypedArray(array, op)) {
746 this->performMove(idx, leaf, offsets, moveIndices, sortedIndices);
747 }
748 }
749
750 private:
751 LeafOffsetArray& mOffsetMap;
752 AttributeHandles& mTargetHandles;
753 AttributeHandles& mSourceHandles;
754 const Index mAttributeIndex;
755 const GlobalPointIndexMap& mMoveLeafMap;
756 const GlobalPointIndexIndices& mMoveLeafIndices;
757 }; // struct GlobalMovePointsOp
758
759
760 template <typename TreeT>
761 struct LocalMovePointsOp
762 {
763 using LeafT = typename TreeT::LeafNodeType;
764 using LeafArrayT = std::vector<LeafT*>;
765 using LeafManagerT = typename tree::LeafManager<TreeT>;
766
767 LocalMovePointsOp( LeafOffsetArray& offsetMap,
768 AttributeHandles& targetHandles,
769 const LeafIndexArray& sourceIndices,
770 AttributeHandles& sourceHandles,
771 const Index attributeIndex,
772 const LocalPointIndexMap& moveLeafMap)
773 : mOffsetMap(offsetMap)
774 , mTargetHandles(targetHandles)
775 , mSourceIndices(sourceIndices)
776 , mSourceHandles(sourceHandles)
777 , mAttributeIndex(attributeIndex)
778 , mMoveLeafMap(moveLeafMap) { }
779
780 struct PerformTypedMoveOp
781 {
782 PerformTypedMoveOp(AttributeHandles& targetHandles, AttributeHandles& sourceHandles,
783 Index targetOffset, Index sourceOffset, const LeafT& targetLeaf,
784 IndexArray& offsets, const IndexPairArray& indices)
785 : mTargetHandles(targetHandles)
786 , mSourceHandles(sourceHandles)
787 , mTargetOffset(targetOffset)
788 , mSourceOffset(sourceOffset)
789 , mTargetLeaf(targetLeaf)
790 , mOffsets(offsets)
791 , mIndices(indices) { }
792
793 template<typename ValueT>
794 void operator()(const AttributeArray&) const
795 {
796 auto& targetHandle = mTargetHandles.getWriteHandle<ValueT>(mTargetOffset);
797 const auto& sourceHandle = mSourceHandles.getHandle<ValueT>(mSourceOffset);
798
799 targetHandle.expand();
800
801 for (const auto& it : mIndices) {
802 const Index targetIndex = indexOffsetFromVoxel(it.first, mTargetLeaf, mOffsets);
803 for (Index i = 0; i < sourceHandle.stride(); i++) {
804 ValueT sourceValue = sourceHandle.get(it.second, i);
805 targetHandle.set(targetIndex, i, sourceValue);
806 }
807 }
808 }
809
810 private:
811 AttributeHandles& mTargetHandles;
812 AttributeHandles& mSourceHandles;
813 Index mTargetOffset;
814 Index mSourceOffset;
815 const LeafT& mTargetLeaf;
816 IndexArray& mOffsets;
817 const IndexPairArray& mIndices;
818 }; // struct PerformTypedMoveOp
819
820 template <typename ValueT>
821 void performTypedMove(Index sourceOffset, Index targetOffset, const LeafT& targetLeaf,
822 IndexArray& offsets, const IndexPairArray& indices) const
823 {
824 auto& targetHandle = mTargetHandles.getWriteHandle<ValueT>(targetOffset);
825 const auto& sourceHandle = mSourceHandles.getHandle<ValueT>(sourceOffset);
826
827 targetHandle.expand();
828
829 for (const auto& it : indices) {
830 const Index tgtOffset = indexOffsetFromVoxel(it.first, targetLeaf, offsets);
831 for (Index i = 0; i < sourceHandle.stride(); i++) {
832 ValueT sourceValue = sourceHandle.get(it.second, i);
833 targetHandle.set(tgtOffset, i, sourceValue);
834 }
835 }
836 }
837
838 void performMove(Index targetOffset, Index sourceOffset, const LeafT& targetLeaf,
839 IndexArray& offsets, const IndexPairArray& indices) const
840 {
841 auto& targetArray = mTargetHandles.getArray(targetOffset);
842 const auto& sourceArray = mSourceHandles.getConstArray(sourceOffset);
843
844 for (const auto& it : indices) {
845 const Index sourceOffset = it.second;
846 const Index targetOffset = indexOffsetFromVoxel(it.first, targetLeaf, offsets);
847
848 targetArray.set(targetOffset, sourceArray, sourceOffset);
849 }
850 }
851
852 void operator()(const LeafT& leaf, size_t aIdx) const
853 {
854 const Index idx(static_cast<Index>(aIdx));
855 const auto& moveIndices = mMoveLeafMap.at(aIdx);
856 if (moveIndices.empty()) return;
857
858 // extract target leaf and per-voxel offsets for this leaf
859
860 auto& offsets = mOffsetMap[aIdx];
861
862 // extract source leaf that has the same origin as the target leaf (if any)
863
864 assert(aIdx < mSourceIndices.size());
865 const Index sourceOffset(mSourceIndices[aIdx]);
866
867 const auto& array = leaf.constAttributeArray(mAttributeIndex);
868
869 PerformTypedMoveOp op(mTargetHandles, mSourceHandles,
870 idx, sourceOffset, leaf, offsets, moveIndices);
871 if (!processTypedArray(array, op)) {
872 this->performMove(idx, sourceOffset, leaf, offsets, moveIndices);
873 }
874 }
875
876 private:
877 LeafOffsetArray& mOffsetMap;
878 AttributeHandles& mTargetHandles;
879 const LeafIndexArray& mSourceIndices;
880 AttributeHandles& mSourceHandles;
881 const Index mAttributeIndex;
882 const LocalPointIndexMap& mMoveLeafMap;
883 }; // struct LocalMovePointsOp
884
885
886 #endif // OPENVDB_ABI_VERSION_NUMBER >= 6
887
888
889 } // namespace point_move_internal
890
891
893
894
895 template <typename PointDataGridT, typename DeformerT, typename FilterT>
896 inline void movePoints( PointDataGridT& points,
897 const math::Transform& transform,
898 DeformerT& deformer,
899 const FilterT& filter,
900 future::Advect* objectNotInUse,
901 bool threaded)
902 {
903 using LeafIndex = point_move_internal::LeafIndex;
904 using PointDataTreeT = typename PointDataGridT::TreeType;
905 using LeafT = typename PointDataTreeT::LeafNodeType;
906 using LeafManagerT = typename tree::LeafManager<PointDataTreeT>;
907
908 using namespace point_move_internal;
909
910 // this object is for future use only
911 assert(!objectNotInUse);
912 (void)objectNotInUse;
913
914 PointDataTreeT& tree = points.tree();
915
916 // early exit if no LeafNodes
917
918 PointDataTree::LeafCIter iter = tree.cbeginLeaf();
919
920 if (!iter) return;
921
922 // build voxel topology taking into account any point group deletion
923
924 auto newPoints = point_mask_internal::convertPointsToScalar<PointDataGrid>(
925 points, transform, filter, deformer, threaded);
926 auto& newTree = newPoints->tree();
927
928 // create leaf managers for both trees
929
930 LeafManagerT sourceLeafManager(tree);
931 LeafManagerT targetLeafManager(newTree);
932
933 // extract the existing attribute set
934 const auto& existingAttributeSet = points.tree().cbeginLeaf()->attributeSet();
935
936 // build a coord -> index map for looking up target leafs by origin and a faster
937 // unordered map for finding the source index from a target index
938
939 LeafMap targetLeafMap;
940 LeafIndexArray sourceIndices(targetLeafManager.leafCount(),
941 std::numeric_limits<LeafIndex>::max());
942
943 LeafOffsetArray offsetMap(targetLeafManager.leafCount());
944
945 {
946 LeafMap sourceLeafMap;
947 auto sourceRange = sourceLeafManager.leafRange();
948 for (auto leaf = sourceRange.begin(); leaf; ++leaf) {
949 sourceLeafMap.insert({leaf->origin(), LeafIndex(static_cast<LeafIndex>(leaf.pos()))});
950 }
951 auto targetRange = targetLeafManager.leafRange();
952 for (auto leaf = targetRange.begin(); leaf; ++leaf) {
953 targetLeafMap.insert({leaf->origin(), LeafIndex(static_cast<LeafIndex>(leaf.pos()))});
954 }
955
956 // acquire registry lock to avoid locking when appending attributes in parallel
957
958 AttributeArray::ScopedRegistryLock lock;
959
960 // perform four independent per-leaf operations in parallel
961 targetLeafManager.foreach(
962 [&](LeafT& leaf, size_t idx) {
963 // map frequency => cumulative histogram
964 auto* buffer = leaf.buffer().data();
965 for (Index i = 1; i < leaf.buffer().size(); i++) {
966 buffer[i] = buffer[i-1] + buffer[i];
967 }
968 // replace attribute set with a copy of the existing one
969 leaf.replaceAttributeSet(
970 new AttributeSet(existingAttributeSet, leaf.getLastValue(), &lock),
971 /*allowMismatchingDescriptors=*/true);
972 // store the index of the source leaf in a corresponding target leaf array
973 const auto it = sourceLeafMap.find(leaf.origin());
974 if (it != sourceLeafMap.end()) {
975 sourceIndices[idx] = it->second;
976 }
977 // allocate offset maps
978 offsetMap[idx].resize(LeafT::SIZE);
979 },
980 threaded);
981 }
982
983 // moving leaf
984
985 GlobalPointIndexMap globalMoveLeafMap(targetLeafManager.leafCount());
986 LocalPointIndexMap localMoveLeafMap(targetLeafManager.leafCount());
987
988 // build global and local move leaf maps and update local positions
989
990 if (filter.state() == index::ALL) {
991 NullFilter nullFilter;
992 BuildMoveMapsOp<DeformerT, PointDataTreeT, NullFilter> op(deformer,
993 globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
994 transform, points.transform(), nullFilter);
995 sourceLeafManager.foreach(op, threaded);
996 } else {
997 BuildMoveMapsOp<DeformerT, PointDataTreeT, FilterT> op(deformer,
998 globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
999 transform, points.transform(), filter);
1000 sourceLeafManager.foreach(op, threaded);
1001 }
1002
1003 // build a sorted index vector for each leaf that references the global move map
1004 // indices in order of their source leafs and voxels to ensure determinism in the
1005 // resulting point orders
1006
1007 GlobalPointIndexIndices globalMoveLeafIndices(globalMoveLeafMap.size());
1008
1009 targetLeafManager.foreach(
1010 [&](LeafT& /*leaf*/, size_t idx) {
1011 const IndexTripleArray& moveIndices = globalMoveLeafMap[idx];
1012 if (moveIndices.empty()) return;
1013
1014 IndexArray& sortedIndices = globalMoveLeafIndices[idx];
1015 sortedIndices.resize(moveIndices.size());
1016 std::iota(std::begin(sortedIndices), std::end(sortedIndices), 0);
1017 std::sort(std::begin(sortedIndices), std::end(sortedIndices),
1018 [&](int i, int j)
1019 {
1020 const Index& indexI0(std::get<0>(moveIndices[i]));
1021 const Index& indexJ0(std::get<0>(moveIndices[j]));
1022 if (indexI0 < indexJ0) return true;
1023 if (indexI0 > indexJ0) return false;
1024 return std::get<2>(moveIndices[i]) < std::get<2>(moveIndices[j]);
1025 }
1026 );
1027 },
1028 threaded);
1029
1030 #if OPENVDB_ABI_VERSION_NUMBER < 6
1031 // initialize attribute handles
1032 AttributeHandles sourceHandles(sourceLeafManager.leafCount());
1033 AttributeHandles targetHandles(targetLeafManager.leafCount());
1034 #endif
1035
1036 for (const auto& it : existingAttributeSet.descriptor().map()) {
1037
1038 const Index attributeIndex = static_cast<Index>(it.second);
1039
1040 // zero offsets
1041 targetLeafManager.foreach(
1042 [&offsetMap](const LeafT& /*leaf*/, size_t idx) {
1043 std::fill(offsetMap[idx].begin(), offsetMap[idx].end(), 0);
1044 },
1045 threaded);
1046
1047 #if OPENVDB_ABI_VERSION_NUMBER >= 6
1048
1049 // move points between leaf nodes
1050
1051 GlobalMovePointsOp<PointDataTreeT> globalMoveOp(offsetMap,
1052 sourceLeafManager, attributeIndex, globalMoveLeafMap, globalMoveLeafIndices);
1053 targetLeafManager.foreach(globalMoveOp, threaded);
1054
1055 // move points within leaf nodes
1056
1057 LocalMovePointsOp<PointDataTreeT> localMoveOp(offsetMap,
1058 sourceIndices, sourceLeafManager, attributeIndex, localMoveLeafMap);
1059 targetLeafManager.foreach(localMoveOp, threaded);
1060 #else
1061 // cache attribute handles
1062
1063 sourceHandles.cache(sourceLeafManager.leafRange(), attributeIndex);
1064 targetHandles.cache(targetLeafManager.leafRange(), attributeIndex);
1065
1066 // move points between leaf nodes
1067
1068 GlobalMovePointsOp<PointDataTreeT> globalMoveOp(offsetMap, targetHandles,
1069 sourceHandles, attributeIndex, globalMoveLeafMap, globalMoveLeafIndices);
1070 targetLeafManager.foreach(globalMoveOp, threaded);
1071
1072 // move points within leaf nodes
1073
1074 LocalMovePointsOp<PointDataTreeT> localMoveOp(offsetMap, targetHandles,
1075 sourceIndices, sourceHandles,
1076 attributeIndex, localMoveLeafMap);
1077 targetLeafManager.foreach(localMoveOp, threaded);
1078 #endif // OPENVDB_ABI_VERSION_NUMBER >= 6
1079 }
1080
1081 points.setTree(newPoints->treePtr());
1082 }
1083
1084
1085 template <typename PointDataGridT, typename DeformerT, typename FilterT>
1086 inline void movePoints( PointDataGridT& points,
1087 DeformerT& deformer,
1088 const FilterT& filter,
1089 future::Advect* objectNotInUse,
1090 bool threaded)
1091 {
1092 movePoints(points, points.transform(), deformer, filter, objectNotInUse, threaded);
1093 }
1094
1095
1097
1098
1099 template <typename T>
1100 CachedDeformer<T>::CachedDeformer(Cache& cache)
1101 : mCache(cache) { }
1102
1103
1104 template <typename T>
1105 template <typename PointDataGridT, typename DeformerT, typename FilterT>
1106 void CachedDeformer<T>::evaluate(PointDataGridT& grid, DeformerT& deformer, const FilterT& filter,
1107 bool threaded)
1108 {
1109 using TreeT = typename PointDataGridT::TreeType;
1110 using LeafT = typename TreeT::LeafNodeType;
1111 using LeafManagerT = typename tree::LeafManager<TreeT>;
1112 LeafManagerT leafManager(grid.tree());
1113
1114 // initialize cache
1115 auto& leafs = mCache.leafs;
1116 leafs.resize(leafManager.leafCount());
1117
1118 const auto& transform = grid.transform();
1119
1120 // insert deformed positions into the cache
1121
1122 auto cachePositionsOp = [&](const LeafT& leaf, size_t idx) {
1123
1124 const Index64 totalPointCount = leaf.pointCount();
1125 if (totalPointCount == 0) return;
1126
1127 // deformer is copied to ensure that it is unique per-thread
1128
1129 DeformerT newDeformer(deformer);
1130
1131 newDeformer.reset(leaf, idx);
1132
1133 auto handle = AttributeHandle<Vec3f>::create(leaf.constAttributeArray("P"));
1134
1135 auto& cache = leafs[idx];
1136 cache.clear();
1137
1138 // only insert into a vector directly if the filter evaluates all points
1139 // and all points are stored in active voxels
1140 const bool useVector = filter.state() == index::ALL &&
1141 (leaf.isDense() || (leaf.onPointCount() == leaf.pointCount()));
1142 if (useVector) {
1143 cache.vecData.resize(totalPointCount);
1144 }
1145
1146 for (auto iter = leaf.beginIndexOn(filter); iter; iter++) {
1147
1148 // extract index-space position and apply index-space deformation (if defined)
1149
1150 Vec3d position = handle->get(*iter) + iter.getCoord().asVec3d();
1151
1152 // if deformer is designed to be used in index-space, perform deformation prior
1153 // to transforming position to world-space, otherwise perform deformation afterwards
1154
1155 if (DeformerTraits<DeformerT>::IndexSpace) {
1156 newDeformer.apply(position, iter);
1157 position = transform.indexToWorld(position);
1158 }
1159 else {
1160 position = transform.indexToWorld(position);
1161 newDeformer.apply(position, iter);
1162 }
1163
1164 // insert new position into the cache
1165
1166 if (useVector) {
1167 cache.vecData[*iter] = static_cast<Vec3T>(position);
1168 }
1169 else {
1170 cache.mapData.insert({*iter, static_cast<Vec3T>(position)});
1171 }
1172 }
1173
1174 // store the total number of points to allow use of an expanded vector on access
1175
1176 if (!cache.mapData.empty()) {
1177 cache.totalSize = static_cast<Index>(totalPointCount);
1178 }
1179 };
1180
1181 leafManager.foreach(cachePositionsOp, threaded);
1182 }
1183
1184
1185 template <typename T>
1186 template <typename LeafT>
1187 void CachedDeformer<T>::reset(const LeafT& /*leaf*/, size_t idx)
1188 {
1189 if (idx >= mCache.leafs.size()) {
1190 if (mCache.leafs.empty()) {
1191 throw IndexError("No leafs in cache, perhaps CachedDeformer has not been evaluated?");
1192 } else {
1193 throw IndexError("Leaf index is out-of-range of cache leafs.");
1194 }
1195 }
1196 auto& cache = mCache.leafs[idx];
1197 if (!cache.mapData.empty()) {
1198 mLeafMap = &cache.mapData;
1199 mLeafVec = nullptr;
1200 }
1201 else {
1202 mLeafVec = &cache.vecData;
1203 mLeafMap = nullptr;
1204 }
1205 }
1206
1207
1208 template <typename T>
1209 template <typename IndexIterT>
1210 void CachedDeformer<T>::apply(Vec3d& position, const IndexIterT& iter) const
1211 {
1212 assert(*iter >= 0);
1213
1214 if (mLeafMap) {
1215 auto it = mLeafMap->find(*iter);
1216 if (it == mLeafMap->end()) return;
1217 position = static_cast<openvdb::Vec3d>(it->second);
1218 }
1219 else {
1220 assert(mLeafVec);
1221
1222 if (mLeafVec->empty()) return;
1223 assert(*iter < mLeafVec->size());
1224 position = static_cast<openvdb::Vec3d>((*mLeafVec)[*iter]);
1225 }
1226 }
1227
1228
1229 } // namespace points
1230 } // namespace OPENVDB_VERSION_NAME
1231 } // namespace openvdb
1232
1233 #endif // OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED
openvdb::v8_2::points::CachedDeformer::Cache::Leaf::vecData
LeafVecT vecData
Definition: PointMove.h:118
openvdb::v8_2::points::CachedDeformer::reset
void reset(const LeafT &leaf, size_t idx)
Definition: PointMove.h:1187
openvdb::v8_2::points::CachedDeformer::Cache
Definition: PointMove.h:108
openvdb::v8_2::points::point_move_internal::LocalMovePointsOp::AttributeArrays
std::vector< AttributeArray * > AttributeArrays
Definition: PointMove.h:444
openvdb::v8_2::math::Mat3
3x3 matrix class.
Definition: Mat3.h:29
openvdb::v8_2::points::point_move_internal::GlobalMovePointsOp::CopyIterator
Definition: PointMove.h:311
openvdb::v8_2::points::AttributeArray
Base class for storing attribute data.
Definition: AttributeArray.h:93
openvdb::v8_2::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:26
openvdb::v8_2::points::point_move_internal::GlobalPointIndexMap
std::vector< IndexTripleArray > GlobalPointIndexMap
Definition: PointMove.h:165
openvdb::v8_2::points::point_move_internal::LocalPointIndexMap
std::vector< IndexPairArray > LocalPointIndexMap
Definition: PointMove.h:170
openvdb::v8_2::points::DeformerTraits
Deformer Traits for optionally configuring deformers to be applied in index-space....
Definition: PointMask.h:77
openvdb::v8_2::points::index::ALL
@ ALL
Definition: IndexIterator.h:43
PointMask.h
Methods for extracting masks from VDB Point grids.
openvdb::v8_2::points::AttributeSet
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:39
openvdb::v8_2::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::v8_2::Index
Index32 Index
Definition: openvdb/Types.h:32
openvdb::v8_2::points::CachedDeformer::Cache::Leaf::clear
void clear()
clear data buffers and reset counter
Definition: PointMove.h:112
openvdb::v8_2::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::v8_2::points::point_move_internal::GlobalPointIndexIndices
std::vector< IndexArray > GlobalPointIndexIndices
Definition: PointMove.h:166
openvdb::v8_2::points::CachedDeformer::Cache::Leaf
Definition: PointMove.h:110
openvdb::v8_2::points::point_move_internal::BuildMoveMapsOp
Definition: PointMove.h:179
openvdb::v8_2::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:896
openvdb::v8_2::points::NullFilter
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:51
openvdb::v8_2::points::point_move_internal::GlobalMovePointsOp::CopyIterator::reset
void reset(Index startIndex, Index endIndex)
Definition: PointMove.h:321
openvdb::v8_2::points::future::Advect
Definition: PointMove.h:59
openvdb::v8_2::points::point_move_internal::LocalMovePointsOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:441
openvdb::v8_2::points::AttributeArray::ScopedRegistryLock
Definition: AttributeArray.h:119
openvdb::v8_2::points::point_move_internal::LeafOffsetArray
std::vector< LeafIndexArray > LeafOffsetArray
Definition: PointMove.h:173
openvdb::v8_2::points::point_move_internal::LocalMovePointsOp::CopyIterator
Definition: PointMove.h:460
openvdb::v8_2::points::point_move_internal::LocalMovePointsOp::LeafManagerT
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:443
openvdb::v8_2::points::point_move_internal::BuildMoveMapsOp::LeafArrayT
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:181
openvdb::v8_2::tools::composite::max
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:107
openvdb::v8_2::points::point_move_internal::IndexTriple
std::tuple< LeafIndex, Index, Index > IndexTriple
Definition: PointMove.h:163
openvdb::v8_2::points::point_move_internal::LeafIndex
Index32 LeafIndex
Definition: PointMove.h:93
openvdb::v8_2::points::CachedDeformer::Cache::leafs
std::vector< Leaf > leafs
Definition: PointMove.h:123
openvdb::v8_2::points::point_move_internal::IndexPair
std::pair< Index, Index > IndexPair
Definition: PointMove.h:168
openvdb::v8_2::math::Vec3
Definition: Vec3.h:24
openvdb::v8_2::points::point_move_internal::GlobalMovePointsOp::LeafArrayT
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:293
openvdb::v8_2::points::point_move_internal::LocalMovePointsOp::CopyIterator::CopyIterator
CopyIterator(const LeafT &leaf, const IndexPairArray &indices, IndexArray &offsets)
Definition: PointMove.h:461
openvdb::v8_2::points::point_move_internal::LocalMovePointsOp::CopyIterator::operator++
CopyIterator & operator++()
Definition: PointMove.h:468
openvdb::v8_2::points::AttributeWriteHandle
Write-able version of AttributeHandle.
Definition: AttributeArray.h:915
openvdb::v8_2::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
PointDataGrid.h
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
openvdb::v8_2::points::CachedDeformer::Cache::Leaf::mapData
LeafMapT mapData
Definition: PointMove.h:119
openvdb::v8_2::points::point_move_internal::GlobalMovePointsOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:292
openvdb::v8_2::points::CachedDeformer::LeafIndex
point_move_internal::LeafIndex LeafIndex
Definition: PointMove.h:101
openvdb::v8_2::points::point_move_internal::GlobalMovePointsOp::AttributeArrays
std::vector< AttributeArray * > AttributeArrays
Definition: PointMove.h:295
openvdb::v8_2::points::point_move_internal::LeafIndexArray
std::vector< LeafIndex > LeafIndexArray
Definition: PointMove.h:172
openvdb::v8_2::points::point_move_internal::IndexTripleArray
tbb::concurrent_vector< IndexTriple > IndexTripleArray
Definition: PointMove.h:164
openvdb::v8_2::points::CachedDeformer::Vec3T
typename math::Vec3< T > Vec3T
Definition: PointMove.h:102
openvdb::v8_2::points::point_move_internal::GlobalMovePointsOp::operator()
void operator()(LeafT &leaf, size_t idx) const
Definition: PointMove.h:381
openvdb::v8_2::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::v8_2::points::point_move_internal::IndexArray
std::vector< Index > IndexArray
Definition: PointMove.h:161
openvdb::v8_2::points::CachedDeformer::apply
void apply(Vec3d &position, const IndexIterT &iter) const
Retrieve the new position from the cache.
Definition: PointMove.h:1210
openvdb::v8_2::points::CachedDeformer
A Deformer that caches the resulting positions from evaluating another Deformer.
Definition: PointMove.h:99
openvdb::v8_2::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:85
openvdb::v8_2::points::point_move_internal::LocalMovePointsOp
Definition: PointMove.h:440
openvdb::v8_2::points::CachedDeformer::LeafMapT
std::unordered_map< LeafIndex, Vec3T > LeafMapT
Definition: PointMove.h:104
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:153
openvdb::v8_2::math::Vec3d
Vec3< double > Vec3d
Definition: Vec3.h:668
openvdb::v8_2::points::point_move_internal::LocalMovePointsOp::CopyIterator::sourceIndex
Index sourceIndex() const
Definition: PointMove.h:470
openvdb::v8_2::points::point_move_internal::BuildMoveMapsOp::operator()
void operator()(LeafT &leaf, size_t idx) const
Definition: PointMove.h:199
openvdb::v8_2::math::Transform
Definition: Transform.h:40
openvdb::v8_2::points::point_move_internal::LocalMovePointsOp::LeafArrayT
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:442
openvdb::v8_2::points::point_move_internal::LocalMovePointsOp::operator()
void operator()(LeafT &leaf, size_t idx) const
Definition: PointMove.h:487
openvdb::v8_2::points::point_move_internal::GlobalMovePointsOp::LeafManagerT
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:294
openvdb::v8_2::Index32
uint32_t Index32
Definition: openvdb/Types.h:30
openvdb::v8_2::points::point_move_internal::LocalMovePointsOp::CopyIterator::targetIndex
Index targetIndex() const
Definition: PointMove.h:475
openvdb::v8_2::points::point_move_internal::LeafMap
std::unordered_map< Coord, LeafIndex > LeafMap
Definition: PointMove.h:174
openvdb::v8_2::points::point_move_internal::GlobalMovePointsOp::CopyIterator::operator++
CopyIterator & operator++()
Definition: PointMove.h:328
openvdb::v8_2::points::point_move_internal::BuildMoveMapsOp::LeafManagerT
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:182
openvdb::v8_2::points::CachedDeformer::evaluate
void evaluate(PointDataGridT &grid, DeformerT &deformer, const FilterT &filter, bool threaded=true)
Definition: PointMove.h:1106
openvdb::v8_2::math::Mat4
4x4 -matrix class.
Definition: Mat4.h:24
openvdb::v8_2::Index64
uint64_t Index64
Definition: openvdb/Types.h:31
openvdb::v8_2::points::point_move_internal::GlobalMovePointsOp
Definition: PointMove.h:291
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:101
openvdb::v8_2::points::point_move_internal::BuildMoveMapsOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:180
openvdb::v8_2::points::point_move_internal::GlobalMovePointsOp::CopyIterator::targetIndex
Index targetIndex() const
Definition: PointMove.h:348
openvdb::v8_2::math::Quat
Definition: Quat.h:79
openvdb::v8_2::points::point_move_internal::indexOffsetFromVoxel
Index indexOffsetFromVoxel(const Index voxelOffset, const LeafT &leaf, IndexArray &offsets)
Definition: PointMove.h:272
openvdb::v8_2::points::point_move_internal::IndexPairArray
std::vector< IndexPair > IndexPairArray
Definition: PointMove.h:169
openvdb::v8_2::points::point_move_internal::GlobalMovePointsOp::CopyIterator::CopyIterator
CopyIterator(const LeafT &leaf, const IndexArray &sortedIndices, const IndexTripleArray &moveIndices, IndexArray &offsets)
Definition: PointMove.h:312
openvdb
Definition: openvdb/Exceptions.h:13
openvdb::v8_2::math::Coord::asVec3d
Vec3d asVec3d() const
Definition: Coord.h:144
openvdb::v8_2::IndexError
Definition: openvdb/Exceptions.h:57
openvdb::v8_2::points::point_move_internal::GlobalMovePointsOp::CopyIterator::sourceIndex
Index sourceIndex() const
Definition: PointMove.h:342
openvdb.h
openvdb::v8_2::points::point_move_internal::GlobalMovePointsOp::CopyIterator::leafIndex
Index leafIndex(Index i) const
Definition: PointMove.h:334
openvdb::v8_2::tree::LeafIteratorBase
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels)
Definition: TreeIterator.h:1187
openvdb::v8_2::points::AttributeHandle::create
static Ptr create(const AttributeArray &array, const bool collapseOnDestruction=true)
Definition: AttributeArray.h:2116
openvdb::v8_2::math::Transform::indexToWorld
Vec3d indexToWorld(const Vec3d &xyz) const
Apply this transformation to the given coordinates.
Definition: Transform.h:108
openvdb::v8_2::points::CachedDeformer::LeafVecT
std::vector< Vec3T > LeafVecT
Definition: PointMove.h:103