master
ブランチ master
VulkanExample / dep / include / glm / detail / func_matrix.inl
15.8 KB、484行 生 Blame 履歴
1#include "../geometric.hpp"
2#include <limits>
3
4namespace glm{
5namespace detail
6{
7 template<length_t C, length_t R, typename T, qualifier Q, bool Aligned>
8 struct compute_matrixCompMult
9 {
10 GLM_FUNC_QUALIFIER static mat<C, R, T, Q> call(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y)
11 {
12 mat<C, R, T, Q> Result(1);
13 for(length_t i = 0; i < Result.length(); ++i)
14 Result[i] = x[i] * y[i];
15 return Result;
16 }
17 };
18
19 template<length_t C, length_t R, typename T, qualifier Q, bool IsFloat, bool Aligned>
20 struct compute_matrixCompMult_type {
21 GLM_FUNC_QUALIFIER static mat<C, R, T, Q> call(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y)
22 {
23 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE,
24 "'matrixCompMult' only accept floating-point inputs, include <glm/ext/matrix_integer.hpp> to discard this restriction.");
25 return detail::compute_matrixCompMult<C, R, T, Q, detail::is_aligned<Q>::value>::call(x, y);
26 }
27 };
28
29 template<length_t DA, length_t DB, typename T, qualifier Q>
30 struct compute_outerProduct {
31 GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<DA, DB, T, Q>::type call(vec<DA, T, Q> const& c, vec<DB, T, Q> const& r)
32 {
33 typename detail::outerProduct_trait<DA, DB, T, Q>::type m(0);
34 for(length_t i = 0; i < m.length(); ++i)
35 m[i] = c * r[i];
36 return m;
37 }
38 };
39
40 template<length_t DA, length_t DB, typename T, qualifier Q, bool IsFloat>
41 struct compute_outerProduct_type {
42 GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<DA, DB, T, Q>::type call(vec<DA, T, Q> const& c, vec<DB, T, Q> const& r)
43 {
44 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE,
45 "'outerProduct' only accept floating-point inputs, include <glm/ext/matrix_integer.hpp> to discard this restriction.");
46
47 return detail::compute_outerProduct<DA, DB, T, Q>::call(c, r);
48 }
49 };
50
51 template<length_t C, length_t R, typename T, qualifier Q, bool Aligned>
52 struct compute_transpose{};
53
54 template<typename T, qualifier Q, bool Aligned>
55 struct compute_transpose<2, 2, T, Q, Aligned>
56 {
57 GLM_FUNC_QUALIFIER static mat<2, 2, T, Q> call(mat<2, 2, T, Q> const& m)
58 {
59 mat<2, 2, T, Q> Result(1);
60 Result[0][0] = m[0][0];
61 Result[0][1] = m[1][0];
62 Result[1][0] = m[0][1];
63 Result[1][1] = m[1][1];
64 return Result;
65 }
66 };
67
68 template<typename T, qualifier Q, bool Aligned>
69 struct compute_transpose<2, 3, T, Q, Aligned>
70 {
71 GLM_FUNC_QUALIFIER static mat<3, 2, T, Q> call(mat<2, 3, T, Q> const& m)
72 {
73 mat<3,2, T, Q> Result(1);
74 Result[0][0] = m[0][0];
75 Result[0][1] = m[1][0];
76 Result[1][0] = m[0][1];
77 Result[1][1] = m[1][1];
78 Result[2][0] = m[0][2];
79 Result[2][1] = m[1][2];
80 return Result;
81 }
82 };
83
84 template<typename T, qualifier Q, bool Aligned>
85 struct compute_transpose<2, 4, T, Q, Aligned>
86 {
87 GLM_FUNC_QUALIFIER static mat<4, 2, T, Q> call(mat<2, 4, T, Q> const& m)
88 {
89 mat<4, 2, T, Q> Result(1);
90 Result[0][0] = m[0][0];
91 Result[0][1] = m[1][0];
92 Result[1][0] = m[0][1];
93 Result[1][1] = m[1][1];
94 Result[2][0] = m[0][2];
95 Result[2][1] = m[1][2];
96 Result[3][0] = m[0][3];
97 Result[3][1] = m[1][3];
98 return Result;
99 }
100 };
101
102 template<typename T, qualifier Q, bool Aligned>
103 struct compute_transpose<3, 2, T, Q, Aligned>
104 {
105 GLM_FUNC_QUALIFIER static mat<2, 3, T, Q> call(mat<3, 2, T, Q> const& m)
106 {
107 mat<2, 3, T, Q> Result(1);
108 Result[0][0] = m[0][0];
109 Result[0][1] = m[1][0];
110 Result[0][2] = m[2][0];
111 Result[1][0] = m[0][1];
112 Result[1][1] = m[1][1];
113 Result[1][2] = m[2][1];
114 return Result;
115 }
116 };
117
118 template<typename T, qualifier Q, bool Aligned>
119 struct compute_transpose<3, 3, T, Q, Aligned>
120 {
121 GLM_FUNC_QUALIFIER static mat<3, 3, T, Q> call(mat<3, 3, T, Q> const& m)
122 {
123 mat<3, 3, T, Q> Result(1);
124 Result[0][0] = m[0][0];
125 Result[0][1] = m[1][0];
126 Result[0][2] = m[2][0];
127
128 Result[1][0] = m[0][1];
129 Result[1][1] = m[1][1];
130 Result[1][2] = m[2][1];
131
132 Result[2][0] = m[0][2];
133 Result[2][1] = m[1][2];
134 Result[2][2] = m[2][2];
135 return Result;
136 }
137 };
138
139 template<typename T, qualifier Q, bool Aligned>
140 struct compute_transpose<3, 4, T, Q, Aligned>
141 {
142 GLM_FUNC_QUALIFIER static mat<4, 3, T, Q> call(mat<3, 4, T, Q> const& m)
143 {
144 mat<4, 3, T, Q> Result(1);
145 Result[0][0] = m[0][0];
146 Result[0][1] = m[1][0];
147 Result[0][2] = m[2][0];
148 Result[1][0] = m[0][1];
149 Result[1][1] = m[1][1];
150 Result[1][2] = m[2][1];
151 Result[2][0] = m[0][2];
152 Result[2][1] = m[1][2];
153 Result[2][2] = m[2][2];
154 Result[3][0] = m[0][3];
155 Result[3][1] = m[1][3];
156 Result[3][2] = m[2][3];
157 return Result;
158 }
159 };
160
161 template<typename T, qualifier Q, bool Aligned>
162 struct compute_transpose<4, 2, T, Q, Aligned>
163 {
164 GLM_FUNC_QUALIFIER static mat<2, 4, T, Q> call(mat<4, 2, T, Q> const& m)
165 {
166 mat<2, 4, T, Q> Result(1);
167 Result[0][0] = m[0][0];
168 Result[0][1] = m[1][0];
169 Result[0][2] = m[2][0];
170 Result[0][3] = m[3][0];
171 Result[1][0] = m[0][1];
172 Result[1][1] = m[1][1];
173 Result[1][2] = m[2][1];
174 Result[1][3] = m[3][1];
175 return Result;
176 }
177 };
178
179 template<typename T, qualifier Q, bool Aligned>
180 struct compute_transpose<4, 3, T, Q, Aligned>
181 {
182 GLM_FUNC_QUALIFIER static mat<3, 4, T, Q> call(mat<4, 3, T, Q> const& m)
183 {
184 mat<3, 4, T, Q> Result(1);
185 Result[0][0] = m[0][0];
186 Result[0][1] = m[1][0];
187 Result[0][2] = m[2][0];
188 Result[0][3] = m[3][0];
189 Result[1][0] = m[0][1];
190 Result[1][1] = m[1][1];
191 Result[1][2] = m[2][1];
192 Result[1][3] = m[3][1];
193 Result[2][0] = m[0][2];
194 Result[2][1] = m[1][2];
195 Result[2][2] = m[2][2];
196 Result[2][3] = m[3][2];
197 return Result;
198 }
199 };
200
201 template<typename T, qualifier Q, bool Aligned>
202 struct compute_transpose<4, 4, T, Q, Aligned>
203 {
204 GLM_FUNC_QUALIFIER static mat<4, 4, T, Q> call(mat<4, 4, T, Q> const& m)
205 {
206 mat<4, 4, T, Q> Result(1);
207 Result[0][0] = m[0][0];
208 Result[0][1] = m[1][0];
209 Result[0][2] = m[2][0];
210 Result[0][3] = m[3][0];
211
212 Result[1][0] = m[0][1];
213 Result[1][1] = m[1][1];
214 Result[1][2] = m[2][1];
215 Result[1][3] = m[3][1];
216
217 Result[2][0] = m[0][2];
218 Result[2][1] = m[1][2];
219 Result[2][2] = m[2][2];
220 Result[2][3] = m[3][2];
221
222 Result[3][0] = m[0][3];
223 Result[3][1] = m[1][3];
224 Result[3][2] = m[2][3];
225 Result[3][3] = m[3][3];
226 return Result;
227 }
228 };
229
230 template<length_t C, length_t R, typename T, qualifier Q, bool IsFloat, bool Aligned>
231 struct compute_transpose_type {
232 GLM_FUNC_QUALIFIER static mat<R, C, T, Q> call(mat<C, R, T, Q> const& m)
233 {
234 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE,
235 "'transpose' only accept floating-point inputs, include <glm/ext/matrix_integer.hpp> to discard this restriction.");
236 return detail::compute_transpose<C, R, T, Q, detail::is_aligned<Q>::value>::call(m);
237 }
238 };
239
240 template<length_t C, length_t R, typename T, qualifier Q, bool Aligned>
241 struct compute_determinant{};
242
243 template<typename T, qualifier Q, bool Aligned>
244 struct compute_determinant<2, 2, T, Q, Aligned>
245 {
246 GLM_FUNC_QUALIFIER static T call(mat<2, 2, T, Q> const& m)
247 {
248 return m[0][0] * m[1][1] - m[1][0] * m[0][1];
249 }
250 };
251
252 template<typename T, qualifier Q, bool Aligned>
253 struct compute_determinant<3, 3, T, Q, Aligned>
254 {
255 GLM_FUNC_QUALIFIER static T call(mat<3, 3, T, Q> const& m)
256 {
257 return
258 + m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])
259 - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2])
260 + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
261 }
262 };
263
264 template<typename T, qualifier Q, bool Aligned>
265 struct compute_determinant<4, 4, T, Q, Aligned>
266 {
267 GLM_FUNC_QUALIFIER static T call(mat<4, 4, T, Q> const& m)
268 {
269 T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
270 T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
271 T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
272 T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
273 T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
274 T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
275
276 vec<4, T, Q> DetCof(
277 + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02),
278 - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04),
279 + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05),
280 - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05));
281
282 return
283 m[0][0] * DetCof[0] + m[0][1] * DetCof[1] +
284 m[0][2] * DetCof[2] + m[0][3] * DetCof[3];
285 }
286 };
287
288 template<length_t C, length_t R, typename T, qualifier Q, bool IsFloat, bool Aligned>
289 struct compute_determinant_type{
290
291 GLM_FUNC_QUALIFIER static T call(mat<C, R, T, Q> const& m)
292 {
293 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE,
294 "'determinant' only accept floating-point inputs, include <glm/ext/matrix_integer.hpp> to discard this restriction.");
295 return detail::compute_determinant<C, R, T, Q, detail::is_aligned<Q>::value>::call(m);
296 }
297 };
298
299 template<length_t C, length_t R, typename T, qualifier Q, bool Aligned>
300 struct compute_inverse{};
301
302 template<typename T, qualifier Q, bool Aligned>
303 struct compute_inverse<2, 2, T, Q, Aligned>
304 {
305 GLM_FUNC_QUALIFIER static mat<2, 2, T, Q> call(mat<2, 2, T, Q> const& m)
306 {
307 T OneOverDeterminant = static_cast<T>(1) / (
308 + m[0][0] * m[1][1]
309 - m[1][0] * m[0][1]);
310
311 mat<2, 2, T, Q> Inverse(
312 + m[1][1] * OneOverDeterminant,
313 - m[0][1] * OneOverDeterminant,
314 - m[1][0] * OneOverDeterminant,
315 + m[0][0] * OneOverDeterminant);
316
317 return Inverse;
318 }
319 };
320
321 template<typename T, qualifier Q, bool is_aligned>
322 struct inv3x3 {};
323
324 template<typename T, qualifier Q>
325 struct inv3x3<T, Q, true>
326 {
327 GLM_FUNC_QUALIFIER static mat<3, 3, T, Q> call(mat<3, 3, T, Q> const& m)
328 {
329 // see: https://www.onlinemathstutor.org/post/3x3_inverses
330
331 vec<4, T, Q> a = xyz0(m[0]);
332 vec<4, T, Q> b = xyz0(m[1]);
333 vec<4, T, Q> c = xyz0(m[2]);
334
335 vec<4, T, Q> i0 = compute_cross<T, Q, true>::call(b, c);
336 vec<4, T, Q> i1 = compute_cross<T, Q, true>::call(c, a);
337 vec<4, T, Q> i2 = compute_cross<T, Q, true>::call(a, b);
338
339 mat<3, 3, T, Q> Inverse;
340 Inverse[0] = xyz(i0);
341 Inverse[1] = xyz(i1);
342 Inverse[2] = xyz(i2);
343 Inverse = transpose(Inverse);
344
345 T Determinant = compute_dot<vec<4, T, Q>, T, true>::call(a, compute_cross<T, Q, true>::call(b, c));
346 vec<3, T, Q> OneOverDeterminant(static_cast<T>(1) / Determinant);
347 Inverse *= OneOverDeterminant;
348 return Inverse;
349 }
350 };
351
352 template<typename T, qualifier Q>
353 struct inv3x3<T, Q, false>
354 {
355 GLM_FUNC_QUALIFIER static mat<3, 3, T, Q> call(mat<3, 3, T, Q> const& m)
356 {
357 T OneOverDeterminant = static_cast<T>(1) / (
358 +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])
359 - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2])
360 + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]));
361
362 mat<3, 3, T, Q> Inverse;
363 Inverse[0][0] = +(m[1][1] * m[2][2] - m[2][1] * m[1][2]);
364 Inverse[1][0] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);
365 Inverse[2][0] = +(m[1][0] * m[2][1] - m[2][0] * m[1][1]);
366 Inverse[0][1] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);
367 Inverse[1][1] = +(m[0][0] * m[2][2] - m[2][0] * m[0][2]);
368 Inverse[2][1] = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);
369 Inverse[0][2] = +(m[0][1] * m[1][2] - m[1][1] * m[0][2]);
370 Inverse[1][2] = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);
371 Inverse[2][2] = +(m[0][0] * m[1][1] - m[1][0] * m[0][1]);
372
373 Inverse *= OneOverDeterminant;
374 return Inverse;
375 }
376 };
377
378 template<typename T, qualifier Q, bool Aligned>
379 struct compute_inverse<3, 3, T, Q, Aligned>
380 {
381 GLM_FUNC_QUALIFIER static mat<3, 3, T, Q> call(mat<3, 3, T, Q> const& m)
382 {
383 return detail::inv3x3<T, Q, detail::is_aligned<Q>::value>::call(m);
384 }
385 };
386
387 template<typename T, qualifier Q, bool Aligned>
388 struct compute_inverse<4, 4, T, Q, Aligned>
389 {
390 GLM_FUNC_QUALIFIER static mat<4, 4, T, Q> call(mat<4, 4, T, Q> const& m)
391 {
392 T Coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
393 T Coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3];
394 T Coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3];
395
396 T Coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
397 T Coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
398 T Coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3];
399
400 T Coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
401 T Coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2];
402 T Coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
403
404 T Coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
405 T Coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3];
406 T Coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3];
407
408 T Coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
409 T Coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2];
410 T Coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2];
411
412 T Coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
413 T Coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1];
414 T Coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
415
416 vec<4, T, Q> Fac0(Coef00, Coef00, Coef02, Coef03);
417 vec<4, T, Q> Fac1(Coef04, Coef04, Coef06, Coef07);
418 vec<4, T, Q> Fac2(Coef08, Coef08, Coef10, Coef11);
419 vec<4, T, Q> Fac3(Coef12, Coef12, Coef14, Coef15);
420 vec<4, T, Q> Fac4(Coef16, Coef16, Coef18, Coef19);
421 vec<4, T, Q> Fac5(Coef20, Coef20, Coef22, Coef23);
422
423 vec<4, T, Q> Vec0(m[1][0], m[0][0], m[0][0], m[0][0]);
424 vec<4, T, Q> Vec1(m[1][1], m[0][1], m[0][1], m[0][1]);
425 vec<4, T, Q> Vec2(m[1][2], m[0][2], m[0][2], m[0][2]);
426 vec<4, T, Q> Vec3(m[1][3], m[0][3], m[0][3], m[0][3]);
427
428 vec<4, T, Q> Inv0(Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2);
429 vec<4, T, Q> Inv1(Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4);
430 vec<4, T, Q> Inv2(Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5);
431 vec<4, T, Q> Inv3(Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5);
432
433 vec<4, T, Q> SignA(+1, -1, +1, -1);
434 vec<4, T, Q> SignB(-1, +1, -1, +1);
435 mat<4, 4, T, Q> Inverse(Inv0 * SignA, Inv1 * SignB, Inv2 * SignA, Inv3 * SignB);
436
437 vec<4, T, Q> Row0(Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0]);
438
439 vec<4, T, Q> Dot0(m[0] * Row0);
440 T Dot1 = (Dot0.x + Dot0.y) + (Dot0.z + Dot0.w);
441
442 T OneOverDeterminant = static_cast<T>(1) / Dot1;
443
444 return Inverse * OneOverDeterminant;
445 }
446 };
447}//namespace detail
448
449 template<length_t C, length_t R, typename T, qualifier Q>
450 GLM_FUNC_QUALIFIER mat<C, R, T, Q> matrixCompMult(mat<C, R, T, Q> const& x, mat<C, R, T, Q> const& y)
451 {
452 return detail::compute_matrixCompMult_type<C, R, T, Q, std::numeric_limits<T>::is_iec559, detail::is_aligned<Q>::value>::call(x, y);
453 }
454
455 template<length_t DA, length_t DB, typename T, qualifier Q>
456 GLM_FUNC_QUALIFIER typename detail::outerProduct_trait<DA, DB, T, Q>::type outerProduct(vec<DA, T, Q> const& c, vec<DB, T, Q> const& r)
457 {
458 return detail::compute_outerProduct_type<DA, DB, T, Q, std::numeric_limits<T>::is_iec559>::call(c, r);
459 }
460
461 template<length_t C, length_t R, typename T, qualifier Q>
462 GLM_FUNC_QUALIFIER typename mat<C, R, T, Q>::transpose_type transpose(mat<C, R, T, Q> const& m)
463 {
464 return detail::compute_transpose_type<C, R, T, Q, std::numeric_limits<T>::is_iec559, detail::is_aligned<Q>::value>::call(m);
465 }
466
467 template<length_t C, length_t R, typename T, qualifier Q>
468 GLM_FUNC_QUALIFIER T determinant(mat<C, R, T, Q> const& m)
469 {
470 return detail::compute_determinant_type<C, R, T, Q, std::numeric_limits<T>::is_iec559, detail::is_aligned<Q>::value>::call(m);
471 }
472
473 template<length_t C, length_t R, typename T, qualifier Q>
474 GLM_FUNC_QUALIFIER mat<C, R, T, Q> inverse(mat<C, R, T, Q> const& m)
475 {
476 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'inverse' only accept floating-point inputs");
477 return detail::compute_inverse<C, R, T, Q, detail::is_aligned<Q>::value>::call(m);
478 }
479}//namespace glm
480
481#if GLM_CONFIG_SIMD == GLM_ENABLE
482# include "func_matrix_simd.inl"
483#endif
484