Blender V4.3
attribute_math.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_array_utils.hh"
6#include "BLI_math_euler.hh"
7#include "BLI_math_matrix.hh"
9
10#include "BKE_attribute_math.hh"
11
13
14template<>
15math::Quaternion mix2(const float factor, const math::Quaternion &a, const math::Quaternion &b)
16{
17 return math::interpolate(a, b, factor);
18}
19
20template<>
22 const math::Quaternion &v0,
23 const math::Quaternion &v1,
24 const math::Quaternion &v2)
25{
26 const float3 expmap_mixed = mix3(weights, v0.expmap(), v1.expmap(), v2.expmap());
27 return math::Quaternion::expmap(expmap_mixed);
28}
29
30template<>
32 const math::Quaternion &v0,
33 const math::Quaternion &v1,
34 const math::Quaternion &v2,
35 const math::Quaternion &v3)
36{
37 const float3 expmap_mixed = mix4(weights, v0.expmap(), v1.expmap(), v2.expmap(), v3.expmap());
38 return math::Quaternion::expmap(expmap_mixed);
39}
40
41template<> float4x4 mix2(const float factor, const float4x4 &a, const float4x4 &b)
42{
43 return math::interpolate(a, b, factor);
44}
45
46template<>
47float4x4 mix3(const float3 &weights, const float4x4 &v0, const float4x4 &v1, const float4x4 &v2)
48{
49 const float3 location = mix3(weights, v0.location(), v1.location(), v2.location());
50 const math::Quaternion rotation = mix3(
51 weights,
55 const float3 scale = mix3(weights, math::to_scale(v0), math::to_scale(v1), math::to_scale(v2));
56 return math::from_loc_rot_scale<float4x4>(location, rotation, scale);
57}
58
59template<>
60float4x4 mix4(const float4 &weights,
61 const float4x4 &v0,
62 const float4x4 &v1,
63 const float4x4 &v2,
64 const float4x4 &v3)
65{
66 const float3 location = mix4(
67 weights, v0.location(), v1.location(), v2.location(), v3.location());
68 const math::Quaternion rotation = mix4(weights,
73 const float3 scale = mix4(
75 return math::from_loc_rot_scale<float4x4>(location, rotation, scale);
76}
77
79 ColorGeometry4f default_color)
80 : ColorGeometry4fMixer(buffer, buffer.index_range(), default_color)
81{
82}
83
85 const IndexMask &mask,
86 const ColorGeometry4f default_color)
87 : buffer_(buffer), default_color_(default_color), total_weights_(buffer.size(), 0.0f)
88{
89 const ColorGeometry4f zero{0.0f, 0.0f, 0.0f, 0.0f};
90 mask.foreach_index([&](const int64_t i) { buffer_[i] = zero; });
91}
92
94 const ColorGeometry4f &color,
95 const float weight)
96{
97 buffer_[index].r = color.r * weight;
98 buffer_[index].g = color.g * weight;
99 buffer_[index].b = color.b * weight;
100 buffer_[index].a = color.a * weight;
101 total_weights_[index] = weight;
102}
103
105 const ColorGeometry4f &color,
106 const float weight)
107{
108 ColorGeometry4f &output_color = buffer_[index];
109 output_color.r += color.r * weight;
110 output_color.g += color.g * weight;
111 output_color.b += color.b * weight;
112 output_color.a += color.a * weight;
113 total_weights_[index] += weight;
114}
115
117{
118 this->finalize(buffer_.index_range());
119}
120
122{
123 mask.foreach_index([&](const int64_t i) {
124 const float weight = total_weights_[i];
125 ColorGeometry4f &output_color = buffer_[i];
126 if (weight > 0.0f) {
127 const float weight_inv = 1.0f / weight;
128 output_color.r *= weight_inv;
129 output_color.g *= weight_inv;
130 output_color.b *= weight_inv;
131 output_color.a *= weight_inv;
132 }
133 else {
134 output_color = default_color_;
135 }
136 });
137}
138
140 const ColorGeometry4b default_color)
141 : ColorGeometry4bMixer(buffer, buffer.index_range(), default_color)
142{
143}
144
146 const IndexMask &mask,
147 const ColorGeometry4b default_color)
148 : buffer_(buffer),
149 default_color_(default_color),
150 total_weights_(buffer.size(), 0.0f),
151 accumulation_buffer_(buffer.size(), float4(0, 0, 0, 0))
152{
153 const ColorGeometry4b zero{0, 0, 0, 0};
154 mask.foreach_index([&](const int64_t i) { buffer_[i] = zero; });
155}
156
157void ColorGeometry4bMixer::ColorGeometry4bMixer::set(int64_t index,
158 const ColorGeometry4b &color,
159 const float weight)
160{
161 accumulation_buffer_[index][0] = color.r * weight;
162 accumulation_buffer_[index][1] = color.g * weight;
163 accumulation_buffer_[index][2] = color.b * weight;
164 accumulation_buffer_[index][3] = color.a * weight;
165 total_weights_[index] = weight;
166}
167
168void ColorGeometry4bMixer::mix_in(int64_t index, const ColorGeometry4b &color, float weight)
169{
170 float4 &accum_value = accumulation_buffer_[index];
171 accum_value[0] += color.r * weight;
172 accum_value[1] += color.g * weight;
173 accum_value[2] += color.b * weight;
174 accum_value[3] += color.a * weight;
175 total_weights_[index] += weight;
176}
177
179{
180 this->finalize(buffer_.index_range());
181}
182
184{
185 mask.foreach_index([&](const int64_t i) {
186 const float weight = total_weights_[i];
187 const float4 &accum_value = accumulation_buffer_[i];
188 ColorGeometry4b &output_color = buffer_[i];
189 if (weight > 0.0f) {
190 const float weight_inv = 1.0f / weight;
191 output_color.r = accum_value[0] * weight_inv;
192 output_color.g = accum_value[1] * weight_inv;
193 output_color.b = accum_value[2] * weight_inv;
194 output_color.a = accum_value[3] * weight_inv;
195 }
196 else {
197 output_color = default_color_;
198 }
199 });
200}
201
203 : float4x4Mixer(buffer, buffer.index_range())
204{
205}
206
208 : buffer_(buffer),
209 total_weights_(buffer.size(), 0.0f),
210 location_buffer_(buffer.size(), float3(0)),
211 expmap_buffer_(buffer.size(), float3(0)),
212 scale_buffer_(buffer.size(), float3(0))
213{
214}
215
216void float4x4Mixer::float4x4Mixer::set(int64_t index, const float4x4 &value, const float weight)
217{
218 location_buffer_[index] = value.location() * weight;
219 expmap_buffer_[index] = math::to_quaternion(value).expmap() * weight;
220 scale_buffer_[index] = math::to_scale(value) * weight;
221 total_weights_[index] = weight;
222}
223
224void float4x4Mixer::mix_in(int64_t index, const float4x4 &value, float weight)
225{
226 location_buffer_[index] += value.location() * weight;
227 expmap_buffer_[index] += math::to_quaternion(value).expmap() * weight;
228 scale_buffer_[index] += math::to_scale(value) * weight;
229 total_weights_[index] += weight;
230}
231
233{
234 this->finalize(buffer_.index_range());
235}
236
238{
239 mask.foreach_index([&](const int64_t i) {
240 const float weight = total_weights_[i];
241 if (weight > 0.0f) {
242 const float weight_inv = math::rcp(weight);
244 location_buffer_[i] * weight_inv,
245 math::Quaternion::expmap(expmap_buffer_[i] * weight_inv),
246 scale_buffer_[i] * weight_inv);
247 }
248 else {
249 buffer_[i] = float4x4::identity();
250 }
251 });
252}
253
254void gather(const GSpan src, const Span<int> map, GMutableSpan dst)
255{
256 attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
257 using T = decltype(dummy);
258 array_utils::gather(src.typed<T>(), map, dst.typed<T>());
259 });
260}
261
262void gather(const GVArray &src, const Span<int> map, GMutableSpan dst)
263{
264 attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
265 using T = decltype(dummy);
266 array_utils::gather(src.typed<T>(), map, dst.typed<T>());
267 });
268}
269
271 const OffsetIndices<int> dst_offsets,
272 const IndexMask &selection,
273 const GSpan src,
274 GMutableSpan dst)
275{
276 attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
277 using T = decltype(dummy);
278 array_utils::gather_group_to_group(
279 src_offsets, dst_offsets, selection, src.typed<T>(), dst.typed<T>());
280 });
281}
282
284 const IndexMask &src_selection,
285 const GSpan src,
286 GMutableSpan dst)
287{
288 attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
289 using T = decltype(dummy);
290 array_utils::gather_to_groups(dst_offsets, src_selection, src.typed<T>(), dst.typed<T>());
291 });
292}
293
294} // namespace blender::bke::attribute_math
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ChannelStorageType r
Definition BLI_color.hh:88
ChannelStorageType g
Definition BLI_color.hh:88
ChannelStorageType b
Definition BLI_color.hh:88
ChannelStorageType a
Definition BLI_color.hh:88
const CPPType & type() const
ColorGeometry4bMixer(MutableSpan< ColorGeometry4b > buffer, ColorGeometry4b default_color=ColorGeometry4b(0, 0, 0, 255))
void mix_in(int64_t index, const ColorGeometry4b &color, float weight=1.0f)
void mix_in(int64_t index, const ColorGeometry4f &color, float weight=1.0f)
ColorGeometry4fMixer(MutableSpan< ColorGeometry4f > buffer, ColorGeometry4f default_color=ColorGeometry4f(0.0f, 0.0f, 0.0f, 1.0f))
void set(int64_t index, const ColorGeometry4f &color, float weight=1.0f)
void mix_in(int64_t index, const float4x4 &value, float weight=1.0f)
float4x4Mixer(MutableSpan< float4x4 > buffer)
local_group_size(16, 16) .push_constant(Type b
void gather(GSpan src, Span< int > map, GMutableSpan dst)
void gather_to_groups(OffsetIndices< int > dst_offsets, const IndexMask &src_selection, GSpan src, GMutableSpan dst)
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2)
T mix4(const float4 &weights, const T &v0, const T &v1, const T &v2, const T &v3)
void gather_group_to_group(OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, GSpan src, GMutableSpan dst)
T mix2(float factor, const T &a, const T &b)
QuaternionBase< T > to_quaternion(const AxisAngleBase< T, AngleT > &axis_angle)
T interpolate(const T &a, const T &b, const FactorT &t)
T rcp(const T &a)
QuaternionBase< T > normalized_to_quaternion_safe(const MatBase< T, 3, 3 > &mat)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
VecBase< T, 3 > to_scale(const MatBase< T, NumCol, NumRow > &mat)
MatT from_loc_rot_scale(const typename MatT::loc_type &location, const RotationT &rotation, const VecBase< typename MatT::base_type, ScaleDim > &scale)
MatBase< float, 3, 3 > float3x3
__int64 int64_t
Definition stdint.h:89
static QuaternionBase expmap(const VecBase< T, 3 > &expmap)