9 #ifndef OPENVDB_POINTS_POINT_MOVE_IMPL_HAS_BEEN_INCLUDED
10 #define OPENVDB_POINTS_POINT_MOVE_IMPL_HAS_BEEN_INCLUDED
31 using LeafMapT = std::unordered_map<LeafIndex, Vec3T>;
61 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT>
62 void evaluate(PointDataGridT& grid, DeformerT& deformer,
const FilterT&
filter,
63 bool threaded =
true);
67 template <
typename LeafT>
68 void reset(
const LeafT& leaf,
size_t idx);
71 template <
typename IndexIterT>
75 friend class ::TestPointMove;
86 namespace point_move_internal {
101 using LeafMap = std::unordered_map<Coord, LeafIndex>;
104 template <
typename DeformerT,
typename TreeT,
typename FilterT>
107 using LeafT =
typename TreeT::LeafNodeType;
118 : mDeformer(deformer)
119 , mGlobalMoveLeafMap(globalMoveLeafMap)
120 , mLocalMoveLeafMap(localMoveLeafMap)
121 , mTargetLeafMap(targetLeafMap)
122 , mTargetTransform(targetTransform)
123 , mSourceTransform(sourceTransform)
124 , mFilter(filter) { }
128 DeformerT deformer(mDeformer);
129 deformer.reset(leaf, idx);
133 Coord sourceLeafOrigin = leaf.origin();
137 for (
auto iter = leaf.beginIndexOn(mFilter); iter; iter++) {
143 Vec3d positionIS = sourceHandle->get(*iter) + iter.getCoord().asVec3d();
145 deformer.apply(positionIS, iter);
150 Vec3d positionWS = mSourceTransform.
indexToWorld(positionIS);
151 if (!useIndexSpace) {
152 deformer.apply(positionWS, iter);
162 Index targetOffset = LeafT::coordToOffset(targetVoxel);
166 Vec3d voxelPosition(positionIS - targetVoxel.asVec3d());
167 sourceHandle->set(*iter, voxelPosition);
171 Coord targetLeafOrigin = targetVoxel & ~(LeafT::DIM - 1);
172 assert(mTargetLeafMap.find(targetLeafOrigin) != mTargetLeafMap.end());
173 const LeafIndex targetLeafOffset(mTargetLeafMap.at(targetLeafOrigin));
177 if (targetLeafOrigin == sourceLeafOrigin) {
178 mLocalMoveLeafMap[targetLeafOffset].emplace_back(targetOffset, *iter);
181 mGlobalMoveLeafMap[targetLeafOffset].push_back(
IndexTriple(
182 LeafIndex(static_cast<LeafIndex>(idx)), targetOffset, *iter));
188 const DeformerT& mDeformer;
194 const FilterT& mFilter;
197 template <
typename LeafT>
205 Index targetOffset = offsets[voxelOffset]++;
206 if (voxelOffset > 0) {
207 targetOffset +=
static_cast<Index>(leaf.getValue(voxelOffset - 1));
213 template <
typename TreeT>
216 using LeafT =
typename TreeT::LeafNodeType;
223 const Index attributeIndex,
226 : mOffsetMap(offsetMap)
227 , mSourceLeafManager(sourceLeafManager)
228 , mAttributeIndex(attributeIndex)
229 , mMoveLeafMap(moveLeafMap)
230 , mMoveLeafIndices(moveLeafIndices) { }
239 , mSortedIndices(sortedIndices)
240 , mMoveIndices(moveIndices)
241 , mOffsets(offsets) { }
243 operator bool()
const {
return bool(mIt); }
248 mEndIndex = endIndex;
260 if (i < mSortedIndices.size()) {
261 return std::get<0>(this->leafIndexTriple(i));
269 return std::get<2>(*mIt);
281 if (mIndex >= mEndIndex || mIndex >= mSortedIndices.size()) {
285 mIt = &this->leafIndexTriple(mIndex);
292 return mMoveIndices[mSortedIndices[i]];
308 if (moveIndices.empty())
return;
309 const IndexArray& sortedIndices = mMoveLeafIndices[idx];
317 auto& targetArray = leaf.attributeArray(mAttributeIndex);
318 targetArray.loadData();
319 targetArray.expand();
323 CopyIterator copyIterator(leaf, sortedIndices, moveIndices, offsets);
328 Index startIndex = 0;
330 for (
size_t i = 1; i <= sortedIndices.size(); i++) {
338 if (newSourceLeafIndex > sourceLeafIndex) {
339 copyIterator.
reset(startIndex, endIndex);
341 const LeafT& sourceLeaf = mSourceLeafManager.leaf(sourceLeafIndex);
342 const auto& sourceArray = sourceLeaf.constAttributeArray(mAttributeIndex);
343 sourceArray.loadData();
345 targetArray.copyValuesUnsafe(sourceArray, copyIterator);
347 sourceLeafIndex = newSourceLeafIndex;
348 startIndex = endIndex;
356 const Index mAttributeIndex;
362 template <
typename TreeT>
365 using LeafT =
typename TreeT::LeafNodeType;
373 const Index attributeIndex,
375 : mOffsetMap(offsetMap)
376 , mSourceIndices(sourceIndices)
377 , mSourceLeafManager(sourceLeafManager)
378 , mAttributeIndex(attributeIndex)
379 , mMoveLeafMap(moveLeafMap) { }
388 , mOffsets(offsets) { }
390 operator bool()
const {
return mIndex < static_cast<int>(mIndices.size()); }
396 return mIndices[mIndex].second;
414 if (moveIndices.empty())
return;
422 assert(idx < mSourceIndices.size());
423 const Index sourceLeafOffset(mSourceIndices[idx]);
424 LeafT& sourceLeaf = mSourceLeafManager.leaf(sourceLeafOffset);
425 const auto& sourceArray = sourceLeaf.constAttributeArray(mAttributeIndex);
426 sourceArray.loadData();
430 auto& targetArray = leaf.attributeArray(mAttributeIndex);
431 targetArray.loadData();
432 targetArray.expand();
437 targetArray.copyValuesUnsafe(sourceArray, copyIterator);
444 const Index mAttributeIndex;
455 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT>
464 using PointDataTreeT =
typename PointDataGridT::TreeType;
465 using LeafT =
typename PointDataTreeT::LeafNodeType;
468 using namespace point_move_internal;
471 assert(!objectNotInUse);
472 (
void)objectNotInUse;
474 PointDataTreeT& tree = points.tree();
478 auto iter = tree.cbeginLeaf();
484 auto newPoints = point_mask_internal::convertPointsToScalar<PointDataGridT>(
486 auto& newTree = newPoints->tree();
490 LeafManagerT sourceLeafManager(tree);
491 LeafManagerT targetLeafManager(newTree);
494 const auto& existingAttributeSet = points.tree().cbeginLeaf()->attributeSet();
507 auto sourceRange = sourceLeafManager.leafRange();
508 for (
auto leaf = sourceRange.begin(); leaf; ++leaf) {
509 sourceLeafMap.insert({leaf->origin(),
LeafIndex(static_cast<LeafIndex>(leaf.pos()))});
511 auto targetRange = targetLeafManager.leafRange();
512 for (
auto leaf = targetRange.begin(); leaf; ++leaf) {
513 targetLeafMap.insert({leaf->origin(),
LeafIndex(static_cast<LeafIndex>(leaf.pos()))});
521 targetLeafManager.foreach(
522 [&](LeafT& leaf,
size_t idx) {
525 for (
Index i = 1; i < leaf.buffer().size(); i++) {
529 leaf.replaceAttributeSet(
530 new AttributeSet(existingAttributeSet, leaf.getLastValue(), &lock),
533 const auto it = sourceLeafMap.find(leaf.origin());
534 if (it != sourceLeafMap.end()) {
535 sourceIndices[idx] = it->second;
552 BuildMoveMapsOp<DeformerT, PointDataTreeT, NullFilter> op(deformer,
553 globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
554 transform, points.transform(), nullFilter);
555 sourceLeafManager.foreach(op, threaded);
557 BuildMoveMapsOp<DeformerT, PointDataTreeT, FilterT> op(deformer,
558 globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
559 transform, points.transform(),
filter);
560 sourceLeafManager.foreach(op, threaded);
569 targetLeafManager.foreach(
570 [&](LeafT& ,
size_t idx) {
572 if (moveIndices.empty())
return;
574 IndexArray& sortedIndices = globalMoveLeafIndices[idx];
575 sortedIndices.resize(moveIndices.size());
580 const Index& indexI0(std::get<0>(moveIndices[i]));
581 const Index& indexJ0(std::get<0>(moveIndices[j]));
582 if (indexI0 < indexJ0)
return true;
583 if (indexI0 > indexJ0)
return false;
584 return std::get<2>(moveIndices[i]) < std::get<2>(moveIndices[j]);
590 for (
const auto& it : existingAttributeSet.descriptor().map()) {
592 const Index attributeIndex =
static_cast<Index>(it.second);
595 targetLeafManager.foreach(
596 [&offsetMap](
const LeafT& ,
size_t idx) {
603 GlobalMovePointsOp<PointDataTreeT> globalMoveOp(offsetMap,
604 sourceLeafManager, attributeIndex, globalMoveLeafMap, globalMoveLeafIndices);
605 targetLeafManager.foreach(globalMoveOp, threaded);
609 LocalMovePointsOp<PointDataTreeT> localMoveOp(offsetMap,
610 sourceIndices, sourceLeafManager, attributeIndex, localMoveLeafMap);
611 targetLeafManager.foreach(localMoveOp, threaded);
614 points.setTree(newPoints->treePtr());
618 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT>
625 movePoints(points, points.transform(), deformer,
filter, objectNotInUse, threaded);
632 template <
typename T>
637 template <
typename T>
638 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT>
642 using TreeT =
typename PointDataGridT::TreeType;
643 using LeafT =
typename TreeT::LeafNodeType;
645 LeafManagerT leafManager(grid.tree());
648 auto& leafs = mCache.leafs;
649 leafs.resize(leafManager.leafCount());
651 const auto&
transform = grid.transform();
655 auto cachePositionsOp = [&](
const LeafT& leaf,
size_t idx) {
657 const Index64 totalPointCount = leaf.pointCount();
658 if (totalPointCount == 0)
return;
662 DeformerT newDeformer(deformer);
664 newDeformer.reset(leaf, idx);
668 auto& cache = leafs[idx];
673 const bool useVector = filter.state() ==
index::ALL &&
674 (leaf.isDense() || (leaf.onPointCount() == leaf.pointCount()));
676 cache.vecData.resize(totalPointCount);
679 for (
auto iter = leaf.beginIndexOn(filter); iter; iter++) {
689 newDeformer.apply(position, iter);
690 position =
transform.indexToWorld(position);
693 position =
transform.indexToWorld(position);
694 newDeformer.apply(position, iter);
709 if (!cache.mapData.empty()) {
710 cache.totalSize =
static_cast<Index>(totalPointCount);
714 leafManager.foreach(cachePositionsOp, threaded);
718 template <
typename T>
719 template <
typename LeafT>
722 if (idx >= mCache.leafs.size()) {
723 if (mCache.leafs.empty()) {
724 throw IndexError(
"No leafs in cache, perhaps CachedDeformer has not been evaluated?");
726 throw IndexError(
"Leaf index is out-of-range of cache leafs.");
729 auto& cache = mCache.leafs[idx];
730 if (!cache.mapData.empty()) {
731 mLeafMap = &cache.mapData;
735 mLeafVec = &cache.vecData;
741 template <
typename T>
742 template <
typename IndexIterT>
748 auto it = mLeafMap->find(*iter);
749 if (it == mLeafMap->end())
return;
750 position =
static_cast<openvdb::Vec3d
>(it->second);
755 if (mLeafVec->empty())
return;
756 assert(*iter < mLeafVec->
size());
757 position =
static_cast<openvdb::Vec3d
>((*mLeafVec)[*iter]);
766 #endif // OPENVDB_POINTS_POINT_MOVE_IMPL_HAS_BEEN_INCLUDED
Index targetIndex() const
std::vector< AttributeArray * > AttributeArrays
LocalMovePointsOp(LeafOffsetArray &offsetMap, const LeafIndexArray &sourceIndices, LeafManagerT &sourceLeafManager, const Index attributeIndex, const LocalPointIndexMap &moveLeafMap)
GLsizei GLenum const void * indices
GLdouble GLdouble GLint GLint const GLdouble * points
typename tree::LeafManager< TreeT > LeafManagerT
std::vector< IndexPairArray > LocalPointIndexMap
std::vector< LeafT * > LeafArrayT
#define OPENVDB_USE_VERSION_NAMESPACE
Index sourceIndex() const
GlobalMovePointsOp(LeafOffsetArray &offsetMap, LeafManagerT &sourceLeafManager, const Index attributeIndex, const GlobalPointIndexMap &moveLeafMap, const GlobalPointIndexIndices &moveLeafIndices)
A no-op filter that can be used when iterating over all indices.
void operator()(LeafT &leaf, size_t idx) const
std::vector< LeafIndexArray > LeafOffsetArray
std::tuple< LeafIndex, Index, Index > IndexTriple
static Ptr create(AttributeArray &array, const bool expand=true)
GLuint GLsizei const GLuint const GLintptr * offsets
std::vector< IndexPair > IndexPairArray
std::vector< Index > IndexArray
void operator()(LeafT &leaf, size_t idx) const
Index targetIndex() const
std::vector< LeafT * > LeafArrayT
tbb::concurrent_vector< IndexTriple > IndexTripleArray
Index indexOffsetFromVoxel(const Index voxelOffset, const LeafT &leaf, IndexArray &offsets)
CopyIterator & operator++()
CopyIterator & operator++()
CopyIterator(const LeafT &leaf, const IndexPairArray &indices, IndexArray &offsets)
void operator()(LeafT &leaf, size_t idx) const
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
void movePoints(PointDataGridT &points, const math::Transform &transform, DeformerT &deformer, const FilterT &filter, future::Advect *objectNotInUse, bool threaded)
Move points in a PointDataGrid using a custom deformer and a new transform.
typename TreeT::LeafNodeType LeafT
std::pair< Index, Index > IndexPair
std::unordered_map< Coord, LeafIndex > LeafMap
vfloat4 round(const vfloat4 &a)
GA_API const UT_StringHolder transform
void reset(Index startIndex, Index endIndex)
std::vector< IndexTripleArray > GlobalPointIndexMap
buffer(size_t sz) FMT_NOEXCEPT
BuildMoveMapsOp(const DeformerT &deformer, GlobalPointIndexMap &globalMoveLeafMap, LocalPointIndexMap &localMoveLeafMap, const LeafMap &targetLeafMap, const math::Transform &targetTransform, const math::Transform &sourceTransform, const FilterT &filter)
typename TreeT::LeafNodeType LeafT
typename tree::LeafManager< TreeT > LeafManagerT
static Ptr create(const AttributeArray &array, const bool collapseOnDestruction=true)
std::vector< AttributeArray * > AttributeArrays
SIM_API const UT_StringHolder position
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
Ordered collection of uniquely-named attribute arrays.
typename TreeT::LeafNodeType LeafT
Index leafIndex(Index i) const
CopyIterator(const LeafT &leaf, const IndexArray &sortedIndices, const IndexTripleArray &moveIndices, IndexArray &offsets)
std::vector< LeafT * > LeafArrayT
Index sourceIndex() const
std::vector< IndexArray > GlobalPointIndexIndices
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
void sort(I begin, I end, const Pred &pred)
typename tree::LeafManager< TreeT > LeafManagerT
std::vector< LeafIndex > LeafIndexArray
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.