TGX 1.1.1
A tiny 2D/3D graphics library optimized for 32 bits microcontrollers.
Loading...
Searching...
No Matches
Mat4.h
Go to the documentation of this file.
1
5//
6// Copyright 2020 Arvind Singh
7//
8// This library is free software; you can redistribute it and/or
9// modify it under the terms of the GNU Lesser General Public
10// License as published by the Free Software Foundation; either
11//version 2.1 of the License, or (at your option) any later version.
12//
13// This library is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
16// Lesser General Public License for more details.
17//
18// You should have received a copy of the GNU Lesser General Public
19// License along with this library; If not, see <http://www.gnu.org/licenses/>.
20
21
22#ifndef _TGX_MAT4_H_
23#define _TGX_MAT4_H_
24
25// only C++, no plain C
26#ifdef __cplusplus
27
28
29#include <stdint.h>
30#include <type_traits>
31
32#include "Misc.h"
33#include "Vec2.h"
34#include "Vec3.h"
35#include "Vec4.h"
36
37
38namespace tgx
39{
40
41 // forward declaration
42
43 template<typename T> struct Vec2;
44
45 template<typename T> struct Vec3;
46
47 template<typename T> struct Vec4;
48
49 template<typename T> struct Mat4;
50
51
52 // Specializations (only floating types T make sense for the matrix class).
53
55
57
58
59 // forward declaration of matrix multiplication
60 template<typename T> Mat4<T> operator*(const Mat4<T> & A, const Mat4<T> & B);
61
62
63
87 template<typename T> struct Mat4
88 {
89
90 static_assert(std::is_floating_point<T>::value, "The template parameter T of class Mat4<T> must be a floating point number.");
91
92
93 // mtools extension (if available).
94 #if (MTOOLS_TGX_EXTENSIONS)
95 #include <mtools/extensions/tgx/tgx_ext_Mat4.inl>
96 #endif
97
98
114 T M[16];
115
116
120 Mat4() {}
121
122
126 constexpr Mat4(T x1, T y1, T z1, T t1,
127 T x2, T y2, T z2, T t2,
128 T x3, T y3, T z3, T t3,
129 T x4, T y4, T z4, T t4) : M{ x1,x2,x3,x4, y1,y2,y3,y4, z1,z2,z3,z4, t1,t2,t3,t4 }
130 {
131 }
132
133
137 Mat4(const T* mat) { memcpy(M, mat, 16 * sizeof(T)); }
138
139
143 Mat4(const Mat4 & mat) = default;
144
145
149 Mat4& operator=(const Mat4 & mat) = default;
150
151
155 operator T*() { return M; }
156
160 operator const T*() const { return M; }
161
162
166 void setZero()
167 {
168 memset(M, 0, 16 * sizeof(T));
169 }
170
171
176 {
177 memset(M, 0, 16 * sizeof(T));
178 M[0] = M[5] = M[10] = M[15] = ((T)1);
179 }
180
181
191 void setOrtho(T left, T right, T bottom, T top, T zNear, T zFar)
192 {
193 memset(M, 0, 16 * sizeof(T));
194 M[0] = ((T)2) / (right - left);
195 M[5] = ((T)2) / (top - bottom);
196 M[10] = -((T)2) / (zFar - zNear);
197 M[12] = (right + left) / (left - right);
198 M[13] = (top + bottom) / (bottom - top);
199 M[14] = (zFar + zNear) / (zNear - zFar);
200 M[15] = (T)1;
201 }
202
203
213 void setFrustum(T left, T right, T bottom, T top, T zNear, T zFar)
214 {
215 memset(M, 0, 16 * sizeof(T));
216 M[0] = (((T)2) * zNear) / (right - left);
217 M[5] = (((T)2) * zNear) / (top - bottom);
218 M[8] = (right + left) / (right - left);
219 M[9] = (top + bottom) / (top - bottom);
220 M[10] = (zFar + zNear) / (zNear - zFar);
221 M[11] = -((T)1);
222 M[14] = (((T)2) * zFar * zNear) / (zNear - zFar);
223 }
224
225
236 void setPerspective(T fovy, T aspect, T zNear, T zFar)
237 {
238 static const T deg2rad = (T)(M_PI / 180);
239 const T angle = (fovy / ((T)2)) * deg2rad;
240 T aux;
241 if constexpr (std::is_same<T, float>::value)
242 aux = (T)tanf((float)angle);
243 else
244 aux = (T)tan((double)angle);
245 const T top = zNear * aux;
246 const T bottom = -top;
247 const T right = zNear * aspect * aux;
248 const T left = -right;
249 setFrustum(left, right, bottom, top, zNear, zFar);
250 }
251
252
261 void setRotate(T angle, T x, T y, T z)
262 {
263 static const T deg2rad = (T)(M_PI / 180);
264 const T norm = tgx::precise_sqrt(x*x + y*y + z*z);
265 if (norm == 0) { setIdentity(); return; }
266 const T nx = x / norm;
267 const T ny = y / norm;
268 const T nz = z / norm;
269 const T angle_rad = deg2rad * angle;
270 T c, s;
271 if constexpr (std::is_same<T, float>::value)
272 {
273 c = (T)cosf((float)angle_rad);
274 s = (T)sinf((float)angle_rad);
275 }
276 else
277 {
278 c = (T)cos((double)angle_rad);
279 s = (T)sin((double)angle_rad);
280 }
281 const T oneminusc = ((T)1) - c;
282
283 memset(M, 0, 16 * sizeof(T));
284 M[0] = nx * nx * oneminusc + c;
285 M[1] = ny * nx * oneminusc + nz * s;
286 M[2] = nx * nz * oneminusc - ny * s;
287 M[4] = nx * ny * oneminusc - nz * s;
288 M[5] = ny * ny * oneminusc + c;
289 M[6] = ny * nz * oneminusc + nx * s;
290 M[8] = nx * nz * oneminusc + ny * s;
291 M[9] = ny * nz * oneminusc - nx * s;
292 M[10] = nz * nz * oneminusc + c;
293 M[15] = (T)1;
294 }
295
296
305 void setRotate(T angle, const Vec3<T> v)
306 {
307 setRotate(angle, v.x, v.y, v.z);
308 }
309
310
319 void multRotate(T angle, T x, T y, T z)
320 {
321 Mat4 mat;
322 mat.setRotate(angle, x, y, z);
323 *this = (mat * (*this));
324 }
325
326
327
336 void multRotate(T angle, const Vec3<T> v)
337 {
338 multRotate(angle, v.x, v.y, v.z);
339 }
340
341
349 void setTranslate(T x, T y, T z)
350 {
351 memset(M, 0, 16 * sizeof(T));
352 M[0] = (T)1;
353 M[5] = (T)1;
354 M[10] = (T)1;
355 M[12] = x;
356 M[13] = y;
357 M[14] = z;
358 M[15] = (T)1;
359 }
360
361
369 void setTranslate(const Vec3<T> v)
370 {
371 setTranslate(v.x, v.y, v.z);
372 }
373
374
382 void multTranslate(T x, T y, T z)
383 {
384 Mat4 mat;
385 mat.setTranslate(x, y, z);
386 *this = (mat * (*this));
387 }
388
389
397 void multTranslate(const Vec3<T> v)
398 {
399 multTranslate(v.x, v.y, v.z);
400 }
401
402
410 void setScale(T x, T y, T z)
411 {
412 memset(M, 0, 16 * sizeof(T));
413 M[0] = x;
414 M[5] = y;
415 M[10] = z;
416 M[15] = (T)1;
417 }
418
419
427 void setScale(const Vec3<T> v)
428 {
429 setScale(v.x, v.y, v.z);
430 }
431
432
440 void multScale(T x, T y, T z)
441 {
442 Mat4 mat;
443 mat.setScale(x, y, z);
444 *this = (mat * (*this));
445 }
446
447
455 void multScale(const Vec3<T> v)
456 {
457 multScale(v.x, v.y, v.z);
458 }
459
460
465 {
466 M[1] = -M[1];
467 M[5] = -M[5];
468 M[9] = -M[9];
469 M[13] = -M[13];
470 }
471
472
487 void setLookAt(T eyeX, T eyeY, T eyeZ, T centerX, T centerY, T centerZ, T upX, T upY, T upZ)
488 {
489 const Vec4<T> f = normalize(Vec4<T>{ centerX - eyeX, centerY - eyeY, centerZ - eyeZ, (T)0 });
490 Vec4<T> up = normalize(Vec4<T>{ upX, upY, upZ, (T)0 });
491 up = normalize(up - (dotProduct(up, f) * f));
492 const Vec4<T> s = crossProduct(f, up);
493 const Vec4<T> u = crossProduct(s, f);
494 M[0] = s.x; M[4] = s.y; M[8] = s.z; M[12] = -s.x * eyeX - s.y * eyeY - s.z * eyeZ;
495 M[1] = u.x; M[5] = u.y; M[9] = u.z; M[13] = -u.x * eyeX - u.y * eyeY - u.z * eyeZ;
496 M[2] = -f.x; M[6] = -f.y; M[10] = -f.z; M[14] = f.x * eyeX + f.y * eyeY + f.z * eyeZ;
497 M[3] = 0; M[7] = 0; M[11] = 0; M[15] = (T)1;
498 }
499
500
515 void setLookAt(const Vec3<T> eye, const Vec3<T> center, const Vec3<T> up)
516 {
517 setLookAt(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z);
518 }
519
520
524 TGX_INLINE inline Vec4<T> mult(const Vec4<T> V) const
525 {
526 return Vec4<T>{ M[0] * V.x + M[4] * V.y + M[8] * V.z + M[12] * V.w,
527 M[1] * V.x + M[5] * V.y + M[9] * V.z + M[13] * V.w,
528 M[2] * V.x + M[6] * V.y + M[10] * V.z + M[14] * V.w,
529 M[3] * V.x + M[7] * V.y + M[11] * V.z + M[15] * V.w };
530 }
531
532
536 TGX_INLINE inline Vec4<T> mult(const Vec3<T> & V, T w) const
537 {
538#if TGX_USE_FMA_MATH
539 if constexpr (std::is_same<T, float>::value)
540 {
541 return Vec4<T>{ fmaf(M[0], V.x, fmaf(M[4], V.y, fmaf(M[8], V.z, M[12] * w))),
542 fmaf(M[1], V.x, fmaf(M[5], V.y, fmaf(M[9], V.z, M[13] * w))),
543 fmaf(M[2], V.x, fmaf(M[6], V.y, fmaf(M[10], V.z, M[14] * w))),
544 fmaf(M[3], V.x, fmaf(M[7], V.y, fmaf(M[11], V.z, M[15] * w))) };
545 }
546#endif
547 return Vec4<T>{ M[0] * V.x + M[4] * V.y + M[8] * V.z + M[12] * w,
548 M[1] * V.x + M[5] * V.y + M[9] * V.z + M[13] * w,
549 M[2] * V.x + M[6] * V.y + M[10] * V.z + M[14] * w,
550 M[3] * V.x + M[7] * V.y + M[11] * V.z + M[15] * w };
551 }
552
553
557 TGX_INLINE inline Vec4<T> mult0(const Vec3<T> & V) const
558 {
559#if TGX_USE_FMA_MATH
560 if constexpr (std::is_same<T, float>::value)
561 {
562 return Vec4<T>{ fmaf(M[0], V.x, fmaf(M[4], V.y, M[8] * V.z)),
563 fmaf(M[1], V.x, fmaf(M[5], V.y, M[9] * V.z)),
564 fmaf(M[2], V.x, fmaf(M[6], V.y, M[10] * V.z)),
565 fmaf(M[3], V.x, fmaf(M[7], V.y, M[11] * V.z)) };
566 }
567#endif
568 return Vec4<T>{ M[0] * V.x + M[4] * V.y + M[8] * V.z,
569 M[1] * V.x + M[5] * V.y + M[9] * V.z,
570 M[2] * V.x + M[6] * V.y + M[10] * V.z,
571 M[3] * V.x + M[7] * V.y + M[11] * V.z };
572 }
573
574
578 TGX_INLINE inline Vec4<T> mult1(const Vec3<T> & V) const
579 {
580#if TGX_USE_FMA_MATH
581 if constexpr (std::is_same<T, float>::value)
582 {
583 return Vec4<T>{ fmaf(M[0], V.x, fmaf(M[4], V.y, fmaf(M[8], V.z, M[12]))),
584 fmaf(M[1], V.x, fmaf(M[5], V.y, fmaf(M[9], V.z, M[13]))),
585 fmaf(M[2], V.x, fmaf(M[6], V.y, fmaf(M[10], V.z, M[14]))),
586 fmaf(M[3], V.x, fmaf(M[7], V.y, fmaf(M[11], V.z, M[15]))) };
587 }
588#endif
589 return Vec4<T>{ M[0] * V.x + M[4] * V.y + M[8] * V.z + M[12],
590 M[1] * V.x + M[5] * V.y + M[9] * V.z + M[13],
591 M[2] * V.x + M[6] * V.y + M[10] * V.z + M[14],
592 M[3] * V.x + M[7] * V.y + M[11] * V.z + M[15]};
593 }
594
595
596 //
597 // DO NOT DEFINE TO PREVENT ANBIGUITY !
598 // Matrix multiplication : (*this ) = M * (*this)
599 //
600 //
601 //void operator*=(const Mat4 & M)
602 // {
603 // *this = (M * (*this));
604 // }
605
606
610 inline void operator*=(T a)
611 {
612 for (int i = 0; i < 16; i++) { M[i] *= a; }
613 }
614
615
616
620 inline void transpose()
621 {
622 tgx::swap(M[4],M[1]);
623 tgx::swap(M[8],M[2]);
624 tgx::swap(M[12],M[3]);
625 tgx::swap(M[13],M[7]);
626 tgx::swap(M[14],M[11]);
627 tgx::swap(M[9],M[6]);
628 }
629
630
631
632
633
634
635
636
637
638
639
640
641
642#ifdef TGX_ON_ARDUINO
643
644
650 inline void print(Stream & outputStream = Serial) const
651 {
652 outputStream.printf("%.3f \t %.3f \t %.3f \t %.3f\n", M[0],M[4],M[8],M[12]);
653 outputStream.printf("%.3f \t %.3f \t %.3f \t %.3f\n", M[1], M[5], M[9], M[13]);
654 outputStream.printf("%.3f \t %.3f \t %.3f \t %.3f\n", M[2], M[6], M[10], M[14]);
655 outputStream.printf("%.3f \t %.3f \t %.3f \t %.3f\n\n", M[3], M[7], M[11], M[15]);
656 }
657
658#endif
659
660 };
661
662
663
667 template<typename T> TGX_INLINE inline Vec4<T> operator*(const Mat4<T> & M, const Vec4<T> V)
668 {
669#if TGX_USE_FMA_MATH
670 if constexpr (std::is_same<T, float>::value)
671 {
672 return Vec4<T>{ fmaf(M.M[0], V.x, fmaf(M.M[4], V.y, fmaf(M.M[8], V.z, M.M[12] * V.w))),
673 fmaf(M.M[1], V.x, fmaf(M.M[5], V.y, fmaf(M.M[9], V.z, M.M[13] * V.w))),
674 fmaf(M.M[2], V.x, fmaf(M.M[6], V.y, fmaf(M.M[10], V.z, M.M[14] * V.w))),
675 fmaf(M.M[3], V.x, fmaf(M.M[7], V.y, fmaf(M.M[11], V.z, M.M[15] * V.w))) };
676 }
677#endif
678 return Vec4<T>{ M.M[0] * V.x + M.M[4] * V.y + M.M[8] * V.z + M.M[12] * V.w,
679 M.M[1] * V.x + M.M[5] * V.y + M.M[9] * V.z + M.M[13] * V.w,
680 M.M[2] * V.x + M.M[6] * V.y + M.M[10] * V.z + M.M[14] * V.w,
681 M.M[3] * V.x + M.M[7] * V.y + M.M[11] * V.z + M.M[15] * V.w };
682 }
683
684
685
689 template<typename T> inline Mat4<T> operator*(const Mat4<T> & A, const Mat4<T> & B)
690 {
691 Mat4<T> R;
692 for (int i = 0; i < 4; i++)
693 {
694 for (int j = 0; j < 4; j++)
695 {
696 R.M[i + j*4] = (T)0;
697 for (int k = 0; k < 4; k++) { R.M[i + j * 4] += A.M[i + k * 4] * B.M[k + j * 4]; }
698 }
699 }
700 return R;
701 }
702
703
707 template<typename T> inline Mat4<T> operator*(T a, const Mat4<T> & m)
708 {
709 Mat4<T> R(m);
710 for (int i = 0; i < 16; i++) { R.M[i] *= a; }
711 return R;
712 }
713
714
715
716
717
718
719}
720
721#endif
722
723#endif
724
Mat4< T > operator*(const Mat4< T > &A, const Mat4< T > &B)
Matrix-matrix multiplication.
Definition: Mat4.h:689
Utility/miscellaneous functions used throughout the library.
TGX_INLINE void swap(T &a, T &b)
Baby let me swap you one more time...
Definition: Misc.h:145
TGX_INLINE float precise_sqrt(float x)
Compute the square root of a float (exact computation).
Definition: Misc.h:248
#define M_PI
define Pi in case math.h is not yet included.
Definition: Misc.h:79
2D vector.
T crossProduct(const Vec2< T > &U, const Vec2< T > &V)
Return the cross product UxV (i.e.
Definition: Vec2.h:569
T dotProduct(const Vec2< T > U, const Vec2< T > V)
Return the dot product U.V between two vectors.
Definition: Vec2.h:560
Vec2< T > normalize(Vec2< T > V)
Return the vector normalized to have unit norm (do nothing if the vector is 0).
Definition: Vec2.h:459
3D vector.
4D vector.
Generic 4x4 matrix [specializations fMat4, dMat4].
Definition: Mat4.h:88
TGX_INLINE Vec4< T > mult1(const Vec3< T > &V) const
Matrix-vector multiplication (last component of vector set to w = 1)
Definition: Mat4.h:578
void setPerspective(T fovy, T aspect, T zNear, T zFar)
Set as a perspective projection matrix.
Definition: Mat4.h:236
TGX_INLINE Vec4< T > mult0(const Vec3< T > &V) const
Matrix-vector multiplication (last component of vector set to w = 0).
Definition: Mat4.h:557
void multScale(const Vec3< T > v)
Pre-multiply this matrix by a dilatation matrix.
Definition: Mat4.h:455
void transpose()
Transpose the matrix (in place)
Definition: Mat4.h:620
void setTranslate(const Vec3< T > v)
Set as a translation matrix.
Definition: Mat4.h:369
void setScale(T x, T y, T z)
Set as a dilatation matrix.
Definition: Mat4.h:410
void multRotate(T angle, T x, T y, T z)
Pre-multiply this matrix by a rotation matrix.
Definition: Mat4.h:319
TGX_INLINE Vec4< T > mult(const Vec3< T > &V, T w) const
Matrix-vector multiplication.
Definition: Mat4.h:536
void setScale(const Vec3< T > v)
Set as a dilatation matrix.
Definition: Mat4.h:427
void setLookAt(T eyeX, T eyeY, T eyeZ, T centerX, T centerY, T centerZ, T upX, T upY, T upZ)
Set the matrix for a camera looking at a given direction.
Definition: Mat4.h:487
void multRotate(T angle, const Vec3< T > v)
Pre-multiply this matrix by a rotation matrix.
Definition: Mat4.h:336
TGX_INLINE Vec4< T > mult(const Vec4< T > V) const
Matrix-vector multiplication.
Definition: Mat4.h:524
void setZero()
Set as the null matrix (all coefficients equal 0).
Definition: Mat4.h:166
void setTranslate(T x, T y, T z)
Set as a translation matrix.
Definition: Mat4.h:349
void multScale(T x, T y, T z)
Pre-multiply this matrix by a dilatation matrix.
Definition: Mat4.h:440
void setIdentity()
Set as the identity matrix.
Definition: Mat4.h:175
void setRotate(T angle, T x, T y, T z)
Set as a rotation matrix.
Definition: Mat4.h:261
Mat4(const T *mat)
Constructor from an array (with column major ordering same as M).
Definition: Mat4.h:137
void setFrustum(T left, T right, T bottom, T top, T zNear, T zFar)
Set as a perspective projection matrix.
Definition: Mat4.h:213
void multTranslate(T x, T y, T z)
Pre-multiply this matrix by a translation matrix.
Definition: Mat4.h:382
Mat4()
Default constructor.
Definition: Mat4.h:120
void setOrtho(T left, T right, T bottom, T top, T zNear, T zFar)
Set as an orthographic projection matrix.
Definition: Mat4.h:191
void operator*=(T a)
Scalar multiplication.
Definition: Mat4.h:610
void setLookAt(const Vec3< T > eye, const Vec3< T > center, const Vec3< T > up)
Set the matrix for a camera looking at a given direction.
Definition: Mat4.h:515
void multTranslate(const Vec3< T > v)
Pre-multiply this matrix by a translation matrix.
Definition: Mat4.h:397
Mat4 & operator=(const Mat4 &mat)=default
Assignment operator.
void setRotate(T angle, const Vec3< T > v)
Set as a rotation matrix.
Definition: Mat4.h:305
constexpr Mat4(T x1, T y1, T z1, T t1, T x2, T y2, T z2, T t2, T x3, T y3, T z3, T t3, T x4, T y4, T z4, T t4)
Constructor from explicit values.
Definition: Mat4.h:126
void invertYaxis()
invert the y axis, same as multScale({1,-1,1})
Definition: Mat4.h:464
T M[16]
The matrix array in column major ordering:
Definition: Mat4.h:114
Mat4(const Mat4 &mat)=default
Copy constructor.
T x
'x' coordinate (first dimension)
Definition: Vec2.h:72
T y
'y' coordinate (second dimension)
Definition: Vec2.h:73
Generic 3D vector [specializations iVec3, fVec3, dVec3].
Definition: Vec3.h:70
T z
'z' coordinate (third dimension)
Definition: Vec3.h:83
Geenric 4D vector [specializations iVec4, fVec4, dVec4].
Definition: Vec4.h:71
T w
'w' coordinate (fourth dimension)
Definition: Vec4.h:85