59 #ifndef OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED 60 #define OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED 62 #include <openvdb/openvdb.h> 64 #include <openvdb/points/PointDataGrid.h> 65 #include <openvdb/points/PointMask.h> 67 #include <tbb/concurrent_vector.h> 74 #include <unordered_map> 86 namespace future {
struct Advect { }; }
95 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT = NullFilter>
100 bool threaded =
true);
110 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT = NullFilter>
111 inline void movePoints(PointDataGridT& points,
116 bool threaded =
true);
120 template <
typename T>
156 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT>
157 void evaluate(PointDataGridT& grid, DeformerT& deformer,
const FilterT& filter,
158 bool threaded =
true);
162 template <
typename LeafT>
163 void reset(
const LeafT& leaf,
size_t idx);
166 template <
typename IndexIterT>
167 void apply(
Vec3d& position,
const IndexIterT& iter)
const;
170 friend class ::TestPointMove;
182 namespace point_move_internal {
204 template<
typename ValueType,
typename OpType>
208 op.operator()<ValueType>(array);
210 op.template operator()<ValueType>(array);
217 template<
typename ArrayType,
typename OpType>
222 using namespace openvdb::math;
251 : mHandles() { mHandles.reserve(size); }
257 return handle->array();
262 const auto* handle = mHandles[leafOffset].get();
264 return handle->array();
267 template <
typename ValueT>
275 template <
typename ValueT>
287 : mHandles(handles) { }
289 template<
typename ValueT>
294 mHandles.emplace_back(handleAsInt);
301 template <
typename LeafRangeT>
302 void cache(
const LeafRangeT& range,
const Index attributeIndex)
304 using namespace openvdb::math;
309 for (
auto leaf = range.begin(); leaf; ++leaf) {
310 auto& array = leaf->attributeArray(attributeIndex);
320 template <
typename DeformerT,
typename TreeT,
typename FilterT>
323 using LeafT =
typename TreeT::LeafNodeType;
330 const std::map<Coord, Index>& targetLeafMap,
333 const FilterT& filter)
334 : mDeformer(deformer)
335 , mGlobalMoveLeafMap(globalMoveLeafMap)
336 , mLocalMoveLeafMap(localMoveLeafMap)
337 , mTargetLeafMap(targetLeafMap)
338 , mTargetTransform(targetTransform)
339 , mSourceTransform(sourceTransform)
340 , mFilter(filter) { }
344 DeformerT deformer(mDeformer);
345 deformer.reset(leaf, idx);
349 Coord sourceLeafOrigin = leaf.origin();
353 for (
auto iter = leaf.beginIndexOn(mFilter); iter; iter++) {
359 Vec3d positionIS = sourceHandle->get(*iter) + iter.getCoord().asVec3d();
361 deformer.apply(positionIS, iter);
366 Vec3d positionWS = mSourceTransform.indexToWorld(positionIS);
367 if (!useIndexSpace) {
368 deformer.apply(positionWS, iter);
373 positionIS = mTargetTransform.worldToIndex(positionWS);
378 Index targetOffset = LeafT::coordToOffset(targetVoxel);
382 Vec3d voxelPosition(positionIS - targetVoxel.
asVec3d());
383 sourceHandle->set(*iter, voxelPosition);
387 Coord targetLeafOrigin = targetVoxel & ~(LeafT::DIM - 1);
388 assert(mTargetLeafMap.find(targetLeafOrigin) != mTargetLeafMap.end());
389 const Index targetLeafOffset(mTargetLeafMap.at(targetLeafOrigin));
393 if (targetLeafOrigin == sourceLeafOrigin) {
394 mLocalMoveLeafMap[targetLeafOffset].emplace_back(targetOffset, *iter);
397 mGlobalMoveLeafMap[targetLeafOffset].push_back(
IndexTriple(idx,
398 targetOffset, *iter));
404 const DeformerT& mDeformer;
407 const std::map<Coord, Index>& mTargetLeafMap;
410 const FilterT& mFilter;
413 template <
typename LeafT>
421 Index targetOffset =
Index(offsets[voxelOffset]++);
422 if (voxelOffset > 0) {
423 targetOffset +=
Index(leaf.getValue(voxelOffset - 1));
428 template <
typename TreeT>
431 using LeafT =
typename TreeT::LeafNodeType;
438 const Index attributeIndex,
440 : mOffsetMap(offsetMap)
441 , mTargetHandles(targetHandles)
442 , mSourceHandles(sourceHandles)
443 , mAttributeIndex(attributeIndex)
444 , mMoveLeafMap(moveLeafMap) { }
449 int targetOffset,
const LeafT& targetLeaf,
451 : mTargetHandles(targetHandles)
452 , mSourceHandles(sourceHandles)
453 , mTargetOffset(targetOffset)
454 , mTargetLeaf(targetLeaf)
456 , mIndices(indices) { }
458 template<
typename ValueT>
461 auto& targetHandle = mTargetHandles.getWriteHandle<ValueT>(mTargetOffset);
462 targetHandle.expand();
467 std::vector<int> sortedIndices(mIndices.size());
468 std::iota(std::begin(sortedIndices), std::end(sortedIndices), 0);
469 std::sort(std::begin(sortedIndices), std::end(sortedIndices),
472 const Index& indexI0(std::get<0>(mIndices[i]));
473 const Index& indexJ0(std::get<0>(mIndices[j]));
474 if (indexI0 < indexJ0)
return true;
475 if (indexI0 > indexJ0)
return false;
476 return std::get<2>(mIndices[i]) < std::get<2>(mIndices[j]);
480 for (
const auto& index : sortedIndices) {
481 const auto& it = mIndices[index];
482 const auto& sourceHandle = mSourceHandles.getHandle<ValueT>(std::get<0>(it));
484 for (
Index i = 0; i < sourceHandle.stride(); i++) {
485 ValueT sourceValue = sourceHandle.get(std::get<2>(it), i);
486 targetHandle.set(targetIndex, i, sourceValue);
495 const LeafT& mTargetLeaf;
503 auto& targetArray = mTargetHandles.getArray(targetOffset);
505 for (
const auto& it : indices) {
506 const auto& sourceArray = mSourceHandles.getConstArray(std::get<0>(it));
508 targetArray.set(tgtOffset, sourceArray, std::get<2>(it));
515 const auto& moveIndices = mMoveLeafMap.at(idx);
516 if (moveIndices.empty())
return;
520 auto& offsets = mOffsetMap[idx];
522 const auto& array = leaf.constAttributeArray(mAttributeIndex);
524 PerformTypedMoveOp op(mTargetHandles, mSourceHandles, idx, leaf, offsets, moveIndices);
526 this->performMove(idx, leaf, offsets, moveIndices);
534 const Index mAttributeIndex;
538 template <
typename TreeT>
541 using LeafT =
typename TreeT::LeafNodeType;
549 const Index attributeIndex,
551 : mOffsetMap(offsetMap)
552 , mTargetHandles(targetHandles)
553 , mSourceIndices(sourceIndices)
554 , mSourceHandles(sourceHandles)
555 , mAttributeIndex(attributeIndex)
556 , mMoveLeafMap(moveLeafMap) { }
561 int targetOffset,
int sourceOffset,
const LeafT& targetLeaf,
563 : mTargetHandles(targetHandles)
564 , mSourceHandles(sourceHandles)
565 , mTargetOffset(targetOffset)
566 , mSourceOffset(sourceOffset)
567 , mTargetLeaf(targetLeaf)
569 , mIndices(indices) { }
571 template<
typename ValueT>
574 auto& targetHandle = mTargetHandles.getWriteHandle<ValueT>(mTargetOffset);
575 const auto& sourceHandle = mSourceHandles.getHandle<ValueT>(mSourceOffset);
577 targetHandle.expand();
579 for (
const auto& it : mIndices) {
581 for (
Index i = 0; i < sourceHandle.stride(); i++) {
582 ValueT sourceValue = sourceHandle.get(it.second, i);
583 targetHandle.set(targetIndex, i, sourceValue);
593 const LeafT& mTargetLeaf;
598 template <
typename ValueT>
602 auto& targetHandle = mTargetHandles.getWriteHandle<ValueT>(targetOffset);
603 const auto& sourceHandle = mSourceHandles.getHandle<ValueT>(sourceOffset);
605 targetHandle.expand();
607 for (
const auto& it : indices) {
609 for (
Index i = 0; i < sourceHandle.stride(); i++) {
610 ValueT sourceValue = sourceHandle.get(it.second, i);
611 targetHandle.set(tgtOffset, i, sourceValue);
619 auto& targetArray = mTargetHandles.getArray(targetOffset);
620 const auto& sourceArray = mSourceHandles.getConstArray(sourceOffset);
622 for (
const auto& it : indices) {
624 targetArray.set(tgtOffset, sourceArray, it.second);
631 const auto& moveIndices = mMoveLeafMap.at(idx);
632 if (moveIndices.empty())
return;
636 auto& offsets = mOffsetMap[idx];
640 assert(idx < mSourceIndices.size());
641 const Index sourceOffset(mSourceIndices[idx]);
643 const auto& array = leaf.constAttributeArray(mAttributeIndex);
646 idx, sourceOffset, leaf, offsets, moveIndices);
648 this->performMove(idx, sourceOffset, leaf, offsets, moveIndices);
657 const Index mAttributeIndex;
667 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT>
671 const FilterT& filter,
675 using PointDataTreeT =
typename PointDataGridT::TreeType;
676 using LeafT =
typename PointDataTreeT::LeafNodeType;
679 using namespace point_move_internal;
682 assert(!objectNotInUse);
683 (void)objectNotInUse;
685 PointDataTreeT& tree = points.tree();
695 auto newPoints = point_mask_internal::convertPointsToScalar<PointDataGrid>(
696 points, transform, filter, deformer, threaded);
697 auto& newTree = newPoints->tree();
701 LeafManagerT sourceLeafManager(tree);
702 LeafManagerT targetLeafManager(newTree);
705 AttributeHandles sourceHandles(sourceLeafManager.leafCount());
706 AttributeHandles targetHandles(targetLeafManager.leafCount());
709 const auto& existingAttributeSet = points.tree().cbeginLeaf()->attributeSet();
714 std::map<Coord, Index> targetLeafMap;
715 std::vector<Index> sourceIndices(targetLeafManager.leafCount(),
718 OffsetMap offsetMap(targetLeafManager.leafCount());
721 std::map<Coord, Index> sourceLeafMap;
722 auto sourceRange = sourceLeafManager.leafRange();
723 for (
auto leaf = sourceRange.begin(); leaf; ++leaf) {
724 sourceLeafMap.insert({leaf->origin(), leaf.pos()});
726 auto targetRange = targetLeafManager.leafRange();
727 for (
auto leaf = targetRange.begin(); leaf; ++leaf) {
728 targetLeafMap.insert({leaf->origin(), leaf.pos()});
732 targetLeafManager.foreach(
733 [&](LeafT& leaf,
size_t idx) {
735 auto* buffer = leaf.buffer().data();
736 for (
Index i = 1; i < leaf.buffer().size(); i++) {
737 buffer[i] = buffer[i-1] + buffer[i];
740 leaf.replaceAttributeSet(
new AttributeSet(existingAttributeSet, leaf.getLastValue()),
743 const auto it = sourceLeafMap.find(leaf.origin());
744 if (it != sourceLeafMap.end()) {
745 sourceIndices[idx] = it->second;
748 offsetMap[idx].resize(LeafT::SIZE);
762 BuildMoveMapsOp<DeformerT, PointDataTreeT, NullFilter> op(deformer,
763 globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
764 transform, points.transform(), nullFilter);
765 sourceLeafManager.foreach(op, threaded);
767 BuildMoveMapsOp<DeformerT, PointDataTreeT, FilterT> op(deformer,
768 globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
769 transform, points.transform(), filter);
770 sourceLeafManager.foreach(op, threaded);
773 for (
const auto& it : existingAttributeSet.descriptor().map()) {
775 const Index attributeIndex =
static_cast<Index>(it.second);
778 targetLeafManager.foreach(
779 [&offsetMap](
const LeafT& ,
size_t idx) {
780 std::fill(offsetMap[
Index(idx)].begin(), offsetMap[
Index(idx)].end(), 0);
786 sourceHandles.cache(sourceLeafManager.leafRange(), attributeIndex);
787 targetHandles.cache(targetLeafManager.leafRange(), attributeIndex);
791 GlobalMovePointsOp<PointDataTreeT> globalMoveOp(offsetMap, targetHandles,
792 sourceHandles, attributeIndex, globalMoveLeafMap);
793 targetLeafManager.foreach(globalMoveOp, threaded);
797 LocalMovePointsOp<PointDataTreeT> localMoveOp(offsetMap, targetHandles,
798 sourceIndices, sourceHandles,
799 attributeIndex, localMoveLeafMap);
800 targetLeafManager.foreach(localMoveOp, threaded);
803 points.setTree(newPoints->treePtr());
807 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT>
810 const FilterT& filter,
814 movePoints(points, points.transform(), deformer, filter, objectNotInUse, threaded);
821 template <
typename T>
826 template <
typename T>
827 template <
typename Po
intDataGr
idT,
typename DeformerT,
typename FilterT>
831 using TreeT =
typename PointDataGridT::TreeType;
832 using LeafT =
typename TreeT::LeafNodeType;
834 LeafManagerT leafManager(grid.tree());
837 auto& leafs = mCache.
leafs;
838 leafs.resize(leafManager.leafCount());
840 const auto& transform = grid.transform();
844 auto cachePositionsOp = [&](
const LeafT& leaf,
size_t idx) {
846 const Index64 totalPointCount = leaf.pointCount();
847 if (totalPointCount == 0)
return;
851 DeformerT newDeformer(deformer);
855 const Index64 vectorThreshold = totalPointCount / 2;
857 newDeformer.reset(leaf, idx);
861 auto& cache = leafs[idx];
866 const bool useVector = filter.state() ==
index::ALL &&
867 (leaf.isDense() || (leaf.onPointCount() > vectorThreshold));
869 cache.vecData.resize(totalPointCount);
872 for (
auto iter = leaf.beginIndexOn(filter); iter; iter++) {
876 Vec3d position = handle->get(*iter) + iter.getCoord().asVec3d();
882 newDeformer.apply(position, iter);
887 newDeformer.apply(position, iter);
893 cache.vecData[*iter] =
static_cast<Vec3T>(position);
896 cache.mapData.insert({*iter,
static_cast<Vec3T>(position)});
902 if (!useVector && cache.mapData.
size() > vectorThreshold) {
903 cache.vecData.resize(totalPointCount);
904 for (
const auto& it : cache.mapData) {
905 cache.vecData[it.first] = it.second;
907 cache.mapData.clear();
912 if (!cache.mapData.empty()) {
913 cache.totalSize =
static_cast<Index>(totalPointCount);
917 leafManager.foreach(cachePositionsOp, threaded);
921 template <
typename T>
922 template <
typename LeafT>
925 if (idx >= mCache.
leafs.size()) {
926 if (mCache.
leafs.empty()) {
927 throw IndexError(
"No leafs in cache, perhaps CachedDeformer has not been evaluated?");
929 throw IndexError(
"Leaf index is out-of-range of cache leafs.");
932 auto& cache = mCache.
leafs[idx];
933 if (!cache.mapData.empty()) {
937 if (cache.mapData.size() > 16 &&
938 cache.totalSize < (cache.mapData.size() * 256)) {
939 if (cache.totalSize < cache.mapData.size()) {
940 throw ValueError(
"Cache total size is not valid.");
942 mLocalLeafVec.resize(cache.totalSize);
943 for (
const auto& it : cache.mapData) {
944 assert(it.first < cache.totalSize);
945 mLocalLeafVec[it.first] = it.second;
947 mLeafVec = &mLocalLeafVec;
951 mLeafMap = &cache.mapData;
956 mLeafVec = &cache.vecData;
962 template <
typename T>
963 template <
typename IndexIterT>
969 auto it = mLeafMap->find(*iter);
970 if (it == mLeafMap->end())
return;
976 if (mLeafVec->empty())
return;
977 assert(*iter < mLeafVec->size());
987 #endif // OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:323
void cache(const LeafRangeT &range, const Index attributeIndex)
Definition: PointMove.h:302
Definition: PointMove.h:321
bool processTypedArray(const ArrayType &array, OpType &op)
Utility function that, given a generic attribute array, calls a functor with the fully-resolved value...
Definition: PointMove.h:219
Write-able version of AttributeHandle.
Definition: AttributeArray.h:715
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:668
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:432
Helper class used internally by processTypedArray()
Definition: PointMove.h:205
void operator()(LeafT &leaf, size_t aIdx) const
Definition: PointMove.h:512
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:433
std::vector< IndexTripleArray > GlobalPointIndexMap
Definition: PointMove.h:187
std::vector< IndexArray > OffsetMap
Definition: PointMove.h:194
void operator()(const LeafT &leaf, size_t aIdx) const
Definition: PointMove.h:628
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
AttributeWriteHandle< ValueT > & getWriteHandle(const Index leafOffset)
Definition: PointMove.h:276
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:325
const AttributeArray & getConstArray(const Index leafOffset) const
Definition: PointMove.h:260
AttributeArray & getArray(const Index leafOffset)
Definition: PointMove.h:253
void operator()(LeafT &leaf, size_t idx) const
Definition: PointMove.h:342
Index size() const
Definition: AttributeArray.h:667
std::vector< AttributeHandle< int >::Ptr > HandleArray
Definition: PointMove.h:248
Definition: IndexIterator.h:70
static Ptr create(const AttributeArray &array, const bool preserveCompression=true)
Definition: AttributeArray.h:1864
4x4 -matrix class.
Definition: Mat3.h:49
Vec3< double > Vec3d
Definition: Vec3.h:679
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:542
Cache read and write attribute handles to amortize construction cost.
Definition: PointMove.h:246
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
static void call(OpType &op, const AttributeArray &array)
Definition: PointMove.h:206
GlobalMovePointsOp(OffsetMap &offsetMap, AttributeHandles &targetHandles, AttributeHandles &sourceHandles, const Index attributeIndex, const GlobalPointIndexMap &moveLeafMap)
Definition: PointMove.h:435
Definition: Exceptions.h:92
std::tuple< Index, Index, Index > IndexTriple
Definition: PointMove.h:185
CacheHandleOp(HandleArray &handles)
Definition: PointMove.h:286
Definition: PointMove.h:86
Index indexOffsetFromVoxel(const Index voxelOffset, const LeafT &leaf, IndexArray &offsets)
Definition: PointMove.h:415
LocalMovePointsOp(OffsetMap &offsetMap, AttributeHandles &targetHandles, const IndexArray &sourceIndices, AttributeHandles &sourceHandles, const Index attributeIndex, const LocalPointIndexMap &moveLeafMap)
Definition: PointMove.h:545
Definition: Exceptions.h:40
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels) ...
Definition: TreeIterator.h:1235
tbb::concurrent_vector< IndexTriple > IndexTripleArray
Definition: PointMove.h:186
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:77
Create a handle and reinterpret cast as an int handle to store.
Definition: PointMove.h:284
Index32 Index
Definition: Types.h:61
3x3 matrix class.
Definition: Mat3.h:55
Definition: AttributeArray.h:644
Base class for storing attribute data.
Definition: AttributeArray.h:118
uint64_t Index64
Definition: Types.h:60
static Coord round(const Vec3< T > &xyz)
Return xyz rounded to the closest integer coordinates (cell centered conversion). ...
Definition: Coord.h:77
void performMove(int targetOffset, const LeafT &targetLeaf, IndexArray &offsets, const IndexTripleArray &indices) const
Definition: PointMove.h:500
Definition: PointMove.h:539
std::vector< IndexPair > IndexPairArray
Definition: PointMove.h:190
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:110
typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:541
AttributeHandles(const size_t size)
Definition: PointMove.h:250
Definition: Exceptions.h:84
void performTypedMove(int sourceOffset, int targetOffset, const LeafT &targetLeaf, IndexArray &offsets, const IndexPairArray &indices) const
Definition: PointMove.h:599
AttributeHandle< ValueT > & getHandle(const Index leafOffset)
Definition: PointMove.h:268
void performMove(int targetOffset, int sourceOffset, const LeafT &targetLeaf, IndexArray &offsets, const IndexPairArray &indices) const
Definition: PointMove.h:616
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:62
typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:431
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:543
std::vector< Index > IndexArray
Definition: PointMove.h:193
std::vector< IndexPairArray > LocalPointIndexMap
Definition: PointMove.h:191
Vec3d asVec3d() const
Definition: Coord.h:170
std::pair< Index, Index > IndexPair
Definition: PointMove.h:189
BuildMoveMapsOp(const DeformerT &deformer, GlobalPointIndexMap &globalMoveLeafMap, LocalPointIndexMap &localMoveLeafMap, const std::map< Coord, Index > &targetLeafMap, const math::Transform &targetTransform, const math::Transform &sourceTransform, const FilterT &filter)
Definition: PointMove.h:327
Definition: PointMove.h:429
void operator()(const AttributeArray &array) const
Definition: PointMove.h:290
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:324