sculpto
matr4.h
Go to the documentation of this file.
1/*!****************************************************************//*!*
2 * \file matr4.h
3 * \brief Math 4x4 matrix implementation module.
4 *
5 * \author Sabitov Kirill
6 * \date 19 June 2022
7 *********************************************************************/
8
9#pragma once
10
11#include "matr3.h"
12
13namespace scl::math
14{
16 template<class T>
18 {
19 public:
21 T A[4][4];
22
25 A { {1, 0, 0, 0},
26 {0, 1, 0, 0},
27 {0, 0, 1, 0},
28 {0, 0, 0, 1} } {}
29
31 matr4_data(const matr4_data &Other)
32 {
33 memcpy(A, Other.A, sizeof(T) * 16);
34 }
35
36 /*!*
37 * Matrix data constructor by 16 values.
38 *
39 * \param A00-A33 - matrx valeus.
40 */
41 matr4_data(T A00, T A01, T A02, T A03,
42 T A10, T A11, T A12, T A13,
43 T A20, T A21, T A22, T A23,
44 T A30, T A31, T A32, T A33) :
45 A { {A00, A01, A02, A03},
46 {A10, A11, A12, A13},
47 {A20, A21, A22, A23},
48 {A30, A31, A32, A33} } {}
49
50 /*!*
51 * Getting pointer to first component of natrix operator.
52 * Need to pass vector to shader.
53 *
54 * \return pointer to first component of matrix.
55 */
56 operator T *()
57 {
58 return A[0];
59 }
60 };
61
63 template <typename T>
64 class matr4: public matr4_data<T>
65 {
66 private:
67 mutable T InvA[4][4];
68 mutable bool IsInverseEvaluated;
70 /*!*
71 * Evaluate inversed matrix function.
72 *
73 * \param None.
74 * \return None.
75 */
76 void EvaluateInverseMatrix() const
77 {
78 if (IsInverseEvaluated) return;
79 IsInverseEvaluated = true;
80
82 InvA[0][0] =
83 matr3<T>::Det(this->A[1][1], this->A[1][2], this->A[1][3],
84 this->A[2][1], this->A[2][2], this->A[2][3],
85 this->A[3][1], this->A[3][2], this->A[3][3]);
86 InvA[1][0] =
87 -matr3<T>::Det(this->A[1][0], this->A[1][2], this->A[1][3],
88 this->A[2][0], this->A[2][2], this->A[2][3],
89 this->A[3][0], this->A[3][2], this->A[3][3]);
90 InvA[2][0] =
91 matr3<T>::Det(this->A[1][0], this->A[1][1], this->A[1][3],
92 this->A[2][0], this->A[2][1], this->A[2][3],
93 this->A[3][0], this->A[3][1], this->A[3][3]);
94 InvA[3][0] =
95 -matr3<T>::Det(this->A[1][0], this->A[1][1], this->A[1][2],
96 this->A[2][0], this->A[2][1], this->A[2][2],
97 this->A[3][0], this->A[3][1], this->A[3][2]);
98
99 InvA[0][1] =
100 -matr3<T>::Det(this->A[0][1], this->A[0][2], this->A[0][3],
101 this->A[2][1], this->A[2][2], this->A[2][3],
102 this->A[3][1], this->A[3][2], this->A[3][3]);
103 InvA[1][1] =
104 matr3<T>::Det(this->A[0][0], this->A[0][2], this->A[0][3],
105 this->A[2][0], this->A[2][2], this->A[2][3],
106 this->A[3][0], this->A[3][2], this->A[3][3]);
107 InvA[2][1] =
108 -matr3<T>::Det(this->A[0][0], this->A[0][1], this->A[0][3],
109 this->A[2][0], this->A[2][1], this->A[2][3],
110 this->A[3][0], this->A[3][1], this->A[3][3]);
111 InvA[3][1] =
112 matr3<T>::Det(this->A[0][0], this->A[0][1], this->A[0][2],
113 this->A[2][0], this->A[2][1], this->A[2][2],
114 this->A[3][0], this->A[3][1], this->A[3][2]);
115
116 InvA[0][2] =
117 matr3<T>::Det(this->A[0][1], this->A[0][2], this->A[0][3],
118 this->A[1][1], this->A[1][2], this->A[1][3],
119 this->A[3][1], this->A[3][2], this->A[3][3]);
120 InvA[1][2] =
121 -matr3<T>::Det(this->A[0][0], this->A[0][2], this->A[0][3],
122 this->A[1][0], this->A[1][2], this->A[1][3],
123 this->A[3][0], this->A[3][2], this->A[3][3]);
124 InvA[2][2] =
125 matr3<T>::Det(this->A[0][0], this->A[0][1], this->A[0][3],
126 this->A[1][0], this->A[1][1], this->A[1][3],
127 this->A[3][0], this->A[3][1], this->A[3][3]);
128 InvA[3][2] =
129 -matr3<T>::Det(this->A[0][0], this->A[0][1], this->A[0][2],
130 this->A[1][0], this->A[1][1], this->A[1][2],
131 this->A[3][0], this->A[3][1], this->A[3][2]);
132
133 InvA[0][3] =
134 -matr3<T>::Det(this->A[0][1], this->A[0][2], this->A[0][3],
135 this->A[1][1], this->A[1][2], this->A[1][3],
136 this->A[2][1], this->A[2][2], this->A[2][3]);
137 InvA[1][3] =
138 matr3<T>::Det(this->A[0][0], this->A[0][2], this->A[0][3],
139 this->A[1][0], this->A[1][2], this->A[1][3],
140 this->A[2][0], this->A[2][2], this->A[2][3]);
141 InvA[2][3] =
142 -matr3<T>::Det(this->A[0][0], this->A[0][1], this->A[0][3],
143 this->A[1][0], this->A[1][1], this->A[1][3],
144 this->A[2][0], this->A[2][1], this->A[2][3]);
145 InvA[3][3] =
146 matr3<T>::Det(this->A[0][0], this->A[0][1], this->A[0][2],
147 this->A[1][0], this->A[1][1], this->A[1][2],
148 this->A[2][0], this->A[2][1], this->A[2][2]);
149
151 T det = Det();
152 det = 1 / det;
153 InvA[0][0] *= det; InvA[1][0] *= det; InvA[2][0] *= det; InvA[3][0] *= det;
154 InvA[0][1] *= det; InvA[1][1] *= det; InvA[2][1] *= det; InvA[3][1] *= det;
155 InvA[0][2] *= det; InvA[1][2] *= det; InvA[2][2] *= det; InvA[3][2] *= det;
156 InvA[0][3] *= det; InvA[1][3] *= det; InvA[2][3] *= det; InvA[3][3] *= det;
157 }
159 public:
160 /*!*
161 * Default matrix constructor.
162 * Set identity matrix.
163 *
164 * \param None.
165 */
167 matr4_data<T>(),
168 InvA { {0, 0, 0, 0},
169 {0, 0, 0, 0},
170 {0, 0, 0, 0},
171 {0, 0, 0, 0} },
172 IsInverseEvaluated(false) {}
173
174 /*!*
175 * Matrix constructor bt 16 values.
176 *
177 * \param A00-A33 - matrx valeus.
178 */
179 matr4(T A00, T A01, T A02, T A03,
180 T A10, T A11, T A12, T A13,
181 T A20, T A21, T A22, T A23,
182 T A30, T A31, T A32, T A33) :
183 matr4_data<T>(A00, A01, A02, A03,
184 A10, A11, A12, A13,
185 A20, A21, A22, A23,
186 A30, A31, A32, A33),
187 InvA { {0, 0, 0, 0},
188 {0, 0, 0, 0},
189 {0, 0, 0, 0},
190 {0, 0, 0, 0} },
191 IsInverseEvaluated(false) {}
192
193 /*!*
194 * Matrix contructor by array of values.
195 *
196 * \param A - array of values to set in matrix
197 */
198 matr4(T A[4][4]) :
199 InvA { {0, 0, 0, 0},
200 {0, 0, 0, 0},
201 {0, 0, 0, 0},
202 {0, 0, 0, 0} },
203 IsInverseEvaluated(false)
204 {
205 memcpy(this->A, A, 4 * 4 * sizeof(T));
206 }
207
208 /*!*
209 * Matrix data constructor by 1 value.
210 *
211 * \param A00 - calue to set to all matrix cells.
212 */
213 matr4(T A00) :
214 matr4_data<T>(A00, A00, A00, A00,
215 A00, A00, A00, A00,
216 A00, A00, A00, A00,
217 A00, A00, A00, A00),
218 InvA { {0, 0, 0, 0},
219 {0, 0, 0, 0},
220 {0, 0, 0, 0},
221 {0, 0, 0, 0} },
222 IsInverseEvaluated(false) {}
223
224 /*!*
225 * Matrix constructor by matrix data.
226 *
227 * \param Other - matrix data.
228 */
229 matr4(const matr4_data<T> &Other) :
230 matr4_data<T>(Other),
231 InvA { {0, 0, 0, 0},
232 {0, 0, 0, 0},
233 {0, 0, 0, 0},
234 {0, 0, 0, 0} },
235 IsInverseEvaluated(false) {}
236
237 public:
238 /*!*
239 * Identity creation function.
240 *
241 * \return identity matrix.
242 */
244 {
245 return matr4(1, 0, 0, 0,
246 0, 1, 0, 0,
247 0, 0, 1, 0,
248 0, 0, 0, 1);
249 }
250
251 /*!*
252 * Translate matrix creation function.
253 *
254 * \param Transform - translatino vector.
255 * \return translation matrix.
256 */
257 static matr4 Translate(const vec3<T> &Transform)
258 {
259 T x = Transform.GetX(), y = Transform.GetY(), z = Transform.GetZ();
260 return matr4(1, 0, 0, 0,
261 0, 1, 0, 0,
262 0, 0, 1, 0,
263 x, y, z, 1);
264 }
265
266 /*!*
267 * Scale matrix creation function.
268 *
269 * \param S - scale factor.
270 * \return scale matrix.
271 */
273 {
274 T x = S.X, y = S.Y, z = S.Z;
275 return matr4(x, 0, 0, 0,
276 0, y, 0, 0,
277 0, 0, z, 0,
278 0, 0, 0, 1);
279 }
280
281 /*!*
282 * Rotation matrix creation function.
283 *
284 * \param Axis - axis to rotate around of.
285 * \param Angle - angle in degrees to roate on.
286 * \return rotation matrix.
287 */
288 static matr4 Rotate(vec3<T> Axis, degrees<T> Angle)
289 {
290 T c = cos((radians<T>)Angle);
291 T s = sin((radians<T>)Angle);
292 vec3<T> v = Axis.Normalized();
293
294 return matr4(c + v.X * v.X * (1 - c), v.X * v.Y * (1 - c) + v.Z * s, v.X * v.Z * (1 - c) - v.Y * s, 0,
295 v.Y * v.X * (1 - c) - v.Z * s, c + v.Y * v.Y * (1 - c), v.Y * v.Z * (1 - c) + v.X * s, 0,
296 v.Z * v.X * (1 - c) + v.Y * s, v.Z * v.Y * (1 - c) - v.X * s, c + v.Z * v.Z * (1 - c), 0,
297 0, 0, 0, 1);
298 }
299
300 /*!*
301 * Rotation around X axis matrix creation function.
302 *
303 * \param Angle - angle in degrees to roate on.
304 * \return rotation matrix.
305 */
307 {
308 T c = cos((radians<T>)Angle);
309 T s = sin((radians<T>)Angle);
310
311 return matr4(1, 0, 0, 0,
312 0, c, s, 0,
313 0, -s, c, 0,
314 0, 0, 0, 1);
315 }
316
317 /*!*
318 * Rotation around Y axis matrix creation function.
319 *
320 * \param Angle - angle in degrees to roate on.
321 * \return rotation matrix.
322 */
324 {
325 T c = cos((radians<T>)Angle);
326 T s = sin((radians<T>)Angle);
327
328 return matr4(c, 0, -s, 0,
329 0, 1, 0, 0,
330 s, 0, c, 0,
331 0, 0, 0, 1);
332 }
333
334 /*!*
335 * Rotation around Z axis matrix creation function.
336 *
337 * \param Angle - angle in degrees to roate on.
338 * \return rotation matrix.
339 */
341 {
342 T c = cos((radians<T>)Angle);
343 T s = sin((radians<T>)Angle);
344
345 return matr4(c, -s, 0, 0,
346 s, c, 0, 0,
347 0, 0, 1, 0,
348 0, 0, 0, 1);
349 }
350
351 /*!*
352 * Frusum projection matrix creation function.
353 *
354 * \param Left, Right - frustrum view cone left and right sides position
355 * \param Bottom, Top - frustrum view cone bottom and top sides position
356 * \param Near, Far - frustrum view cone near and far planes distance.
357 * \return None.
358 */
359 static matr4 Frustum(T Left, T Right, T Bottom, T Top, T Near, T Far)
360 {
361 return matr4(2 * Near / (Right - Left), 0, 0, 0,
362 0, 2 * Near / (Top - Bottom), 0, 0,
363 (Right + Left) / (Right - Left), (Top + Bottom) / (Top - Bottom), -(Far + Near) / (Far - Near), -1,
364 0, 0, -2 * Near * Far / (Far - Near), 0);
365 }
366
367 /*!*
368 * Ortho projection matrix creation function.
369 *
370 * \param Left, Right - view cube left and right sides position
371 * \param Bottom, Top - view cube bottom and top sides position
372 * \param Near, Far - view cube near and far planes distance.
373 * \return ortho matrix.
374 */
375 static matr4 Ortho(T Left, T Right, T Bottom, T Top, T Near, T Far)
376 {
377 return matr4(2 / (Right - Left), 0, 0, 0,
378 0, 2 / (Top - Bottom), 0, 0,
379 0, 0, -2 / (Far - Near), 0,
380 -(Right + Left) / (Right - Left), -(Top + Bottom) / (Top - Bottom), -(Near + Far) / (Far - Near), 1);
381 }
382
383 /*!*
384 * Viewer coordinate system transformation.
385 *
386 * \param Location - viewer position in global coordinate system.
387 * \param At - viewer looking at point.
388 * \param Up - viewer up direction point.
389 * \return view matrix.
390 */
391 static matr4 View(vec3<T> Location, vec3<T> At, vec3<T> Up)
392 {
393 vec3<T> d = (At - Location).Normalized();
394 vec3<T> r = (
395 d.Dot(Up.Normalized()) == -1 ?
396 vec3 { -d.Y, d.X, d.Z } :
397 r = d.Cross(Up).Normalized()
398 );
399 vec3<T> u = r.Cross(d);
400
401 return matr4(r.X, u.X, -d.X, 0,
402 r.Y, u.Y, -d.Y, 0,
403 r.Z, u.Z, -d.Z, 0,
404 -Location.Dot(r), -Location.Dot(u), Location.Dot(d), 1);
405 }
406
407 public:
408 /*!*
409 * Matrix lerp function.
410 *
411 * \param Start, End - matrices to interpolate.
412 * \param Current - interpolation value [0;1].
413 * \return interpolated matrix.
414 */
415 static matr4 Lerp(const matr4 &Start, const matr4 &End, T Current)
416 {
417 matr4 M;
418
419 for (int i = 0; i < 4; i++)
420 for (int j = 0; j < 4; j++)
421 M.A[i][j] = ::scl::math::Lerp(Start.A[i][j],
422 End.A[i][j],
423 Current);
424
425 return M;
426 }
427
428 /*!*
429 * Transpose matrix function.
430 *
431 * \return result matrix.
432 */
434 {
435 return matr4(this->A[0][0], this->A[1][0], this->A[2][0], this->A[3][0],
436 this->A[0][1], this->A[1][1], this->A[2][1], this->A[3][1],
437 this->A[0][2], this->A[1][2], this->A[2][2], this->A[3][2],
438 this->A[0][3], this->A[1][3], this->A[2][3], this->A[3][3]);
439 }
440
441 /*!*
442 * Mulpiply matrices function.
443 *
444 * \param M - matrix to multyply.
445 * \return result matrix.
446 */
447 matr4 operator*(const matr4 &M) const
448 {
449 matr4 r;
450 int k;
451
452 for (int i = 0; i < 4; i++)
453 for (int j = 0; j < 4; j++)
454 for (k = 0, r.A[i][j] = 0; k < 4; k++)
455 r.A[i][j] += this->A[i][k] * M.A[k][j];
456 return r;
457 }
458
459 /*!*
460 * Calculate matrix determinant.
461 *
462 * \param None.
463 * \return matrix determinant.
464 */
465 T Det() const
466 {
467 return
468 this->A[0][0] * matr3<T>::Det(this->A[1][1], this->A[1][2], this->A[1][3],
469 this->A[2][1], this->A[2][2], this->A[2][3],
470 this->A[3][1], this->A[3][2], this->A[3][3]) +
471 -this->A[0][1] * matr3<T>::Det(this->A[1][0], this->A[1][2], this->A[1][3],
472 this->A[2][0], this->A[2][2], this->A[2][3],
473 this->A[3][0], this->A[3][2], this->A[3][3]) +
474 this->A[0][2] * matr3<T>::Det(this->A[1][0], this->A[1][1], this->A[1][3],
475 this->A[2][0], this->A[2][1], this->A[2][3],
476 this->A[3][0], this->A[3][1], this->A[3][3]) +
477 -this->A[0][3] * matr3<T>::Det(this->A[1][0], this->A[1][1], this->A[1][2],
478 this->A[2][0], this->A[2][1], this->A[2][2],
479 this->A[3][0], this->A[3][1], this->A[3][2]);
480 }
481
482 /*!*
483 * Get inversed matrix.
484 *
485 * \param None.
486 * \return None.
487 */
489 {
490 EvaluateInverseMatrix();
491 return matr4(InvA);
492 }
493
494 /*!*
495 * Transform point position.
496 *
497 * \param V - vectors to transform.
498 * \return None.
499 */
501 {
502 return vec3<T>(V.X * this->A[0][0] + V.Y * this->A[1][0] + V.Z * this->A[2][0] + this->A[3][0],
503 V.X * this->A[0][1] + V.Y * this->A[1][1] + V.Z * this->A[2][1] + this->A[3][1],
504 V.X * this->A[0][2] + V.Y * this->A[1][2] + V.Z * this->A[2][2] + this->A[3][2]);
505 }
506
507 /*!*
508 * Vector linear transformation.
509 *
510 * \param V - vectors to transform.
511 * \return None.
512 */
514 {
515 return vec3<T>(V.X * this->A[0][0] + V.Y * this->A[1][0] + V.Z * this->A[2][0],
516 V.X * this->A[0][1] + V.Y * this->A[1][1] + V.Z * this->A[2][1],
517 V.X * this->A[0][2] + V.Y * this->A[1][2] + V.Z * this->A[2][2]);
518 }
519
520 /*!*
521 * Multiply matrix and vector.
522 *
523 * \param V - vectors to transform.
524 * \return None.
525 */
527 {
528 float w = V.X * this->A[0][3] + V.Y * this->A[1][3] + V.Z * this->A[2][3] + this->A[3][3];
529
530 return vec3<T>((V.X * this->A[0][0] + V.Y * this->A[1][0] + V.Z * this->A[2][0] + this->A[3][0]) / w,
531 (V.X * this->A[0][1] + V.Y * this->A[1][1] + V.Z * this->A[2][1] + this->A[3][1]) / w,
532 (V.X * this->A[0][2] + V.Y * this->A[1][2] + V.Z * this->A[2][2] + this->A[3][2]) / w);
533 }
534
535 /*!*
536 * Getting matrix cell value operator overloading.
537 *
538 * \param Index - cell index.
539 * \return vector cartesian coordinate.
540 */
541 T &operator [](int Index)
542 {
543 return this->A[math::Clamp(Index, 0, 15)];
544 }
545
546 /*!*
547 * Getting coordinate operator overloading.
548 *
549 * \param Index - coordinate index.
550 * \return vector cartesian coordinate.
551 */
552 T operator [](int Index) const
553 {
554 return this->A[math::Clamp(Index, 0, 15)];
555 }
556 };
557}
matr4_data(T A00, T A01, T A02, T A03, T A10, T A11, T A12, T A13, T A20, T A21, T A22, T A23, T A30, T A31, T A32, T A33)
Definition: matr4.h:41
matr4_data(const matr4_data &Other)
Definition: matr4.h:31
static matr4 Identity()
Definition: matr4.h:243
matr4 Transpose() const
Definition: matr4.h:433
vec3< T > Transform4x4(const vec3< T > &V) const
Definition: matr4.h:526
matr4 Inverse() const
Definition: matr4.h:488
static matr4 Rotate(vec3< T > Axis, degrees< T > Angle)
Definition: matr4.h:288
static matr4 RotateY(degrees< T > Angle)
Definition: matr4.h:323
matr4 operator*(const matr4 &M) const
Definition: matr4.h:447
matr4(const matr4_data< T > &Other)
Definition: matr4.h:229
static matr4 Frustum(T Left, T Right, T Bottom, T Top, T Near, T Far)
Definition: matr4.h:359
T Det() const
Definition: matr4.h:465
matr4(T A[4][4])
Definition: matr4.h:198
static matr4 Lerp(const matr4 &Start, const matr4 &End, T Current)
Definition: matr4.h:415
static matr4 View(vec3< T > Location, vec3< T > At, vec3< T > Up)
Definition: matr4.h:391
matr4(T A00, T A01, T A02, T A03, T A10, T A11, T A12, T A13, T A20, T A21, T A22, T A23, T A30, T A31, T A32, T A33)
Definition: matr4.h:179
static matr4 Scale(vec3< T > S)
Definition: matr4.h:272
matr4(T A00)
Definition: matr4.h:213
static matr4 Ortho(T Left, T Right, T Bottom, T Top, T Near, T Far)
Definition: matr4.h:375
static matr4 RotateZ(degrees< T > Angle)
Definition: matr4.h:340
vec3< T > TransformVector(const vec3< T > &V) const
Definition: matr4.h:513
static matr4 RotateX(degrees< T > Angle)
Definition: matr4.h:306
vec3< T > TransformPoint(const vec3< T > &V) const
Definition: matr4.h:500
static matr4 Translate(const vec3< T > &Transform)
Definition: matr4.h:257
vec3 Normalized() const
Definition: vec3.h:190
T Dot(const vec3 &Other) const
Definition: vec3.h:213
T GetX() const
Definition: vec3.h:43
T GetZ() const
Definition: vec3.h:47
vec3 Cross(const vec3 &Other) const
Definition: vec3.h:224
T GetY() const
Definition: vec3.h:45
T Clamp(T Num, T Min=0, T Max=1)
Definition: math_common.h:77
T Lerp(T Start, T End, T Current)
Definition: math_common.h:91
math::matr4< float > matr4
Definition: base.h:48