OpenVDB: PointMove.h Source File

OpenVDB 6.1.0

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