32 #ifndef OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED 33 #define OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED 40 #include <tbb/concurrent_vector.h> 47 #include <unordered_map> 59 namespace future {
struct Advect { }; }
68 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT = NullFilter>
73 bool threaded =
true);
83 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT = NullFilter>
89 bool threaded =
true);
104 using LeafMapT = std::unordered_map<LeafIndex, Vec3T>;
134 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT>
135 void evaluate(PointDataGridT& grid, DeformerT& deformer,
const FilterT& filter,
136 bool threaded =
true);
140 template <
typename LeafT>
141 void reset(
const LeafT& leaf,
size_t idx);
144 template <
typename IndexIterT>
145 void apply(Vec3d& position,
const IndexIterT& iter)
const;
148 friend class ::TestPointMove;
159 namespace point_move_internal {
174 using LeafMap = std::unordered_map<Coord, LeafIndex>;
177 template <
typename DeformerT,
typename TreeT,
typename FilterT>
180 using LeafT =
typename TreeT::LeafNodeType;
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) { }
201 DeformerT deformer(mDeformer);
202 deformer.reset(leaf, idx);
206 Coord sourceLeafOrigin = leaf.origin();
210 for (
auto iter = leaf.beginIndexOn(mFilter); iter; iter++) {
216 Vec3d positionIS = sourceHandle->get(*iter) + iter.getCoord().asVec3d();
218 deformer.apply(positionIS, iter);
223 Vec3d positionWS = mSourceTransform.indexToWorld(positionIS);
224 if (!useIndexSpace) {
225 deformer.apply(positionWS, iter);
230 positionIS = mTargetTransform.worldToIndex(positionWS);
234 Coord targetVoxel = Coord::round(positionIS);
235 Index targetOffset = LeafT::coordToOffset(targetVoxel);
239 Vec3d voxelPosition(positionIS - targetVoxel.asVec3d());
240 sourceHandle->set(*iter, voxelPosition);
244 Coord targetLeafOrigin = targetVoxel & ~(LeafT::DIM - 1);
245 assert(mTargetLeafMap.find(targetLeafOrigin) != mTargetLeafMap.end());
246 const LeafIndex targetLeafOffset(mTargetLeafMap.at(targetLeafOrigin));
250 if (targetLeafOrigin == sourceLeafOrigin) {
251 mLocalMoveLeafMap[targetLeafOffset].emplace_back(targetOffset, *iter);
254 mGlobalMoveLeafMap[targetLeafOffset].push_back(
IndexTriple(
255 LeafIndex(static_cast<LeafIndex>(idx)), targetOffset, *iter));
261 const DeformerT& mDeformer;
267 const FilterT& mFilter;
270 template <
typename LeafT>
278 Index targetOffset = offsets[voxelOffset]++;
279 if (voxelOffset > 0) {
280 targetOffset +=
static_cast<Index>(leaf.getValue(voxelOffset - 1));
286 template <
typename TreeT>
289 using LeafT =
typename TreeT::LeafNodeType;
296 const Index attributeIndex,
299 : mOffsetMap(offsetMap)
300 , mSourceLeafManager(sourceLeafManager)
301 , mAttributeIndex(attributeIndex)
302 , mMoveLeafMap(moveLeafMap)
303 , mMoveLeafIndices(moveLeafIndices) { }
312 , mSortedIndices(sortedIndices)
313 , mMoveIndices(moveIndices)
314 , mOffsets(offsets) { }
316 operator bool()
const {
return bool(mIt); }
321 mEndIndex = endIndex;
333 if (i < mSortedIndices.size()) {
334 return std::get<0>(this->leafIndexTriple(i));
342 return std::get<2>(*mIt);
354 if (mIndex >= mEndIndex || mIndex >= mSortedIndices.size()) {
358 mIt = &this->leafIndexTriple(mIndex);
365 return mMoveIndices[mSortedIndices[i]];
381 if (moveIndices.empty())
return;
382 const IndexArray& sortedIndices = mMoveLeafIndices[idx];
390 auto& targetArray = leaf.attributeArray(mAttributeIndex);
391 targetArray.loadData();
392 targetArray.expand();
396 CopyIterator copyIterator(leaf, sortedIndices, moveIndices, offsets);
401 Index startIndex = 0;
403 for (
size_t i = 1; i <= sortedIndices.size(); i++) {
411 if (newSourceLeafIndex > sourceLeafIndex) {
412 copyIterator.
reset(startIndex, endIndex);
414 const LeafT& sourceLeaf = mSourceLeafManager.leaf(sourceLeafIndex);
415 const auto& sourceArray = sourceLeaf.constAttributeArray(mAttributeIndex);
416 sourceArray.loadData();
418 targetArray.copyValuesUnsafe(sourceArray, copyIterator);
420 sourceLeafIndex = newSourceLeafIndex;
421 startIndex = endIndex;
429 const Index mAttributeIndex;
435 template <
typename TreeT>
438 using LeafT =
typename TreeT::LeafNodeType;
446 const Index attributeIndex,
448 : mOffsetMap(offsetMap)
449 , mSourceIndices(sourceIndices)
450 , mSourceLeafManager(sourceLeafManager)
451 , mAttributeIndex(attributeIndex)
452 , mMoveLeafMap(moveLeafMap) { }
461 , mOffsets(offsets) { }
463 operator bool()
const {
return mIndex < static_cast<int>(mIndices.size()); }
469 return mIndices[mIndex].second;
487 if (moveIndices.empty())
return;
495 assert(idx < mSourceIndices.size());
496 const Index sourceLeafOffset(mSourceIndices[idx]);
497 LeafT& sourceLeaf = mSourceLeafManager.leaf(sourceLeafOffset);
498 const auto& sourceArray = sourceLeaf.constAttributeArray(mAttributeIndex);
499 sourceArray.loadData();
503 auto& targetArray = leaf.attributeArray(mAttributeIndex);
504 targetArray.loadData();
505 targetArray.expand();
510 targetArray.copyValuesUnsafe(sourceArray, copyIterator);
517 const Index mAttributeIndex;
528 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT>
532 const FilterT& filter,
537 using PointDataTreeT =
typename PointDataGridT::TreeType;
538 using LeafT =
typename PointDataTreeT::LeafNodeType;
541 using namespace point_move_internal;
544 assert(!objectNotInUse);
545 (void)objectNotInUse;
547 PointDataTreeT& tree = points.tree();
551 auto iter = tree.cbeginLeaf();
557 auto newPoints = point_mask_internal::convertPointsToScalar<PointDataGridT>(
558 points, transform, filter, deformer, threaded);
559 auto& newTree = newPoints->tree();
563 LeafManagerT sourceLeafManager(tree);
564 LeafManagerT targetLeafManager(newTree);
567 const auto& existingAttributeSet = points.tree().cbeginLeaf()->attributeSet();
580 auto sourceRange = sourceLeafManager.leafRange();
581 for (
auto leaf = sourceRange.begin(); leaf; ++leaf) {
582 sourceLeafMap.insert({leaf->origin(),
LeafIndex(static_cast<LeafIndex>(leaf.pos()))});
584 auto targetRange = targetLeafManager.leafRange();
585 for (
auto leaf = targetRange.begin(); leaf; ++leaf) {
586 targetLeafMap.insert({leaf->origin(),
LeafIndex(static_cast<LeafIndex>(leaf.pos()))});
594 targetLeafManager.foreach(
595 [&](LeafT& leaf,
size_t idx) {
597 auto* buffer = leaf.buffer().data();
598 for (
Index i = 1; i < leaf.buffer().size(); i++) {
599 buffer[i] = buffer[i-1] + buffer[i];
602 leaf.replaceAttributeSet(
603 new AttributeSet(existingAttributeSet, leaf.getLastValue(), &lock),
606 const auto it = sourceLeafMap.find(leaf.origin());
607 if (it != sourceLeafMap.end()) {
608 sourceIndices[idx] = it->second;
611 offsetMap[idx].resize(LeafT::SIZE);
625 BuildMoveMapsOp<DeformerT, PointDataTreeT, NullFilter> op(deformer,
626 globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
627 transform, points.transform(), nullFilter);
628 sourceLeafManager.foreach(op, threaded);
630 BuildMoveMapsOp<DeformerT, PointDataTreeT, FilterT> op(deformer,
631 globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
632 transform, points.transform(), filter);
633 sourceLeafManager.foreach(op, threaded);
642 targetLeafManager.foreach(
643 [&](LeafT& ,
size_t idx) {
645 if (moveIndices.empty())
return;
647 IndexArray& sortedIndices = globalMoveLeafIndices[idx];
648 sortedIndices.resize(moveIndices.size());
649 std::iota(std::begin(sortedIndices), std::end(sortedIndices), 0);
650 std::sort(std::begin(sortedIndices), std::end(sortedIndices),
653 const Index& indexI0(std::get<0>(moveIndices[i]));
654 const Index& indexJ0(std::get<0>(moveIndices[j]));
655 if (indexI0 < indexJ0)
return true;
656 if (indexI0 > indexJ0)
return false;
657 return std::get<2>(moveIndices[i]) < std::get<2>(moveIndices[j]);
663 for (
const auto& it : existingAttributeSet.descriptor().map()) {
665 const Index attributeIndex =
static_cast<Index>(it.second);
668 targetLeafManager.foreach(
669 [&offsetMap](
const LeafT& ,
size_t idx) {
670 std::fill(offsetMap[idx].begin(), offsetMap[idx].end(), 0);
676 GlobalMovePointsOp<PointDataTreeT> globalMoveOp(offsetMap,
677 sourceLeafManager, attributeIndex, globalMoveLeafMap, globalMoveLeafIndices);
678 targetLeafManager.foreach(globalMoveOp, threaded);
682 LocalMovePointsOp<PointDataTreeT> localMoveOp(offsetMap,
683 sourceIndices, sourceLeafManager, attributeIndex, localMoveLeafMap);
684 targetLeafManager.foreach(localMoveOp, threaded);
687 points.setTree(newPoints->treePtr());
691 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT>
694 const FilterT& filter,
698 movePoints(points, points.transform(), deformer, filter, objectNotInUse, threaded);
705 template <
typename T>
710 template <
typename T>
711 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT>
715 using TreeT =
typename PointDataGridT::TreeType;
716 using LeafT =
typename TreeT::LeafNodeType;
718 LeafManagerT leafManager(grid.tree());
721 auto& leafs = mCache.
leafs;
722 leafs.resize(leafManager.leafCount());
724 const auto& transform = grid.transform();
728 auto cachePositionsOp = [&](
const LeafT& leaf,
size_t idx) {
730 const Index64 totalPointCount = leaf.pointCount();
731 if (totalPointCount == 0)
return;
735 DeformerT newDeformer(deformer);
737 newDeformer.reset(leaf, idx);
741 auto& cache = leafs[idx];
746 const bool useVector = filter.state() ==
index::ALL &&
747 (leaf.isDense() || (leaf.onPointCount() == leaf.pointCount()));
749 cache.vecData.resize(totalPointCount);
752 for (
auto iter = leaf.beginIndexOn(filter); iter; iter++) {
756 Vec3d position = handle->get(*iter) + iter.getCoord().asVec3d();
762 newDeformer.apply(position, iter);
767 newDeformer.apply(position, iter);
773 cache.vecData[*iter] =
static_cast<Vec3T>(position);
776 cache.mapData.insert({*iter,
static_cast<Vec3T>(position)});
782 if (!cache.mapData.empty()) {
783 cache.totalSize =
static_cast<Index>(totalPointCount);
787 leafManager.foreach(cachePositionsOp, threaded);
791 template <
typename T>
792 template <
typename LeafT>
795 if (idx >= mCache.
leafs.size()) {
796 if (mCache.
leafs.empty()) {
797 throw IndexError(
"No leafs in cache, perhaps CachedDeformer has not been evaluated?");
799 throw IndexError(
"Leaf index is out-of-range of cache leafs.");
802 auto& cache = mCache.
leafs[idx];
803 if (!cache.mapData.empty()) {
804 mLeafMap = &cache.mapData;
808 mLeafVec = &cache.vecData;
814 template <
typename T>
815 template <
typename IndexIterT>
821 auto it = mLeafMap->find(*iter);
822 if (it == mLeafMap->end())
return;
823 position =
static_cast<openvdb::Vec3d
>(it->second);
828 if (mLeafVec->empty())
return;
829 assert(*iter < mLeafVec->size());
830 position =
static_cast<openvdb::Vec3d
>((*mLeafVec)[*iter]);
839 #endif // OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED std::vector< Index > IndexArray
Definition: PointMove.h:161
typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:289
void operator()(LeafT &leaf, size_t idx) const
Definition: PointMove.h:199
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:38
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:439
CopyIterator & operator++()
Definition: PointMove.h:465
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:50
Definition: PointMove.h:287
Index targetIndex() const
Definition: PointMove.h:345
Definition: PointMove.h:456
Index sourceIndex() const
Definition: PointMove.h:467
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:182
Definition: PointMove.h:307
typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:180
Definition: PointMove.h:436
Definition: AttributeArray.h:118
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:529
std::vector< LeafIndex > LeafIndexArray
Definition: PointMove.h:172
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:291
Index leafIndex(Index i) const
Definition: PointMove.h:331
std::tuple< LeafIndex, Index, Index > IndexTriple
Definition: PointMove.h:163
CopyIterator(const LeafT &leaf, const IndexPairArray &indices, IndexArray &offsets)
Definition: PointMove.h:458
void operator()(LeafT &leaf, size_t idx) const
Definition: PointMove.h:378
std::vector< LeafIndexArray > LeafOffsetArray
Definition: PointMove.h:173
LocalMovePointsOp(LeafOffsetArray &offsetMap, const LeafIndexArray &sourceIndices, LeafManagerT &sourceLeafManager, const Index attributeIndex, const LocalPointIndexMap &moveLeafMap)
Definition: PointMove.h:443
std::vector< AttributeArray * > AttributeArrays
Definition: PointMove.h:441
Index sourceIndex() const
Definition: PointMove.h:339
uint64_t Index64
Definition: Types.h:53
typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:438
Definition: Exceptions.h:13
std::unordered_map< Coord, LeafIndex > LeafMap
Definition: PointMove.h:174
std::vector< IndexTripleArray > GlobalPointIndexMap
Definition: PointMove.h:165
Index32 LeafIndex
Definition: PointMove.h:93
std::vector< AttributeArray * > AttributeArrays
Definition: PointMove.h:292
tbb::concurrent_vector< IndexTriple > IndexTripleArray
Definition: PointMove.h:164
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
Definition: IndexIterator.h:43
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:84
Index targetIndex() const
Definition: PointMove.h:472
Definition: PointMove.h:178
GlobalMovePointsOp(LeafOffsetArray &offsetMap, LeafManagerT &sourceLeafManager, const Index attributeIndex, const GlobalPointIndexMap &moveLeafMap, const GlobalPointIndexIndices &moveLeafIndices)
Definition: PointMove.h:294
Index32 Index
Definition: Types.h:54
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:181
void reset(Index startIndex, Index endIndex)
Definition: PointMove.h:318
Methods for extracting masks from VDB Point grids.
Write-able version of AttributeHandle.
Definition: AttributeArray.h:881
std::vector< IndexPair > IndexPairArray
Definition: PointMove.h:169
CopyIterator & operator++()
Definition: PointMove.h:325
void operator()(LeafT &leaf, size_t idx) const
Definition: PointMove.h:484
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:290
Index indexOffsetFromVoxel(const Index voxelOffset, const LeafT &leaf, IndexArray &offsets)
Definition: PointMove.h:272
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:440
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
Definition: PointMove.h:59
uint32_t Index32
Definition: Types.h:52
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
std::vector< IndexPairArray > LocalPointIndexMap
Definition: PointMove.h:170
CopyIterator(const LeafT &leaf, const IndexArray &sortedIndices, const IndexTripleArray &moveIndices, IndexArray &offsets)
Definition: PointMove.h:309
std::vector< IndexArray > GlobalPointIndexIndices
Definition: PointMove.h:166
std::pair< Index, Index > IndexPair
Definition: PointMove.h:168
Definition: Exceptions.h:57
static Ptr create(const AttributeArray &array, const bool collapseOnDestruction=true)
Definition: AttributeArray.h:2072
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202