9 #ifndef OPENVDB_POINTS_RASTERIZE_TRILINEAR_IMPL_HAS_BEEN_INCLUDED 10 #define OPENVDB_POINTS_RASTERIZE_TRILINEAR_IMPL_HAS_BEEN_INCLUDED 19 namespace rasterize_trilinear_internal {
21 template <
typename TreeType,
22 typename PositionCodecT,
23 typename SourceValueT,
24 typename SourceCodecT>
25 struct TrilinearTransfer :
public VolumeTransfer<TreeType>
27 using BaseT = VolumeTransfer<TreeType>;
28 using WeightT =
typename TreeType::ValueType;
29 using PositionHandleT = points::AttributeHandle<Vec3f, PositionCodecT>;
30 using SourceHandleT = points::AttributeHandle<SourceValueT, SourceCodecT>;
35 using RealT = SourceElementT;
37 static_assert(std::is_floating_point<SourceElementT>::value,
38 "Trilinear rasterization only supports floating point values.");
40 static const Index NUM_VALUES = TreeType::LeafNodeType::NUM_VALUES;
42 TrilinearTransfer(
const size_t pidx,
43 const size_t sidx, TreeType& tree)
51 TrilinearTransfer(
const TrilinearTransfer& other)
60 static inline RealT value(
const RealT x)
62 const RealT abs_x = std::fabs(x);
63 if (abs_x < RealT(1.0))
return RealT(1.0) - abs_x;
67 inline static Int32 range() {
return 1; }
68 inline Int32 range(
const Coord&,
size_t)
const {
return this->range(); }
70 inline void initialize(
const Coord& origin,
const size_t idx,
const CoordBBox& bounds)
73 mWeights.fill(openvdb::zeroVal<WeightT>());
76 inline bool startPointLeaf(
const PointDataTree::LeafNodeType& leaf)
78 mPHandle.reset(
new PositionHandleT(leaf.constAttributeArray(mPIdx)));
79 mSHandle.reset(
new SourceHandleT(leaf.constAttributeArray(mSIdx)));
83 inline bool endPointLeaf(
const PointDataTree::LeafNodeType&) {
return true; }
88 typename PositionHandleT::UniquePtr mPHandle;
89 typename SourceHandleT::UniquePtr mSHandle;
90 std::array<WeightT, NUM_VALUES> mWeights;
93 template <
typename TreeType,
94 typename PositionCodecT,
95 typename SourceValueT,
96 typename SourceCodecT>
97 struct StaggeredTransfer :
98 public TrilinearTransfer<TreeType, PositionCodecT, SourceValueT, SourceCodecT>
100 using BaseT = TrilinearTransfer<TreeType, PositionCodecT, SourceValueT, SourceCodecT>;
101 using RealT =
typename BaseT::RealT;
105 "Target Tree must be a vector tree for staggered rasterization");
107 static const Index DIM = TreeType::LeafNodeType::DIM;
108 static const Index LOG2DIM = TreeType::LeafNodeType::LOG2DIM;
110 StaggeredTransfer(
const size_t pidx,
111 const size_t sidx, TreeType& tree)
112 : BaseT(pidx, sidx, tree) {}
114 void rasterizePoint(
const Coord& ijk,
116 const CoordBBox& bounds)
118 CoordBBox intersectBox(ijk.offsetBy(-1), ijk.offsetBy(1));
119 intersectBox.intersect(bounds);
120 if (intersectBox.empty())
return;
122 auto*
const data = this->buffer();
123 const auto& mask = *(this->mask());
125 const math::Vec3<RealT> P(this->mPHandle->get(
id));
126 const SourceValueT s(this->mSHandle->get(
id));
128 math::Vec3<RealT> centerw, macw;
130 const Coord& a(intersectBox.min());
131 const Coord& b(intersectBox.max());
132 for (Coord c = a; c.x() <= b.x(); ++c.x()) {
134 const Index i = ((c.x() & (DIM-1u)) << 2*LOG2DIM);
135 const RealT x =
static_cast<RealT
>(c.x()-ijk.x());
136 centerw[0] = value(P.x() - x);
137 macw.x() = value(P.x() - (x-RealT(0.5)));
139 for (c.y() = a.y(); c.y() <= b.y(); ++c.y()) {
140 const Index ij = i + ((c.y() & (DIM-1u)) << LOG2DIM);
141 const RealT y =
static_cast<RealT
>(c.y()-ijk.y());
142 centerw[1] = value(P.y() - y);
143 macw.y() = value(P.y() - (y-RealT(0.5)));
145 for (c.z() = a.z(); c.z() <= b.z(); ++c.z()) {
147 const Index offset = ij + (c.z() & (DIM-1u));
148 if (!mask.isOn(offset))
continue;
149 const RealT z =
static_cast<RealT
>(c.z()-ijk.z());
150 centerw[2] = value(P.z() - z);
151 macw.z() = value(P.z() - (z-RealT(0.5)));
153 const math::Vec3<RealT> r {
154 (macw[0] * centerw[1] * centerw[2]),
155 (macw[1] * centerw[0] * centerw[2]),
156 (macw[2] * centerw[0] * centerw[1])
159 data[offset] += s * r;
160 this->mWeights[offset] += r;
166 inline bool finalize(
const Coord&,
const size_t)
168 auto*
const data = this->buffer();
169 const auto& mask = *(this->mask());
171 for (
auto iter = mask.beginOn(); iter; ++iter) {
172 const Index offset = iter.pos();
173 const auto& w = this->mWeights[offset];
174 auto& v = data[offset];
184 template <
typename TreeType,
185 typename PositionCodecT,
186 typename SourceValueT,
187 typename SourceCodecT>
188 struct CellCenteredTransfer :
189 public TrilinearTransfer<TreeType, PositionCodecT, SourceValueT, SourceCodecT>
191 using BaseT = TrilinearTransfer<TreeType, PositionCodecT, SourceValueT, SourceCodecT>;
192 using RealT =
typename BaseT::RealT;
195 static const Index DIM = TreeType::LeafNodeType::DIM;
196 static const Index LOG2DIM = TreeType::LeafNodeType::LOG2DIM;
198 CellCenteredTransfer(
const size_t pidx,
199 const size_t sidx, TreeType& tree)
200 : BaseT(pidx, sidx, tree) {}
202 void rasterizePoint(
const Coord& ijk,
204 const CoordBBox& bounds)
206 const Vec3f P(this->mPHandle->get(
id));
209 CoordBBox intersectBox(ijk, ijk);
210 if (P.x() < 0.0f) intersectBox.min().x() -= 1;
211 else intersectBox.max().x() += 1;
212 if (P.y() < 0.0f) intersectBox.min().y() -= 1;
213 else intersectBox.max().y() += 1;
214 if (P.z() < 0.0f) intersectBox.min().z() -= 1;
215 else intersectBox.max().z() += 1;
218 intersectBox.intersect(bounds);
219 if (intersectBox.empty())
return;
221 auto*
const data = this->buffer();
222 const auto& mask = *(this->mask());
224 const SourceValueT s(this->mSHandle->get(
id));
225 math::Vec3<RealT> centerw;
227 const Coord& a(intersectBox.min());
228 const Coord& b(intersectBox.max());
229 for (Coord c = a; c.x() <= b.x(); ++c.x()) {
230 const Index i = ((c.x() & (DIM-1u)) << 2*LOG2DIM);
231 const RealT x =
static_cast<RealT
>(c.x()-ijk.x());
232 centerw[0] = value(P.x() - x);
234 for (c.y() = a.y(); c.y() <= b.y(); ++c.y()) {
235 const Index ij = i + ((c.y() & (DIM-1u)) << LOG2DIM);
236 const RealT y =
static_cast<RealT
>(c.y()-ijk.y());
237 centerw[1] = value(P.y() - y);
239 for (c.z() = a.z(); c.z() <= b.z(); ++c.z()) {
241 const Index offset = ij + (c.z() & (DIM-1u));
242 if (!mask.isOn(offset))
continue;
243 const RealT z =
static_cast<RealT
>(c.z()-ijk.z());
244 centerw[2] = value(P.z() - z);
250 const RealT weight = centerw.product();
251 data[offset] += s * weight;
252 this->mWeights[offset] += weight;
258 inline bool finalize(
const Coord&,
const size_t)
260 auto*
const data = this->buffer();
261 const auto& mask = *(this->mask());
263 for (
auto iter = mask.beginOn(); iter; ++iter) {
264 const Index offset = iter.pos();
265 const auto& w = this->mWeights[offset];
266 auto& v = data[offset];
280 typename PositionCodecT,
282 typename PointDataTreeT>
285 typename TrilinearTraits<ValueT, Staggered>::template TreeT<PointDataTreeT>::Ptr
292 const FilterT& filter)
294 using TraitsT = TrilinearTraits<ValueT, Staggered>;
295 using TargetTreeT =
typename TraitsT::template TreeT<PointDataTree>;
296 using TransferT =
typename std::conditional<Staggered,
297 StaggeredTransfer<TargetTreeT, PositionCodecT, ValueT, CodecT>,
298 CellCenteredTransfer<TargetTreeT, PositionCodecT, ValueT, CodecT>
301 typename TargetTreeT::Ptr tree(
new TargetTreeT);
302 if (std::is_same<FilterT, NullFilter>::value) {
303 tree->topologyUnion(points);
306 using MaskTreeT =
typename PointDataTreeT::template ValueConverter<ValueMask>::Type;
307 auto mask = convertPointsToMask<PointDataTreeT, MaskTreeT>(points, filter);
308 tree->topologyUnion(*mask);
311 TransferT transfer(pidx, sidx, *tree);
315 rasterize<PointDataTreeT, TransferT>(points, transfer, filter);
325 template <
bool Staggered,
328 typename PointDataTreeT>
331 const std::string& attribute,
332 const FilterT& filter)
335 using TargetTreeT =
typename TraitsT::template TreeT<PointDataTree>;
337 const auto iter = points.cbeginLeaf();
338 if (!iter)
return typename TargetTreeT::Ptr(
new TargetTreeT);
340 const AttributeSet::Descriptor& descriptor = iter->attributeSet().descriptor();
341 const size_t pidx = descriptor.find(
"P");
342 const size_t sidx = descriptor.find(attribute);
343 if (pidx == AttributeSet::INVALID_POS) {
346 if (sidx == AttributeSet::INVALID_POS) {
350 const NamePair& ptype = descriptor.type(pidx);
351 const NamePair& stype = descriptor.type(sidx);
352 if (ptype.second == NullCodec::name()) {
353 if (stype.second == NullCodec::name()) {
355 <Staggered, ValueT,
NullCodec, NullCodec>
356 (points, pidx, sidx, filter);
361 (points, pidx, sidx, filter);
365 if (stype.second == NullCodec::name()) {
368 (points, pidx, sidx, filter);
373 (points, pidx, sidx, filter);
383 #endif //OPENVDB_POINTS_RASTERIZE_TRILINEAR_IMPL_HAS_BEEN_INCLUDED static const bool IsVec
Definition: Types.h:245
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
Definition: PointRasterizeTrilinear.h:36
int32_t Int32
Definition: Types.h:56
Index32 Index
Definition: Types.h:54
OPENVDB_IMPORT void initialize()
Global registration of native Grid, Transform, Metadata and Point attribute types. Also initializes blosc (if enabled).
bool isZero(const Type &x)
Return true if x is exactly equal to zero.
Definition: Math.h:337
#define OPENVDB_ASSERT(X)
Definition: Assert.h:41
Definition: Exceptions.h:13
math::Vec3< float > Vec3f
Definition: Types.h:74
std::pair< Name, Name > NamePair
Definition: AttributeArray.h:40
Definition: AttributeArray.h:433
Definition: AttributeArray.h:436
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:121
auto rasterizeTrilinear(const PointDataTreeT &points, const std::string &attribute, const FilterT &filter=NullFilter())
Perform weighted trilinear rasterization of all points within a voxel. This method takes and returns ...
Definition: PointRasterizeTrilinearImpl.h:330
typename T::ValueType ElementType
Definition: Types.h:302
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:218
Definition: Exceptions.h:63