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