Loading...
Searching...
No Matches
PointMove.h
Go to the documentation of this file.
// Copyright Contributors to the OpenVDB Project
// SPDX-License-Identifier: MPL-2.0
/// @author Dan Bailey
///
/// @file PointMove.h
///
/// @brief Ability to move VDB Points using a custom deformer.
///
/// Deformers used when moving points are in world space by default and must adhere
/// to the interface described in the example below:
/// @code
/// struct MyDeformer
/// {
/// // A reset is performed on each leaf in turn before the points in that leaf are
/// // deformed. A leaf and leaf index (standard leaf traversal order) are supplied as
/// // the arguments, which matches the functor interface for LeafManager::foreach().
/// template <typename LeafNoteType>
/// void reset(LeafNoteType& leaf, size_t idx);
///
/// // Evaluate the deformer and modify the given position to generate the deformed
/// // position. An index iterator is supplied as the argument to allow querying the
/// // point offset or containing voxel coordinate.
/// template <typename IndexIterT>
/// void apply(Vec3d& position, const IndexIterT& iter) const;
/// };
/// @endcode
///
/// @note The DeformerTraits struct (defined in PointMask.h) can be used to configure
/// a deformer to evaluate in index space.
#ifndef OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED
#define OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED
#include <openvdb/openvdb.h>
#include "PointDataGrid.h"
#include "PointMask.h"
#include <tbb/concurrent_vector.h>
#include <algorithm>
#include <iterator> // for std::begin(), std::end()
#include <map>
#include <numeric> // for std::iota()
#include <tuple>
#include <unordered_map>
#include <vector>
class TestPointMove;
namespace openvdb {
OPENVDB_USE_VERSION_NAMESPACE
namespace OPENVDB_VERSION_NAME {
namespace points {
// dummy object for future use
namespace future { struct Advect { }; }
/// @brief Move points in a PointDataGrid using a custom deformer
/// @param points the PointDataGrid containing the points to be moved.
/// @param deformer a custom deformer that defines how to move the points.
/// @param filter an optional index filter
/// @param objectNotInUse for future use, this object is currently ignored
/// @param threaded enable or disable threading (threading is enabled by default)
template <typename PointDataGridT, typename DeformerT, typename FilterT = NullFilter>
inline void movePoints(PointDataGridT& points,
DeformerT& deformer,
const FilterT& filter = NullFilter(),
future::Advect* objectNotInUse = nullptr,
bool threaded = true);
/// @brief Move points in a PointDataGrid using a custom deformer and a new transform
/// @param points the PointDataGrid containing the points to be moved.
/// @param transform target transform to use for the resulting points.
/// @param deformer a custom deformer that defines how to move the points.
/// @param filter an optional index filter
/// @param objectNotInUse for future use, this object is currently ignored
/// @param threaded enable or disable threading (threading is enabled by default)
template <typename PointDataGridT, typename DeformerT, typename FilterT = NullFilter>
inline void movePoints(PointDataGridT& points,
const math::Transform& transform,
DeformerT& deformer,
const FilterT& filter = NullFilter(),
future::Advect* objectNotInUse = nullptr,
bool threaded = true);
// define leaf index in use as 32-bit
namespace point_move_internal { using LeafIndex = Index32; }
/// @brief A Deformer that caches the resulting positions from evaluating another Deformer
template <typename T>
class CachedDeformer
{
public:
using LeafIndex = point_move_internal::LeafIndex;
using Vec3T = typename math::Vec3<T>;
using LeafVecT = std::vector<Vec3T>;
using LeafMapT = std::unordered_map<LeafIndex, Vec3T>;
// Internal data cache to allow the deformer to offer light-weight copying
struct Cache
{
struct Leaf
{
/// @brief clear data buffers and reset counter
void clear() {
vecData.clear();
mapData.clear();
totalSize = 0;
}
LeafVecT vecData;
LeafMapT mapData;
Index totalSize = 0;
}; // struct Leaf
std::vector<Leaf> leafs;
}; // struct Cache
/// Cache is expected to be persistent for the lifetime of the CachedDeformer
explicit CachedDeformer(Cache& cache);
/// Caches the result of evaluating the supplied point grid using the deformer and filter
/// @param grid the points to be moved
/// @param deformer the deformer to apply to the points
/// @param filter the point filter to use when evaluating the points
/// @param threaded enable or disable threading (threading is enabled by default)
template <typename PointDataGridT, typename DeformerT, typename FilterT>
void evaluate(PointDataGridT& grid, DeformerT& deformer, const FilterT& filter,
bool threaded = true);
/// Stores pointers to the vector or map and optionally expands the map into a vector
/// @throw IndexError if idx is out-of-range of the leafs in the cache
template <typename LeafT>
void reset(const LeafT& leaf, size_t idx);
/// Retrieve the new position from the cache
template <typename IndexIterT>
void apply(Vec3d& position, const IndexIterT& iter) const;
private:
friend class ::TestPointMove;
Cache& mCache;
const LeafVecT* mLeafVec = nullptr;
const LeafMapT* mLeafMap = nullptr;
}; // class CachedDeformer
////////////////////////////////////////
namespace point_move_internal {
using IndexArray = std::vector<Index>;
using IndexTriple = std::tuple<LeafIndex, Index, Index>;
using IndexTripleArray = tbb::concurrent_vector<IndexTriple>;
using GlobalPointIndexMap = std::vector<IndexTripleArray>;
using GlobalPointIndexIndices = std::vector<IndexArray>;
using IndexPair = std::pair<Index, Index>;
using IndexPairArray = std::vector<IndexPair>;
using LocalPointIndexMap = std::vector<IndexPairArray>;
using LeafIndexArray = std::vector<LeafIndex>;
using LeafOffsetArray = std::vector<LeafIndexArray>;
using LeafMap = std::unordered_map<Coord, LeafIndex>;
template <typename DeformerT, typename TreeT, typename FilterT>
struct BuildMoveMapsOp
{
using LeafT = typename TreeT::LeafNodeType;
using LeafArrayT = std::vector<LeafT*>;
using LeafManagerT = typename tree::LeafManager<TreeT>;
BuildMoveMapsOp(const DeformerT& deformer,
GlobalPointIndexMap& globalMoveLeafMap,
LocalPointIndexMap& localMoveLeafMap,
const LeafMap& targetLeafMap,
const math::Transform& targetTransform,
const math::Transform& sourceTransform,
const FilterT& filter)
: mDeformer(deformer)
, mGlobalMoveLeafMap(globalMoveLeafMap)
, mLocalMoveLeafMap(localMoveLeafMap)
, mTargetLeafMap(targetLeafMap)
, mTargetTransform(targetTransform)
, mSourceTransform(sourceTransform)
, mFilter(filter) { }
void operator()(LeafT& leaf, size_t idx) const
{
DeformerT deformer(mDeformer);
deformer.reset(leaf, idx);
// determine source leaf node origin and offset in the source leaf vector
Coord sourceLeafOrigin = leaf.origin();
auto sourceHandle = AttributeWriteHandle<Vec3f>::create(leaf.attributeArray("P"));
for (auto iter = leaf.beginIndexOn(mFilter); iter; iter++) {
const bool useIndexSpace = DeformerTraits<DeformerT>::IndexSpace;
// extract index-space position and apply index-space deformation (if applicable)
Vec3d positionIS = sourceHandle->get(*iter) + iter.getCoord().asVec3d();
if (useIndexSpace) {
deformer.apply(positionIS, iter);
}
// transform to world-space position and apply world-space deformation (if applicable)
Vec3d positionWS = mSourceTransform.indexToWorld(positionIS);
if (!useIndexSpace) {
deformer.apply(positionWS, iter);
}
// transform to index-space position of target grid
positionIS = mTargetTransform.worldToIndex(positionWS);
// determine target voxel and offset
Coord targetVoxel = Coord::round(positionIS);
Index targetOffset = LeafT::coordToOffset(targetVoxel);
// set new local position in source transform space (if point has been deformed)
Vec3d voxelPosition(positionIS - targetVoxel.asVec3d());
sourceHandle->set(*iter, voxelPosition);
// determine target leaf node origin and offset in the target leaf vector
Coord targetLeafOrigin = targetVoxel & ~(LeafT::DIM - 1);
assert(mTargetLeafMap.find(targetLeafOrigin) != mTargetLeafMap.end());
const LeafIndex targetLeafOffset(mTargetLeafMap.at(targetLeafOrigin));
// insert into move map based on whether point ends up in a new leaf node or not
if (targetLeafOrigin == sourceLeafOrigin) {
mLocalMoveLeafMap[targetLeafOffset].emplace_back(targetOffset, *iter);
}
else {
mGlobalMoveLeafMap[targetLeafOffset].push_back(IndexTriple(
LeafIndex(static_cast<LeafIndex>(idx)), targetOffset, *iter));
}
}
}
private:
const DeformerT& mDeformer;
GlobalPointIndexMap& mGlobalMoveLeafMap;
LocalPointIndexMap& mLocalMoveLeafMap;
const LeafMap& mTargetLeafMap;
const math::Transform& mTargetTransform;
const math::Transform& mSourceTransform;
const FilterT& mFilter;
}; // struct BuildMoveMapsOp
template <typename LeafT>
inline Index
indexOffsetFromVoxel(const Index voxelOffset, const LeafT& leaf, IndexArray& offsets)
{
// compute the target point index by summing the point index of the previous
// voxel with the current number of points added to this voxel, tracked by the
// offsets array
Index targetOffset = offsets[voxelOffset]++;
if (voxelOffset > 0) {
targetOffset += static_cast<Index>(leaf.getValue(voxelOffset - 1));
}
return targetOffset;
}
template <typename TreeT>
struct GlobalMovePointsOp
{
using LeafT = typename TreeT::LeafNodeType;
using LeafArrayT = std::vector<LeafT*>;
using LeafManagerT = typename tree::LeafManager<TreeT>;
using AttributeArrays = std::vector<AttributeArray*>;
GlobalMovePointsOp(LeafOffsetArray& offsetMap,
LeafManagerT& sourceLeafManager,
const Index attributeIndex,
const GlobalPointIndexMap& moveLeafMap,
const GlobalPointIndexIndices& moveLeafIndices)
: mOffsetMap(offsetMap)
, mSourceLeafManager(sourceLeafManager)
, mAttributeIndex(attributeIndex)
, mMoveLeafMap(moveLeafMap)
, mMoveLeafIndices(moveLeafIndices) { }
// A CopyIterator is designed to use the indices in a GlobalPointIndexMap for this leaf
// and match the interface required for AttributeArray::copyValues()
struct CopyIterator
{
CopyIterator(const LeafT& leaf, const IndexArray& sortedIndices,
const IndexTripleArray& moveIndices, IndexArray& offsets)
: mLeaf(leaf)
, mSortedIndices(sortedIndices)
, mMoveIndices(moveIndices)
, mOffsets(offsets) { }
operator bool() const { return bool(mIt); }
void reset(Index startIndex, Index endIndex)
{
mIndex = startIndex;
mEndIndex = endIndex;
this->advance();
}
CopyIterator& operator++()
{
this->advance();
return *this;
}
Index leafIndex(Index i) const
{
if (i < mSortedIndices.size()) {
return std::get<0>(this->leafIndexTriple(i));
}
return std::numeric_limits<Index>::max();
}
Index sourceIndex() const
{
assert(mIt);
return std::get<2>(*mIt);
}
Index targetIndex() const
{
assert(mIt);
return indexOffsetFromVoxel(std::get<1>(*mIt), mLeaf, mOffsets);
}
private:
void advance()
{
if (mIndex >= mEndIndex || mIndex >= mSortedIndices.size()) {
mIt = nullptr;
}
else {
mIt = &this->leafIndexTriple(mIndex);
}
++mIndex;
}
const IndexTriple& leafIndexTriple(Index i) const
{
return mMoveIndices[mSortedIndices[i]];
}
private:
const LeafT& mLeaf;
Index mIndex;
Index mEndIndex;
const IndexArray& mSortedIndices;
const IndexTripleArray& mMoveIndices;
IndexArray& mOffsets;
const IndexTriple* mIt = nullptr;
}; // struct CopyIterator
void operator()(LeafT& leaf, size_t idx) const
{
const IndexTripleArray& moveIndices = mMoveLeafMap[idx];
if (moveIndices.empty()) return;
const IndexArray& sortedIndices = mMoveLeafIndices[idx];
// extract per-voxel offsets for this leaf
LeafIndexArray& offsets = mOffsetMap[idx];
// extract target array and ensure data is out-of-core and non-uniform
auto& targetArray = leaf.attributeArray(mAttributeIndex);
targetArray.loadData();
targetArray.expand();
// perform the copy
CopyIterator copyIterator(leaf, sortedIndices, moveIndices, offsets);
// use the sorted indices to track the index of the source leaf
Index sourceLeafIndex = copyIterator.leafIndex(0);
Index startIndex = 0;
for (size_t i = 1; i <= sortedIndices.size(); i++) {
Index endIndex = static_cast<Index>(i);
Index newSourceLeafIndex = copyIterator.leafIndex(endIndex);
// when it changes, do a batch-copy of all the indices that lie within this range
// TODO: this step could use nested parallelization for cases where there are a
// large number of points being moved per attribute
if (newSourceLeafIndex > sourceLeafIndex) {
copyIterator.reset(startIndex, endIndex);
const LeafT& sourceLeaf = mSourceLeafManager.leaf(sourceLeafIndex);
const auto& sourceArray = sourceLeaf.constAttributeArray(mAttributeIndex);
sourceArray.loadData();
targetArray.copyValuesUnsafe(sourceArray, copyIterator);
sourceLeafIndex = newSourceLeafIndex;
startIndex = endIndex;
}
}
}
private:
LeafOffsetArray& mOffsetMap;
LeafManagerT& mSourceLeafManager;
const Index mAttributeIndex;
const GlobalPointIndexMap& mMoveLeafMap;
const GlobalPointIndexIndices& mMoveLeafIndices;
}; // struct GlobalMovePointsOp
template <typename TreeT>
struct LocalMovePointsOp
{
using LeafT = typename TreeT::LeafNodeType;
using LeafArrayT = std::vector<LeafT*>;
using LeafManagerT = typename tree::LeafManager<TreeT>;
using AttributeArrays = std::vector<AttributeArray*>;
LocalMovePointsOp( LeafOffsetArray& offsetMap,
const LeafIndexArray& sourceIndices,
LeafManagerT& sourceLeafManager,
const Index attributeIndex,
const LocalPointIndexMap& moveLeafMap)
: mOffsetMap(offsetMap)
, mSourceIndices(sourceIndices)
, mSourceLeafManager(sourceLeafManager)
, mAttributeIndex(attributeIndex)
, mMoveLeafMap(moveLeafMap) { }
// A CopyIterator is designed to use the indices in a LocalPointIndexMap for this leaf
// and match the interface required for AttributeArray::copyValues()
struct CopyIterator
{
CopyIterator(const LeafT& leaf, const IndexPairArray& indices, IndexArray& offsets)
: mLeaf(leaf)
, mIndices(indices)
, mOffsets(offsets) { }
operator bool() const { return mIndex < static_cast<int>(mIndices.size()); }
CopyIterator& operator++() { ++mIndex; return *this; }
Index sourceIndex() const
{
return mIndices[mIndex].second;
}
Index targetIndex() const
{
return indexOffsetFromVoxel(mIndices[mIndex].first, mLeaf, mOffsets);
}
private:
const LeafT& mLeaf;
const IndexPairArray& mIndices;
IndexArray& mOffsets;
int mIndex = 0;
}; // struct CopyIterator
void operator()(LeafT& leaf, size_t idx) const
{
const IndexPairArray& moveIndices = mMoveLeafMap[idx];
if (moveIndices.empty()) return;
// extract per-voxel offsets for this leaf
LeafIndexArray& offsets = mOffsetMap[idx];
// extract source array that has the same origin as the target leaf
assert(idx < mSourceIndices.size());
const Index sourceLeafOffset(mSourceIndices[idx]);
LeafT& sourceLeaf = mSourceLeafManager.leaf(sourceLeafOffset);
const auto& sourceArray = sourceLeaf.constAttributeArray(mAttributeIndex);
sourceArray.loadData();
// extract target array and ensure data is out-of-core and non-uniform
auto& targetArray = leaf.attributeArray(mAttributeIndex);
targetArray.loadData();
targetArray.expand();
// perform the copy
CopyIterator copyIterator(leaf, moveIndices, offsets);
targetArray.copyValuesUnsafe(sourceArray, copyIterator);
}
private:
LeafOffsetArray& mOffsetMap;
const LeafIndexArray& mSourceIndices;
LeafManagerT& mSourceLeafManager;
const Index mAttributeIndex;
const LocalPointIndexMap& mMoveLeafMap;
}; // struct LocalMovePointsOp
} // namespace point_move_internal
////////////////////////////////////////
template <typename PointDataGridT, typename DeformerT, typename FilterT>
inline void movePoints( PointDataGridT& points,
const math::Transform& transform,
DeformerT& deformer,
const FilterT& filter,
future::Advect* objectNotInUse,
bool threaded)
{
using LeafIndex = point_move_internal::LeafIndex;
using PointDataTreeT = typename PointDataGridT::TreeType;
using LeafT = typename PointDataTreeT::LeafNodeType;
using LeafManagerT = typename tree::LeafManager<PointDataTreeT>;
using namespace point_move_internal;
// this object is for future use only
assert(!objectNotInUse);
(void)objectNotInUse;
PointDataTreeT& tree = points.tree();
// early exit if no LeafNodes
auto iter = tree.cbeginLeaf();
if (!iter) return;
// build voxel topology taking into account any point group deletion
auto newPoints = point_mask_internal::convertPointsToScalar<PointDataGridT>(
points, transform, filter, deformer, threaded);
auto& newTree = newPoints->tree();
// create leaf managers for both trees
LeafManagerT sourceLeafManager(tree);
LeafManagerT targetLeafManager(newTree);
// extract the existing attribute set
const auto& existingAttributeSet = points.tree().cbeginLeaf()->attributeSet();
// build a coord -> index map for looking up target leafs by origin and a faster
// unordered map for finding the source index from a target index
LeafMap targetLeafMap;
LeafIndexArray sourceIndices(targetLeafManager.leafCount(),
std::numeric_limits<LeafIndex>::max());
LeafOffsetArray offsetMap(targetLeafManager.leafCount());
{
LeafMap sourceLeafMap;
auto sourceRange = sourceLeafManager.leafRange();
for (auto leaf = sourceRange.begin(); leaf; ++leaf) {
sourceLeafMap.insert({leaf->origin(), LeafIndex(static_cast<LeafIndex>(leaf.pos()))});
}
auto targetRange = targetLeafManager.leafRange();
for (auto leaf = targetRange.begin(); leaf; ++leaf) {
targetLeafMap.insert({leaf->origin(), LeafIndex(static_cast<LeafIndex>(leaf.pos()))});
}
// acquire registry lock to avoid locking when appending attributes in parallel
AttributeArray::ScopedRegistryLock lock;
// perform four independent per-leaf operations in parallel
targetLeafManager.foreach(
[&](LeafT& leaf, size_t idx) {
// map frequency => cumulative histogram
auto* buffer = leaf.buffer().data();
for (Index i = 1; i < leaf.buffer().size(); i++) {
buffer[i] = buffer[i-1] + buffer[i];
}
// replace attribute set with a copy of the existing one
leaf.replaceAttributeSet(
new AttributeSet(existingAttributeSet, leaf.getLastValue(), &lock),
/*allowMismatchingDescriptors=*/true);
// store the index of the source leaf in a corresponding target leaf array
const auto it = sourceLeafMap.find(leaf.origin());
if (it != sourceLeafMap.end()) {
sourceIndices[idx] = it->second;
}
// allocate offset maps
offsetMap[idx].resize(LeafT::SIZE);
},
threaded);
}
// moving leaf
GlobalPointIndexMap globalMoveLeafMap(targetLeafManager.leafCount());
LocalPointIndexMap localMoveLeafMap(targetLeafManager.leafCount());
// build global and local move leaf maps and update local positions
if (filter.state() == index::ALL) {
NullFilter nullFilter;
BuildMoveMapsOp<DeformerT, PointDataTreeT, NullFilter> op(deformer,
globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
transform, points.transform(), nullFilter);
sourceLeafManager.foreach(op, threaded);
} else {
BuildMoveMapsOp<DeformerT, PointDataTreeT, FilterT> op(deformer,
globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
transform, points.transform(), filter);
sourceLeafManager.foreach(op, threaded);
}
// build a sorted index vector for each leaf that references the global move map
// indices in order of their source leafs and voxels to ensure determinism in the
// resulting point orders
GlobalPointIndexIndices globalMoveLeafIndices(globalMoveLeafMap.size());
targetLeafManager.foreach(
[&](LeafT& /*leaf*/, size_t idx) {
const IndexTripleArray& moveIndices = globalMoveLeafMap[idx];
if (moveIndices.empty()) return;
IndexArray& sortedIndices = globalMoveLeafIndices[idx];
sortedIndices.resize(moveIndices.size());
std::iota(std::begin(sortedIndices), std::end(sortedIndices), 0);
std::sort(std::begin(sortedIndices), std::end(sortedIndices),
[&](int i, int j)
{
const Index& indexI0(std::get<0>(moveIndices[i]));
const Index& indexJ0(std::get<0>(moveIndices[j]));
if (indexI0 < indexJ0) return true;
if (indexI0 > indexJ0) return false;
return std::get<2>(moveIndices[i]) < std::get<2>(moveIndices[j]);
}
);
},
threaded);
for (const auto& it : existingAttributeSet.descriptor().map()) {
const Index attributeIndex = static_cast<Index>(it.second);
// zero offsets
targetLeafManager.foreach(
[&offsetMap](const LeafT& /*leaf*/, size_t idx) {
std::fill(offsetMap[idx].begin(), offsetMap[idx].end(), 0);
},
threaded);
// move points between leaf nodes
GlobalMovePointsOp<PointDataTreeT> globalMoveOp(offsetMap,
sourceLeafManager, attributeIndex, globalMoveLeafMap, globalMoveLeafIndices);
targetLeafManager.foreach(globalMoveOp, threaded);
// move points within leaf nodes
LocalMovePointsOp<PointDataTreeT> localMoveOp(offsetMap,
sourceIndices, sourceLeafManager, attributeIndex, localMoveLeafMap);
targetLeafManager.foreach(localMoveOp, threaded);
}
points.setTree(newPoints->treePtr());
}
template <typename PointDataGridT, typename DeformerT, typename FilterT>
inline void movePoints( PointDataGridT& points,
DeformerT& deformer,
const FilterT& filter,
future::Advect* objectNotInUse,
bool threaded)
{
movePoints(points, points.transform(), deformer, filter, objectNotInUse, threaded);
}
////////////////////////////////////////
template <typename T>
CachedDeformer<T>::CachedDeformer(Cache& cache)
: mCache(cache) { }
template <typename T>
template <typename PointDataGridT, typename DeformerT, typename FilterT>
void CachedDeformer<T>::evaluate(PointDataGridT& grid, DeformerT& deformer, const FilterT& filter,
bool threaded)
{
using TreeT = typename PointDataGridT::TreeType;
using LeafT = typename TreeT::LeafNodeType;
using LeafManagerT = typename tree::LeafManager<TreeT>;
LeafManagerT leafManager(grid.tree());
// initialize cache
auto& leafs = mCache.leafs;
leafs.resize(leafManager.leafCount());
const auto& transform = grid.transform();
// insert deformed positions into the cache
auto cachePositionsOp = [&](const LeafT& leaf, size_t idx) {
const Index64 totalPointCount = leaf.pointCount();
if (totalPointCount == 0) return;
// deformer is copied to ensure that it is unique per-thread
DeformerT newDeformer(deformer);
newDeformer.reset(leaf, idx);
auto handle = AttributeHandle<Vec3f>::create(leaf.constAttributeArray("P"));
auto& cache = leafs[idx];
cache.clear();
// only insert into a vector directly if the filter evaluates all points
// and all points are stored in active voxels
const bool useVector = filter.state() == index::ALL &&
(leaf.isDense() || (leaf.onPointCount() == leaf.pointCount()));
if (useVector) {
cache.vecData.resize(totalPointCount);
}
for (auto iter = leaf.beginIndexOn(filter); iter; iter++) {
// extract index-space position and apply index-space deformation (if defined)
Vec3d position = handle->get(*iter) + iter.getCoord().asVec3d();
// if deformer is designed to be used in index-space, perform deformation prior
// to transforming position to world-space, otherwise perform deformation afterwards
if (DeformerTraits<DeformerT>::IndexSpace) {
newDeformer.apply(position, iter);
position = transform.indexToWorld(position);
}
else {
position = transform.indexToWorld(position);
newDeformer.apply(position, iter);
}
// insert new position into the cache
if (useVector) {
cache.vecData[*iter] = static_cast<Vec3T>(position);
}
else {
cache.mapData.insert({*iter, static_cast<Vec3T>(position)});
}
}
// store the total number of points to allow use of an expanded vector on access
if (!cache.mapData.empty()) {
cache.totalSize = static_cast<Index>(totalPointCount);
}
};
leafManager.foreach(cachePositionsOp, threaded);
}
template <typename T>
template <typename LeafT>
void CachedDeformer<T>::reset(const LeafT& /*leaf*/, size_t idx)
{
if (idx >= mCache.leafs.size()) {
if (mCache.leafs.empty()) {
throw IndexError("No leafs in cache, perhaps CachedDeformer has not been evaluated?");
} else {
throw IndexError("Leaf index is out-of-range of cache leafs.");
}
}
auto& cache = mCache.leafs[idx];
if (!cache.mapData.empty()) {
mLeafMap = &cache.mapData;
mLeafVec = nullptr;
}
else {
mLeafVec = &cache.vecData;
mLeafMap = nullptr;
}
}
template <typename T>
template <typename IndexIterT>
void CachedDeformer<T>::apply(Vec3d& position, const IndexIterT& iter) const
{
assert(*iter >= 0);
if (mLeafMap) {
auto it = mLeafMap->find(*iter);
if (it == mLeafMap->end()) return;
position = static_cast<openvdb::Vec3d>(it->second);
}
else {
assert(mLeafVec);
if (mLeafVec->empty()) return;
assert(*iter < mLeafVec->size());
position = static_cast<openvdb::Vec3d>((*mLeafVec)[*iter]);
}
}
} // namespace points
} // namespace OPENVDB_VERSION_NAME
} // namespace openvdb
#endif // OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED
PointDataGrid.h
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
PointMask.h
Methods for extracting masks from VDB Point grids.
openvdb::v10_0::Coord::round
static Coord round(const Vec3< T > &xyz)
Return xyz rounded to the closest integer coordinates (cell centered conversion).
Definition Coord.h:50
openvdb::v10_0::IndexError
Definition Exceptions.h:57
openvdb::v10_0::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:25
openvdb::v10_0::math::Coord::asVec3d
Vec3d asVec3d() const
Definition Coord.h:143
openvdb::v10_0::math::Transform
Definition Transform.h:40
openvdb::v10_0::math::Transform::indexToWorld
Vec3d indexToWorld(const Vec3d &xyz) const
Apply this transformation to the given coordinates.
Definition Transform.h:108
openvdb::v10_0::math::Vec3
Definition Vec3.h:24
openvdb::v10_0::points::AttributeArray::ScopedRegistryLock
Definition AttributeArray.h:119
openvdb::v10_0::points::AttributeHandle::create
static Ptr create(const AttributeArray &array, const bool collapseOnDestruction=true)
Definition AttributeArray.h:2116
openvdb::v10_0::points::AttributeSet
Ordered collection of uniquely-named attribute arrays.
Definition AttributeSet.h:39
openvdb::v10_0::points::AttributeWriteHandle::create
static Ptr create(AttributeArray &array, const bool expand=true)
Definition AttributeArray.h:2236
openvdb::v10_0::points::CachedDeformer::CachedDeformer
CachedDeformer(Cache &cache)
Cache is expected to be persistent for the lifetime of the CachedDeformer.
Definition PointMove.h:706
openvdb::v10_0::points::CachedDeformer::reset
void reset(const LeafT &leaf, size_t idx)
Definition PointMove.h:793
openvdb::v10_0::points::CachedDeformer::apply
void apply(Vec3d &position, const IndexIterT &iter) const
Retrieve the new position from the cache.
Definition PointMove.h:816
openvdb::v10_0::points::CachedDeformer::LeafIndex
point_move_internal::LeafIndex LeafIndex
Definition PointMove.h:101
openvdb::v10_0::points::CachedDeformer::LeafMapT
std::unordered_map< LeafIndex, Vec3T > LeafMapT
Definition PointMove.h:104
openvdb::v10_0::points::CachedDeformer::Vec3T
typename math::Vec3< T > Vec3T
Definition PointMove.h:102
openvdb::v10_0::points::CachedDeformer::LeafVecT
std::vector< Vec3T > LeafVecT
Definition PointMove.h:103
openvdb::v10_0::points::CachedDeformer::evaluate
void evaluate(PointDataGridT &grid, DeformerT &deformer, const FilterT &filter, bool threaded=true)
Definition PointMove.h:712
openvdb::v10_0::points::NullFilter
A no-op filter that can be used when iterating over all indices.
Definition IndexIterator.h:51
openvdb::v10_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:85
openvdb::v10_0::math::Vec3d
Vec3< double > Vec3d
Definition Vec3.h:664
openvdb::v10_0::points::future
A container for ABI=5 to help ease introduction of upcoming features.
Definition AttributeSet.h:295
openvdb::v10_0::points::index::ALL
@ ALL
Definition IndexIterator.h:43
openvdb::v10_0::points::point_move_internal
Definition PointMove.h:93
openvdb::v10_0::points::point_move_internal::LeafIndex
Index32 LeafIndex
Definition PointMove.h:93
openvdb::v10_0::points::point_move_internal::GlobalPointIndexMap
std::vector< IndexTripleArray > GlobalPointIndexMap
Definition PointMove.h:165
openvdb::v10_0::points::point_move_internal::IndexPairArray
std::vector< IndexPair > IndexPairArray
Definition PointMove.h:169
openvdb::v10_0::points::point_move_internal::LeafMap
std::unordered_map< Coord, LeafIndex > LeafMap
Definition PointMove.h:174
openvdb::v10_0::points::point_move_internal::LocalPointIndexMap
std::vector< IndexPairArray > LocalPointIndexMap
Definition PointMove.h:170
openvdb::v10_0::points::point_move_internal::LeafIndexArray
std::vector< LeafIndex > LeafIndexArray
Definition PointMove.h:172
openvdb::v10_0::points::point_move_internal::LeafOffsetArray
std::vector< LeafIndexArray > LeafOffsetArray
Definition PointMove.h:173
openvdb::v10_0::points::point_move_internal::GlobalPointIndexIndices
std::vector< IndexArray > GlobalPointIndexIndices
Definition PointMove.h:166
openvdb::v10_0::points::point_move_internal::IndexTripleArray
tbb::concurrent_vector< IndexTriple > IndexTripleArray
Definition PointMove.h:164
openvdb::v10_0::points::point_move_internal::indexOffsetFromVoxel
Index indexOffsetFromVoxel(const Index voxelOffset, const LeafT &leaf, IndexArray &offsets)
Definition PointMove.h:272
openvdb::v10_0::points::point_move_internal::IndexArray
std::vector< Index > IndexArray
Definition PointMove.h:161
openvdb::v10_0::points::point_move_internal::IndexPair
std::pair< Index, Index > IndexPair
Definition PointMove.h:168
openvdb::v10_0::points::point_move_internal::IndexTriple
std::tuple< LeafIndex, Index, Index > IndexTriple
Definition PointMove.h:163
openvdb::v10_0::points
Definition AttributeArray.h:41
openvdb::v10_0::points::movePoints
void movePoints(PointDataGridT &points, DeformerT &deformer, const FilterT &filter=NullFilter(), future::Advect *objectNotInUse=nullptr, bool threaded=true)
Move points in a PointDataGrid using a custom deformer.
Definition PointMove.h:692
openvdb::v10_0::tree
Definition PointDataGrid.h:169
openvdb::v10_0::Index
Index32 Index
Definition Types.h:54
openvdb::v10_0::Index32
uint32_t Index32
Definition Types.h:52
openvdb::v10_0::Index64
uint64_t Index64
Definition Types.h:53
openvdb
Definition Exceptions.h:13
openvdb.h
openvdb::v10_0::points::CachedDeformer::Cache::Leaf
Definition PointMove.h:110
openvdb::v10_0::points::CachedDeformer::Cache::Leaf::mapData
LeafMapT mapData
Definition PointMove.h:119
openvdb::v10_0::points::CachedDeformer::Cache::Leaf::vecData
LeafVecT vecData
Definition PointMove.h:118
openvdb::v10_0::points::CachedDeformer::Cache::Leaf::totalSize
Index totalSize
Definition PointMove.h:120
openvdb::v10_0::points::CachedDeformer::Cache::Leaf::clear
void clear()
clear data buffers and reset counter
Definition PointMove.h:112
openvdb::v10_0::points::CachedDeformer::Cache
Definition PointMove.h:108
openvdb::v10_0::points::CachedDeformer::Cache::leafs
std::vector< Leaf > leafs
Definition PointMove.h:123
openvdb::v10_0::points::DeformerTraits::IndexSpace
static const bool IndexSpace
Definition PointMask.h:88
openvdb::v10_0::points::future::Advect
Definition PointMove.h:59
openvdb::v10_0::points::point_move_internal::BuildMoveMapsOp::LeafArrayT
std::vector< LeafT * > LeafArrayT
Definition PointMove.h:181
openvdb::v10_0::points::point_move_internal::BuildMoveMapsOp::operator()
void operator()(LeafT &leaf, size_t idx) const
Definition PointMove.h:199
openvdb::v10_0::points::point_move_internal::BuildMoveMapsOp::LeafManagerT
typename tree::LeafManager< TreeT > LeafManagerT
Definition PointMove.h:182
openvdb::v10_0::points::point_move_internal::BuildMoveMapsOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition PointMove.h:180
openvdb::v10_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::v10_0::points::point_move_internal::GlobalMovePointsOp::CopyIterator
Definition PointMove.h:308
openvdb::v10_0::points::point_move_internal::GlobalMovePointsOp::CopyIterator::reset
void reset(Index startIndex, Index endIndex)
Definition PointMove.h:318
openvdb::v10_0::points::point_move_internal::GlobalMovePointsOp::CopyIterator::targetIndex
Index targetIndex() const
Definition PointMove.h:345
openvdb::v10_0::points::point_move_internal::GlobalMovePointsOp::CopyIterator::leafIndex
Index leafIndex(Index i) const
Definition PointMove.h:331
openvdb::v10_0::points::point_move_internal::GlobalMovePointsOp::CopyIterator::operator++
CopyIterator & operator++()
Definition PointMove.h:325
openvdb::v10_0::points::point_move_internal::GlobalMovePointsOp::CopyIterator::CopyIterator
CopyIterator(const LeafT &leaf, const IndexArray &sortedIndices, const IndexTripleArray &moveIndices, IndexArray &offsets)
Definition PointMove.h:309
openvdb::v10_0::points::point_move_internal::GlobalMovePointsOp::CopyIterator::sourceIndex
Index sourceIndex() const
Definition PointMove.h:339
openvdb::v10_0::points::point_move_internal::GlobalMovePointsOp::LeafArrayT
std::vector< LeafT * > LeafArrayT
Definition PointMove.h:290
openvdb::v10_0::points::point_move_internal::GlobalMovePointsOp::operator()
void operator()(LeafT &leaf, size_t idx) const
Definition PointMove.h:378
openvdb::v10_0::points::point_move_internal::GlobalMovePointsOp::AttributeArrays
std::vector< AttributeArray * > AttributeArrays
Definition PointMove.h:292
openvdb::v10_0::points::point_move_internal::GlobalMovePointsOp::LeafManagerT
typename tree::LeafManager< TreeT > LeafManagerT
Definition PointMove.h:291
openvdb::v10_0::points::point_move_internal::GlobalMovePointsOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition PointMove.h:289
openvdb::v10_0::points::point_move_internal::GlobalMovePointsOp::GlobalMovePointsOp
GlobalMovePointsOp(LeafOffsetArray &offsetMap, LeafManagerT &sourceLeafManager, const Index attributeIndex, const GlobalPointIndexMap &moveLeafMap, const GlobalPointIndexIndices &moveLeafIndices)
Definition PointMove.h:294
openvdb::v10_0::points::point_move_internal::LocalMovePointsOp::CopyIterator
Definition PointMove.h:457
openvdb::v10_0::points::point_move_internal::LocalMovePointsOp::CopyIterator::targetIndex
Index targetIndex() const
Definition PointMove.h:472
openvdb::v10_0::points::point_move_internal::LocalMovePointsOp::CopyIterator::operator++
CopyIterator & operator++()
Definition PointMove.h:465
openvdb::v10_0::points::point_move_internal::LocalMovePointsOp::CopyIterator::CopyIterator
CopyIterator(const LeafT &leaf, const IndexPairArray &indices, IndexArray &offsets)
Definition PointMove.h:458
openvdb::v10_0::points::point_move_internal::LocalMovePointsOp::CopyIterator::sourceIndex
Index sourceIndex() const
Definition PointMove.h:467
openvdb::v10_0::points::point_move_internal::LocalMovePointsOp::LeafArrayT
std::vector< LeafT * > LeafArrayT
Definition PointMove.h:439
openvdb::v10_0::points::point_move_internal::LocalMovePointsOp::operator()
void operator()(LeafT &leaf, size_t idx) const
Definition PointMove.h:484
openvdb::v10_0::points::point_move_internal::LocalMovePointsOp::LocalMovePointsOp
LocalMovePointsOp(LeafOffsetArray &offsetMap, const LeafIndexArray &sourceIndices, LeafManagerT &sourceLeafManager, const Index attributeIndex, const LocalPointIndexMap &moveLeafMap)
Definition PointMove.h:443
openvdb::v10_0::points::point_move_internal::LocalMovePointsOp::AttributeArrays
std::vector< AttributeArray * > AttributeArrays
Definition PointMove.h:441
openvdb::v10_0::points::point_move_internal::LocalMovePointsOp::LeafManagerT
typename tree::LeafManager< TreeT > LeafManagerT
Definition PointMove.h:440
openvdb::v10_0::points::point_move_internal::LocalMovePointsOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition PointMove.h:438
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:212