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);
316 HandleArray mHandles;
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;
971 position = static_cast<openvdb::Vec3d>(it->second);
976 if (mLeafVec->empty())
return;
977 assert(*iter < mLeafVec->size());
978 position = static_cast<openvdb::Vec3d>((*mLeafVec)[*iter]);
987 #endif // OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED