Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0 | ||
3 | // | ||
4 | /// @author Nick Avramoussis | ||
5 | /// | ||
6 | /// @file PointRasterizeTrilinearImpl.h | ||
7 | /// | ||
8 | |||
9 | #ifndef OPENVDB_POINTS_RASTERIZE_TRILINEAR_IMPL_HAS_BEEN_INCLUDED | ||
10 | #define OPENVDB_POINTS_RASTERIZE_TRILINEAR_IMPL_HAS_BEEN_INCLUDED | ||
11 | |||
12 | namespace openvdb { | ||
13 | OPENVDB_USE_VERSION_NAMESPACE | ||
14 | namespace OPENVDB_VERSION_NAME { | ||
15 | namespace points { | ||
16 | |||
17 | /// @cond OPENVDB_DOCS_INTERNAL | ||
18 | |||
19 | namespace rasterize_trilinear_internal { | ||
20 | |||
21 | template <typename TreeType, | ||
22 | typename PositionCodecT, | ||
23 | typename SourceValueT, | ||
24 | typename SourceCodecT> | ||
25 | struct TrilinearTransfer : public VolumeTransfer<TreeType> | ||
26 | { | ||
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>; | ||
31 | |||
32 | // precision of kernel arithmetic - aliased to the floating point | ||
33 | // element type of the source attribute. | ||
34 | using SourceElementT = typename ValueTraits<SourceValueT>::ElementType; | ||
35 | using RealT = SourceElementT; | ||
36 | |||
37 | static_assert(std::is_floating_point<SourceElementT>::value, | ||
38 | "Trilinear rasterization only supports floating point values."); | ||
39 | |||
40 | static const Index NUM_VALUES = TreeType::LeafNodeType::NUM_VALUES; | ||
41 | |||
42 |
8/64✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✓ Branch 70 taken 1 times.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✓ Branch 82 taken 1 times.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✓ Branch 94 taken 1 times.
✗ Branch 95 not taken.
|
8 | TrilinearTransfer(const size_t pidx, |
43 | const size_t sidx, TreeType& tree) | ||
44 | : BaseT(tree) | ||
45 | , mPIdx(pidx) | ||
46 | , mSIdx(sidx) | ||
47 | , mPHandle() | ||
48 | , mSHandle() | ||
49 |
8/64✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✓ Branch 70 taken 1 times.
✗ Branch 71 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✓ Branch 82 taken 1 times.
✗ Branch 83 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✓ Branch 94 taken 1 times.
✗ Branch 95 not taken.
|
8 | , mWeights() {} |
50 | |||
51 | 8 | TrilinearTransfer(const TrilinearTransfer& other) | |
52 | : BaseT(other) | ||
53 | 8 | , mPIdx(other.mPIdx) | |
54 | 8 | , mSIdx(other.mSIdx) | |
55 | , mPHandle() | ||
56 | , mSHandle() | ||
57 | 8 | , mWeights() {} | |
58 | |||
59 | //// @note Kernel value evaluator | ||
60 | static inline RealT value(const RealT x) | ||
61 | { | ||
62 | 256 | const RealT abs_x = std::fabs(x); | |
63 |
36/144✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✓ Branch 36 taken 4 times.
✓ Branch 37 taken 8 times.
✓ Branch 38 taken 8 times.
✓ Branch 39 taken 4 times.
✓ Branch 40 taken 6 times.
✓ Branch 41 taken 12 times.
✓ Branch 42 taken 12 times.
✓ Branch 43 taken 6 times.
✓ Branch 44 taken 9 times.
✓ Branch 45 taken 18 times.
✓ Branch 46 taken 18 times.
✓ Branch 47 taken 9 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✓ Branch 66 taken 1 times.
✓ Branch 67 taken 1 times.
✓ Branch 68 taken 2 times.
✓ Branch 69 taken 2 times.
✓ Branch 70 taken 4 times.
✓ Branch 71 taken 4 times.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✓ Branch 108 taken 4 times.
✓ Branch 109 taken 8 times.
✓ Branch 110 taken 8 times.
✓ Branch 111 taken 4 times.
✓ Branch 112 taken 6 times.
✓ Branch 113 taken 12 times.
✓ Branch 114 taken 12 times.
✓ Branch 115 taken 6 times.
✓ Branch 116 taken 9 times.
✓ Branch 117 taken 18 times.
✓ Branch 118 taken 18 times.
✓ Branch 119 taken 9 times.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✓ Branch 138 taken 1 times.
✓ Branch 139 taken 1 times.
✓ Branch 140 taken 2 times.
✓ Branch 141 taken 2 times.
✓ Branch 142 taken 4 times.
✓ Branch 143 taken 4 times.
|
270 | if (abs_x < RealT(1.0)) return RealT(1.0) - abs_x; |
64 | return RealT(0.0); | ||
65 | } | ||
66 | |||
67 | inline static Int32 range() { return 1; } | ||
68 | inline Int32 range(const Coord&, size_t) const { return this->range(); } | ||
69 | |||
70 | 96 | inline void initialize(const Coord& origin, const size_t idx, const CoordBBox& bounds) | |
71 | { | ||
72 | 112 | this->BaseT::initialize(origin, idx, bounds); | |
73 | 96 | mWeights.fill(openvdb::zeroVal<WeightT>()); | |
74 | } | ||
75 | |||
76 | 128 | inline bool startPointLeaf(const PointDataTree::LeafNodeType& leaf) | |
77 | { | ||
78 |
1/2✓ Branch 3 taken 64 times.
✗ Branch 4 not taken.
|
128 | mPHandle.reset(new PositionHandleT(leaf.constAttributeArray(mPIdx))); |
79 |
1/2✓ Branch 3 taken 64 times.
✗ Branch 4 not taken.
|
128 | mSHandle.reset(new SourceHandleT(leaf.constAttributeArray(mSIdx))); |
80 | 128 | return true; | |
81 | } | ||
82 | |||
83 | inline bool endPointLeaf(const PointDataTree::LeafNodeType&) { return true; } | ||
84 | |||
85 | protected: | ||
86 | const size_t mPIdx; | ||
87 | const size_t mSIdx; | ||
88 | typename PositionHandleT::UniquePtr mPHandle; | ||
89 | typename SourceHandleT::UniquePtr mSHandle; | ||
90 | std::array<WeightT, NUM_VALUES> mWeights; | ||
91 | }; | ||
92 | |||
93 | template <typename TreeType, | ||
94 | typename PositionCodecT, | ||
95 | typename SourceValueT, | ||
96 | typename SourceCodecT> | ||
97 | 4 | struct StaggeredTransfer : | |
98 | public TrilinearTransfer<TreeType, PositionCodecT, SourceValueT, SourceCodecT> | ||
99 | { | ||
100 | using BaseT = TrilinearTransfer<TreeType, PositionCodecT, SourceValueT, SourceCodecT>; | ||
101 | using RealT = typename BaseT::RealT; | ||
102 | using BaseT::value; | ||
103 | |||
104 | static_assert(VecTraits<typename TreeType::ValueType>::IsVec, | ||
105 | "Target Tree must be a vector tree for staggered rasterization"); | ||
106 | |||
107 | static const Index DIM = TreeType::LeafNodeType::DIM; | ||
108 | static const Index LOG2DIM = TreeType::LeafNodeType::LOG2DIM; | ||
109 | |||
110 | StaggeredTransfer(const size_t pidx, | ||
111 | const size_t sidx, TreeType& tree) | ||
112 | : BaseT(pidx, sidx, tree) {} | ||
113 | |||
114 | 64 | void rasterizePoint(const Coord& ijk, | |
115 | const Index id, | ||
116 | const CoordBBox& bounds) | ||
117 | { | ||
118 | 64 | CoordBBox intersectBox(ijk.offsetBy(-1), ijk.offsetBy(1)); | |
119 | 64 | intersectBox.intersect(bounds); | |
120 | ✗ | if (intersectBox.empty()) return; | |
121 | |||
122 | auto* const data = this->buffer(); | ||
123 | const auto& mask = *(this->mask()); | ||
124 | |||
125 | 64 | const math::Vec3<RealT> P(this->mPHandle->get(id)); | |
126 | 64 | const SourceValueT s(this->mSHandle->get(id)); | |
127 | |||
128 | math::Vec3<RealT> centerw, macw; | ||
129 | |||
130 | const Coord& a(intersectBox.min()); | ||
131 | const Coord& b(intersectBox.max()); | ||
132 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 32 times.
|
160 | for (Coord c = a; c.x() <= b.x(); ++c.x()) { |
133 | // @todo can probably simplify the double call to value() in some way | ||
134 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 32 times.
|
96 | const Index i = ((c.x() & (DIM-1u)) << 2*LOG2DIM); // unsigned bit shift mult |
135 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 16 times.
|
96 | const RealT x = static_cast<RealT>(c.x()-ijk.x()); // distance from ijk to c |
136 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 32 times.
|
96 | centerw[0] = value(P.x() - x); // center dist |
137 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
|
96 | macw.x() = value(P.x() - (x-RealT(0.5))); // mac dist |
138 | |||
139 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 48 times.
|
240 | for (c.y() = a.y(); c.y() <= b.y(); ++c.y()) { |
140 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 48 times.
|
144 | const Index ij = i + ((c.y() & (DIM-1u)) << LOG2DIM); |
141 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 24 times.
|
144 | const RealT y = static_cast<RealT>(c.y()-ijk.y()); |
142 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 48 times.
|
144 | centerw[1] = value(P.y() - y); |
143 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 24 times.
|
144 | macw.y() = value(P.y() - (y-RealT(0.5))); |
144 | |||
145 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 72 times.
|
360 | for (c.z() = a.z(); c.z() <= b.z(); ++c.z()) { |
146 | ✗ | assert(bounds.isInside(c)); | |
147 | 216 | const Index offset = ij + /*k*/(c.z() & (DIM-1u)); | |
148 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
|
216 | if (!mask.isOn(offset)) continue; |
149 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 36 times.
|
216 | const RealT z = static_cast<RealT>(c.z()-ijk.z()); |
150 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 72 times.
|
216 | centerw[2] = value(P.z() - z); |
151 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 36 times.
|
216 | macw.z() = value(P.z() - (z-RealT(0.5))); |
152 | |||
153 | 216 | const math::Vec3<RealT> r { | |
154 | 216 | (macw[0] * centerw[1] * centerw[2]), | |
155 | 216 | (macw[1] * centerw[0] * centerw[2]), | |
156 | 216 | (macw[2] * centerw[0] * centerw[1]) | |
157 | }; | ||
158 | |||
159 | 216 | data[offset] += s * r; | |
160 | this->mWeights[offset] += r; | ||
161 | } | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | |||
166 | 64 | inline bool finalize(const Coord&, const size_t) | |
167 | { | ||
168 | auto* const data = this->buffer(); | ||
169 | const auto& mask = *(this->mask()); | ||
170 | |||
171 |
2/2✓ Branch 1 taken 108 times.
✓ Branch 2 taken 32 times.
|
344 | for (auto iter = mask.beginOn(); iter; ++iter) { |
172 | const Index offset = iter.pos(); | ||
173 | 216 | const auto& w = this->mWeights[offset]; | |
174 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 100 times.
|
216 | auto& v = data[offset]; |
175 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 100 times.
|
216 | if (!math::isZero(w[0])) v[0] /= w[0]; |
176 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 100 times.
|
216 | if (!math::isZero(w[1])) v[1] /= w[1]; |
177 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 100 times.
|
216 | if (!math::isZero(w[2])) v[2] /= w[2]; |
178 | } | ||
179 | |||
180 | 64 | return true; | |
181 | } | ||
182 | }; | ||
183 | |||
184 | template <typename TreeType, | ||
185 | typename PositionCodecT, | ||
186 | typename SourceValueT, | ||
187 | typename SourceCodecT> | ||
188 | 4 | struct CellCenteredTransfer : | |
189 | public TrilinearTransfer<TreeType, PositionCodecT, SourceValueT, SourceCodecT> | ||
190 | { | ||
191 | using BaseT = TrilinearTransfer<TreeType, PositionCodecT, SourceValueT, SourceCodecT>; | ||
192 | using RealT = typename BaseT::RealT; | ||
193 | using BaseT::value; | ||
194 | |||
195 | static const Index DIM = TreeType::LeafNodeType::DIM; | ||
196 | static const Index LOG2DIM = TreeType::LeafNodeType::LOG2DIM; | ||
197 | |||
198 | CellCenteredTransfer(const size_t pidx, | ||
199 | const size_t sidx, TreeType& tree) | ||
200 | : BaseT(pidx, sidx, tree) {} | ||
201 | |||
202 | 64 | void rasterizePoint(const Coord& ijk, | |
203 | const Index id, | ||
204 | const CoordBBox& bounds) | ||
205 | { | ||
206 | 64 | const Vec3f P(this->mPHandle->get(id)); | |
207 | |||
208 | // build area of influence depending on point position | ||
209 | CoordBBox intersectBox(ijk, ijk); | ||
210 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
64 | if (P.x() < 0.0f) intersectBox.min().x() -= 1; |
211 | 64 | else intersectBox.max().x() += 1; | |
212 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
64 | if (P.y() < 0.0f) intersectBox.min().y() -= 1; |
213 | 64 | else intersectBox.max().y() += 1; | |
214 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
64 | if (P.z() < 0.0f) intersectBox.min().z() -= 1; |
215 | 64 | else intersectBox.max().z() += 1; | |
216 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
|
64 | assert(intersectBox.volume() == 8); |
217 | |||
218 | 64 | intersectBox.intersect(bounds); | |
219 | 56 | if (intersectBox.empty()) return; | |
220 | |||
221 | auto* const data = this->buffer(); | ||
222 | const auto& mask = *(this->mask()); | ||
223 | |||
224 | 8 | const SourceValueT s(this->mSHandle->get(id)); | |
225 | math::Vec3<RealT> centerw; | ||
226 | |||
227 | const Coord& a(intersectBox.min()); | ||
228 | const Coord& b(intersectBox.max()); | ||
229 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
|
24 | for (Coord c = a; c.x() <= b.x(); ++c.x()) { |
230 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
16 | const Index i = ((c.x() & (DIM-1u)) << 2*LOG2DIM); // unsigned bit shift mult |
231 | 16 | const RealT x = static_cast<RealT>(c.x()-ijk.x()); // distance from ijk to c | |
232 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
16 | centerw[0] = value(P.x() - x); // center dist |
233 | |||
234 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
|
48 | for (c.y() = a.y(); c.y() <= b.y(); ++c.y()) { |
235 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
|
32 | const Index ij = i + ((c.y() & (DIM-1u)) << LOG2DIM); |
236 | 32 | const RealT y = static_cast<RealT>(c.y()-ijk.y()); | |
237 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
|
32 | centerw[1] = value(P.y() - y); |
238 | |||
239 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 16 times.
|
96 | for (c.z() = a.z(); c.z() <= b.z(); ++c.z()) { |
240 | ✗ | assert(bounds.isInside(c)); | |
241 | 64 | const Index offset = ij + /*k*/(c.z() & (DIM-1u)); | |
242 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
|
64 | if (!mask.isOn(offset)) continue; |
243 | 64 | const RealT z = static_cast<RealT>(c.z()-ijk.z()); | |
244 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
|
64 | centerw[2] = value(P.z() - z); |
245 | |||
246 |
2/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
|
64 | assert(centerw[0] >= 0.0f && centerw[0] <= 1.0f); |
247 |
2/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
|
64 | assert(centerw[1] >= 0.0f && centerw[1] <= 1.0f); |
248 |
2/4✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
|
64 | assert(centerw[2] >= 0.0f && centerw[2] <= 1.0f); |
249 | |||
250 | const RealT weight = centerw.product(); | ||
251 | 64 | data[offset] += s * weight; | |
252 | 32 | this->mWeights[offset] += weight; | |
253 | } | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | |||
258 | 64 | inline bool finalize(const Coord&, const size_t) | |
259 | { | ||
260 | auto* const data = this->buffer(); | ||
261 | const auto& mask = *(this->mask()); | ||
262 | |||
263 |
2/2✓ Branch 1 taken 108 times.
✓ Branch 2 taken 32 times.
|
344 | for (auto iter = mask.beginOn(); iter; ++iter) { |
264 | const Index offset = iter.pos(); | ||
265 |
2/2✓ Branch 0 taken 52 times.
✓ Branch 1 taken 2 times.
|
216 | const auto& w = this->mWeights[offset]; |
266 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 54 times.
|
216 | auto& v = data[offset]; |
267 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 52 times.
|
108 | if (!math::isZero(w)) v /= w; |
268 | } | ||
269 | 64 | return true; | |
270 | } | ||
271 | }; | ||
272 | |||
273 | // @note If building with MSVC we have to use auto to deduce the return type | ||
274 | // due to a compiler bug. We can also use that for the public API - but | ||
275 | // we explicitly define it in non-msvc builds to ensure the API remains | ||
276 | // consistent | ||
277 | template <bool Staggered, | ||
278 | typename ValueT, | ||
279 | typename CodecT, | ||
280 | typename PositionCodecT, | ||
281 | typename FilterT, | ||
282 | typename PointDataTreeT> | ||
283 | inline | ||
284 | #ifndef _MSC_VER | ||
285 | typename TrilinearTraits<ValueT, Staggered>::template TreeT<PointDataTreeT>::Ptr | ||
286 | #else | ||
287 | auto | ||
288 | #endif | ||
289 | 16 | rasterizeTrilinear(const PointDataTreeT& points, | |
290 | const size_t pidx, | ||
291 | const size_t sidx, | ||
292 | const FilterT& filter) | ||
293 | { | ||
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> | ||
299 | >::type; | ||
300 | |||
301 | 16 | typename TargetTreeT::Ptr tree(new TargetTreeT); | |
302 | if (std::is_same<FilterT, NullFilter>::value) { | ||
303 | tree->topologyUnion(points); | ||
304 | } | ||
305 | else { | ||
306 | using MaskTreeT = typename PointDataTreeT::template ValueConverter<ValueMask>::Type; | ||
307 | auto mask = convertPointsToMask<PointDataTreeT, MaskTreeT>(points, filter); | ||
308 | tree->topologyUnion(*mask); | ||
309 | } | ||
310 | |||
311 | TransferT transfer(pidx, sidx, *tree); | ||
312 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
16 | tools::dilateActiveValues(*tree, transfer.range(), |
313 | tools::NN_FACE_EDGE_VERTEX, tools::EXPAND_TILES); | ||
314 | |||
315 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
16 | rasterize<PointDataTreeT, TransferT>(points, transfer, filter); |
316 | 16 | return tree; | |
317 | } | ||
318 | |||
319 | } // namespace rasterize_trilinear_internal | ||
320 | |||
321 | /// @endcond | ||
322 | |||
323 | /////////////////////////////////////////////////// | ||
324 | |||
325 | template <bool Staggered, | ||
326 | typename ValueT, | ||
327 | typename FilterT, | ||
328 | typename PointDataTreeT> | ||
329 | inline auto | ||
330 | 8 | rasterizeTrilinear(const PointDataTreeT& points, | |
331 | const std::string& attribute, | ||
332 | const FilterT& filter) | ||
333 | { | ||
334 | using TraitsT = TrilinearTraits<ValueT, Staggered>; | ||
335 | using TargetTreeT = typename TraitsT::template TreeT<PointDataTree>; | ||
336 | |||
337 | const auto iter = points.cbeginLeaf(); | ||
338 | 8 | if (!iter) return typename TargetTreeT::Ptr(new TargetTreeT); | |
339 | |||
340 | const AttributeSet::Descriptor& descriptor = iter->attributeSet().descriptor(); | ||
341 | 8 | const size_t pidx = descriptor.find("P"); | |
342 | 8 | const size_t sidx = descriptor.find(attribute); | |
343 | 8 | if (pidx == AttributeSet::INVALID_POS) { | |
344 | ✗ | OPENVDB_THROW(RuntimeError, "Failed to find position attribute"); | |
345 | } | ||
346 | 8 | if (sidx == AttributeSet::INVALID_POS) { | |
347 | ✗ | OPENVDB_THROW(RuntimeError, "Failed to find source attribute"); | |
348 | } | ||
349 | |||
350 | 8 | const NamePair& ptype = descriptor.type(pidx); | |
351 | 8 | const NamePair& stype = descriptor.type(sidx); | |
352 | 8 | if (ptype.second == NullCodec::name()) { | |
353 | 8 | if (stype.second == NullCodec::name()) { | |
354 | return rasterize_trilinear_internal::rasterizeTrilinear | ||
355 | <Staggered, ValueT, NullCodec, NullCodec> | ||
356 | 8 | (points, pidx, sidx, filter); | |
357 | } | ||
358 | else { | ||
359 | return rasterize_trilinear_internal::rasterizeTrilinear | ||
360 | <Staggered, ValueT, UnknownCodec, NullCodec> | ||
361 | ✗ | (points, pidx, sidx, filter); | |
362 | } | ||
363 | } | ||
364 | else { | ||
365 | ✗ | if (stype.second == NullCodec::name()) { | |
366 | return rasterize_trilinear_internal::rasterizeTrilinear | ||
367 | <Staggered, ValueT, NullCodec, UnknownCodec> | ||
368 | ✗ | (points, pidx, sidx, filter); | |
369 | } | ||
370 | else { | ||
371 | return rasterize_trilinear_internal::rasterizeTrilinear | ||
372 | <Staggered, ValueT, UnknownCodec, UnknownCodec> | ||
373 | ✗ | (points, pidx, sidx, filter); | |
374 | } | ||
375 | } | ||
376 | } | ||
377 | |||
378 | |||
379 | } // namespace points | ||
380 | } // namespace OPENVDB_VERSION_NAME | ||
381 | } // namespace openvdb | ||
382 | |||
383 | #endif //OPENVDB_POINTS_RASTERIZE_TRILINEAR_IMPL_HAS_BEEN_INCLUDED | ||
384 |