The TransformTransfer module should be used if the source transform of the input points and the target transforms of the destination volumes differ. The default rasterizer will skip index to world (and vice versa) transformations unless a transfer scheme derives from a TransformTransfer.
- A transfer scheme must be configured to call the provided rasterize
- methods. See below for an example, or the various native VDB files which implement schemes e.g.:
- PointRasterizeSDF.h
- PointRasterizeTrilinear.h
- PrincipalComponentAnalysisImpl.h
struct Transfer
{
inline auto& topology();
inline Int32 range(
const Coord& origin,
size_t idx)
const;
inline void initialize(
const Coord& origin,
size_t idx,
const CoordBBox& bounds);
void rasterizePoint(const Coord& ijk,
const Index id,
const CoordBBox& bounds);
void rasterizePoints(const Coord& ijk,
const Index start,
const Index end,
const CoordBBox& bounds);
inline bool finalize(const Coord& origin, size_t idx);
};
Below is a full example using the native components.
struct MyTransfer :
public VolumeTransfer<FloatTree>
{
, VolumeTransfer(dest.tree()) {}
MyTransfer(const MyTransfer& other)
, VolumeTransfer(other) {}
Vec3i range(
const Coord&,
size_t)
const {
return Vec3i(1); }
{
mHandle = std::make_unique<AttributeHandle<Vec3f>>(leaf.constAttributeArray("P"));
mFilter = std::make_unique<GroupFilter>("mygroup", leaf.attributeSet());
return true;
}
void rasterizePoint(const Coord& ijk, const Index id, const CoordBBox& bounds)
{
if (!mFilter->valid(&id)) return;
Vec3d P = ijk.asVec3d() +
Vec3d(this->mHandle->get(
id));
const auto* mask = this->mask();
for (auto& coord : bounds) {
const Index voxel = FloatTree::LeafNodeType::coordToOffset(coord);
if (!mask->isOn(voxel)) continue;
Vec3d dist = coord.asVec3d() - P;
this->buffer()[voxel] += dist.
length();
}
}
bool finalize(const Coord&, size_t) { return false; }
private:
std::unique_ptr<AttributeHandle<Vec3f>> mHandle {nullptr};
std::unique_ptr<GroupFilter> mFilter {nullptr};
};