| TGX 1.0.8 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
38 namespace 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
54 typedef Mat4<float> fMat4;
55
56 typedef Mat4<double> dMat4;
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
157
161 void setZero()
162 {
163 memset(M, 0, 16 * sizeof(T));
164 }
165
166
170 void setIdentity()
171 {
172 memset(M, 0, 16 * sizeof(T));
173 M[0] = M[5] = M[10] = M[15] = ((T)1);
174 }
175
176
186 void setOrtho(T left, T right, T bottom, T top, T zNear, T zFar)
187 {
188 memset(M, 0, 16 * sizeof(T));
189 M[0] = ((T)2) / (right - left);
190 M[5] = ((T)2) / (top - bottom);
191 M[10] = -((T)2) / (zFar - zNear);
192 M[12] = (right + left) / (left - right);
193 M[13] = (top + bottom) / (bottom - top);
194 M[14] = (zFar + zNear) / (zNear - zFar);
195 M[15] = (T)1;
196 }
197
198
208 void setFrustum(T left, T right, T bottom, T top, T zNear, T zFar)
209 {
210 memset(M, 0, 16 * sizeof(T));
211 M[0] = (((T)2) * zNear) / (right - left);
212 M[5] = (((T)2) * zNear) / (top - bottom);
213 M[8] = (right + left) / (right - left);
214 M[9] = (top + bottom) / (top - bottom);
215 M[10] = (zFar + zNear) / (zNear - zFar);
216 M[11] = -((T)1);
217 M[14] = (((T)2) * zFar * zNear) / (zNear - zFar);
218 }
219
220
231 void setPerspective(T fovy, T aspect, T zNear, T zFar)
232 {
233 static const T deg2rad = (T)(M_PI / 180);
234 const T aux = tan((fovy / ((T)2)) * deg2rad);
235 const T top = zNear * aux;
236 const T bottom = -top;
237 const T right = zNear * aspect * aux;
238 const T left = -right;
239 setFrustum(left, right, bottom, top, zNear, zFar);
240 }
241
242
251 void setRotate(T angle, T x, T y, T z)
252 {
253 static const T deg2rad = (T)(M_PI / 180);
254 const T norm = tgx::precise_sqrt(x*x + y*y + z*z);
255 if (norm == 0) { setIdentity(); return; }
256 const T nx = x / norm;
257 const T ny = y / norm;
258 const T nz = z / norm;
259 const T c = cos(deg2rad * angle);
260 const T oneminusc = ((T)1) - c;
261 const T s = sin(deg2rad * angle);
262
263 memset(M, 0, 16 * sizeof(T));
264 M[0] = nx * nx * oneminusc + c;
265 M[1] = ny * nx * oneminusc + nz * s;
266 M[2] = nx * nz * oneminusc - ny * s;
267 M[4] = nx * ny * oneminusc - nz * s;
268 M[5] = ny * ny * oneminusc + c;
269 M[6] = ny * nz * oneminusc + nx * s;
270 M[8] = nx * nz * oneminusc + ny * s;
271 M[9] = ny * nz * oneminusc - nx * s;
272 M[10] = nz * nz * oneminusc + c;
273 M[15] = (T)1;
274 }
275
276
285 void setRotate(T angle, const Vec3<T> v)
286 {
287 setRotate(angle, v.x, v.y, v.z);
288 }
289
290
299 void multRotate(T angle, T x, T y, T z)
300 {
301 Mat4 mat;
302 mat.setRotate(angle, x, y, z);
303 *this = (mat * (*this));
304 }
305
306
307
316 void multRotate(T angle, const Vec3<T> v)
317 {
318 multRotate(angle, v.x, v.y, v.z);
319 }
320
321
329 void setTranslate(T x, T y, T z)
330 {
331 memset(M, 0, 16 * sizeof(T));
332 M[0] = (T)1;
333 M[5] = (T)1;
334 M[10] = (T)1;
335 M[12] = x;
336 M[13] = y;
337 M[14] = z;
338 M[15] = (T)1;
339 }
340
341
349 void setTranslate(const Vec3<T> v)
350 {
351 setTranslate(v.x, v.y, v.z);
352 }
353
354
362 void multTranslate(T x, T y, T z)
363 {
364 Mat4 mat;
365 mat.setTranslate(x, y, z);
366 *this = (mat * (*this));
367 }
368
369
377 void multTranslate(const Vec3<T> v)
378 {
379 multTranslate(v.x, v.y, v.z);
380 }
381
382
390 void setScale(T x, T y, T z)
391 {
392 memset(M, 0, 16 * sizeof(T));
393 M[0] = x;
394 M[5] = y;
395 M[10] = z;
396 M[15] = (T)1;
397 }
398
399
407 void setScale(const Vec3<T> v)
408 {
409 setScale(v.x, v.y, v.z);
410 }
411
412
420 void multScale(T x, T y, T z)
421 {
422 Mat4 mat;
423 mat.setScale(x, y, z);
424 *this = (mat * (*this));
425 }
426
427
435 void multScale(const Vec3<T> v)
436 {
437 multScale(v.x, v.y, v.z);
438 }
439
440
444 void invertYaxis()
445 {
446 M[4] = -M[4];
447 M[5] = -M[5];
448 M[6] = -M[6];
449 M[7] = -M[7];
450 }
451
452
467 void setLookAt(T eyeX, T eyeY, T eyeZ, T centerX, T centerY, T centerZ, T upX, T upY, T upZ)
468 {
469 const Vec4<T> f = normalize(Vec4<T>{ centerX - eyeX, centerY - eyeY, centerZ - eyeZ, (T)0 });
470 Vec4<T> up = normalize(Vec4<T>{ upX, upY, upZ, (T)0 });
471 up = normalize(up - (dotProduct(up, f) * f));
472 const Vec4<T> s = crossProduct(f, up);
473 const Vec4<T> u = crossProduct(s, f);
474 M[0] = s.x; M[4] = s.y; M[8] = s.z; M[12] = -s.x * eyeX - s.y * eyeY - s.z * eyeZ;
475 M[1] = u.x; M[5] = u.y; M[9] = u.z; M[13] = -u.x * eyeX - u.y * eyeY - u.z * eyeZ;
476 M[2] = -f.x; M[6] = -f.y; M[10] = -f.z; M[14] = f.x * eyeX + f.y * eyeY + f.z * eyeZ;
477 M[3] = 0; M[7] = 0; M[11] = 0; M[15] = (T)1;
478 }
479
480
495 void setLookAt(const Vec3<T> eye, const Vec3<T> center, const Vec3<T> up)
496 {
497 setLookAt(eye.x, eye.y, eye.z, center.x, center.y, center.z, up.x, up.y, up.z);
498 }
499
500
504 TGX_INLINE inline Vec4<T> mult(const Vec4<T> V) const
505 {
506 return Vec4<T>{ M[0] * V.x + M[4] * V.y + M[8] * V.z + M[12] * V.w,
507 M[1] * V.x + M[5] * V.y + M[9] * V.z + M[13] * V.w,
508 M[2] * V.x + M[6] * V.y + M[10] * V.z + M[14] * V.w,
509 M[3] * V.x + M[7] * V.y + M[11] * V.z + M[15] * V.w };
510 }
511
512
516 TGX_INLINE inline Vec4<T> mult(const Vec3<T> & V, float w) const
517 {
518 return Vec4<T>{ M[0] * V.x + M[4] * V.y + M[8] * V.z + M[12] * w,
519 M[1] * V.x + M[5] * V.y + M[9] * V.z + M[13] * w,
520 M[2] * V.x + M[6] * V.y + M[10] * V.z + M[14] * w,
521 M[3] * V.x + M[7] * V.y + M[11] * V.z + M[15] * w };
522 }
523
524
528 TGX_INLINE inline Vec4<T> mult0(const Vec3<T> & V) const
529 {
530 return Vec4<T>{ M[0] * V.x + M[4] * V.y + M[8] * V.z,
531 M[1] * V.x + M[5] * V.y + M[9] * V.z,
532 M[2] * V.x + M[6] * V.y + M[10] * V.z,
533 M[3] * V.x + M[7] * V.y + M[11] * V.z };
534 }
535
536
540 TGX_INLINE inline Vec4<T> mult1(const Vec3<T> & V) const
541 {
542 return Vec4<T>{ M[0] * V.x + M[4] * V.y + M[8] * V.z + M[12],
543 M[1] * V.x + M[5] * V.y + M[9] * V.z + M[13],
544 M[2] * V.x + M[6] * V.y + M[10] * V.z + M[14],
545 M[3] * V.x + M[7] * V.y + M[11] * V.z + M[15]};
546 }
547
548
549 //
550 // DO NOT DEFINE TO PREVENT ANBIGUITY !
551 // Matrix multiplication : (*this ) = M * (*this)
552 //
553 //
554 //void operator*=(const Mat4 & M)
555 // {
556 // *this = (M * (*this));
557 // }
558
559
563 inline void operator*=(T a)
564 {
565 for (int i = 0; i < 16; i++) { M[i] *= a; }
566 }
567
568
569
573 inline void transpose()
574 {
575 tgx::swap(M[4],M[1]);
576 tgx::swap(M[8],M[2]);
577 tgx::swap(M[12],M[3]);
578 tgx::swap(M[13],M[7]);
579 tgx::swap(M[14],M[11]);
580 tgx::swap(M[9],M[6]);
581 }
582
583
584
585
586
587
588
589
590
591
592
593
594
595#ifdef TGX_ON_ARDUINO
596
597
603 inline void print(Stream & outputStream = Serial) const
604 {
605 outputStream.printf("%.3f \t %.3f \t %.3f \t %.3f\n", M[0],M[4],M[8],M[12]);
606 outputStream.printf("%.3f \t %.3f \t %.3f \t %.3f\n", M[1], M[5], M[9], M[13]);
607 outputStream.printf("%.3f \t %.3f \t %.3f \t %.3f\n", M[2], M[6], M[10], M[14]);
608 outputStream.printf("%.3f \t %.3f \t %.3f \t %.3f\n\n", M[3], M[7], M[11], M[15]);
609 }
610
611#endif
612
613 };
614
615
616
620 template<typename T> TGX_INLINE inline Vec4<T> operator*(const Mat4<T> & M, const Vec4<T> V)
621 {
622 return Vec4<T>{ M.M[0] * V.x + M.M[4] * V.y + M.M[8] * V.z + M.M[12] * V.w,
623 M.M[1] * V.x + M.M[5] * V.y + M.M[9] * V.z + M.M[13] * V.w,
624 M.M[2] * V.x + M.M[6] * V.y + M.M[10] * V.z + M.M[14] * V.w,
625 M.M[3] * V.x + M.M[7] * V.y + M.M[11] * V.z + M.M[15] * V.w };
626 }
627
628
629
633 template<typename T> inline Mat4<T> operator*(const Mat4<T> & A, const Mat4<T> & B)
634 {
635 Mat4<T> R;
636 for (int i = 0; i < 4; i++)
637 {
638 for (int j = 0; j < 4; j++)
639 {
640 R.M[i + j*4] = (T)0;
641 for (int k = 0; k < 4; k++) { R.M[i + j * 4] += A.M[i + k * 4] * B.M[k + j * 4]; }
642 }
643 }
644 return R;
645 }
646
647
651 template<typename T> inline Mat4<T> operator*(T a, const Mat4<T> & m)
652 {
653 Mat4<T> R(m);
654 for (int i = 0; i < 16; i++) { R.M[i] *= a; }
655 return R;
656 }
657
658
659
660
661
662
663}
664
665#endif
666
667#endif
668
tgx::operator*
Mat4< T > operator*(const Mat4< T > &A, const Mat4< T > &B)
Matrix-matrix multiplication.
Definition: Mat4.h:633
Misc.h
Utility/miscellaneous functions used throughout the library.
tgx::swap
TGX_INLINE void swap(T &a, T &b)
Baby let me swap you one more time...
Definition: Misc.h:128
tgx::precise_sqrt
TGX_INLINE float precise_sqrt(float x)
Compute the square root of a float (exact computation).
Definition: Misc.h:231
M_PI
#define M_PI
define Pi in case math.h is not yet included.
Definition: Misc.h:62
Vec2.h
2D vector.
tgx::crossProduct
T crossProduct(const Vec2< T > &U, const Vec2< T > &V)
Return the cross product UxV (i.e.
Definition: Vec2.h:569
tgx::dotProduct
T dotProduct(const Vec2< T > U, const Vec2< T > V)
Return the dot product U.V between two vectors.
Definition: Vec2.h:560
tgx::normalize
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
Vec3.h
3D vector.
Vec4.h
4D vector.
tgx::Mat4
Generic 4x4 matrix [specializations fMat4, dMat4].
Definition: Mat4.h:88
tgx::Mat4::mult1
TGX_INLINE Vec4< T > mult1(const Vec3< T > &V) const
Matrix-vector multiplication (last component of vector set to w = 1)
Definition: Mat4.h:540
tgx::Mat4::setPerspective
void setPerspective(T fovy, T aspect, T zNear, T zFar)
Set as a perspective projection matrix.
Definition: Mat4.h:231
tgx::Mat4::mult0
TGX_INLINE Vec4< T > mult0(const Vec3< T > &V) const
Matrix-vector multiplication (last component of vector set to w = 0).
Definition: Mat4.h:528
tgx::Mat4::multScale
void multScale(const Vec3< T > v)
Pre-multiply this matrix by a dilatation matrix.
Definition: Mat4.h:435
tgx::Mat4::transpose
void transpose()
Transpose the matrix (in place)
Definition: Mat4.h:573
tgx::Mat4::setTranslate
void setTranslate(const Vec3< T > v)
Set as a translation matrix.
Definition: Mat4.h:349
tgx::Mat4::setScale
void setScale(T x, T y, T z)
Set as a dilatation matrix.
Definition: Mat4.h:390
tgx::Mat4::multRotate
void multRotate(T angle, T x, T y, T z)
Pre-multiply this matrix by a rotation matrix.
Definition: Mat4.h:299
tgx::Mat4::setScale
void setScale(const Vec3< T > v)
Set as a dilatation matrix.
Definition: Mat4.h:407
tgx::Mat4::setLookAt
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:467
tgx::Mat4::multRotate
void multRotate(T angle, const Vec3< T > v)
Pre-multiply this matrix by a rotation matrix.
Definition: Mat4.h:316
tgx::Mat4::mult
TGX_INLINE Vec4< T > mult(const Vec4< T > V) const
Matrix-vector multiplication.
Definition: Mat4.h:504
tgx::Mat4::setZero
void setZero()
Set as the null matrix (all coefficients equal 0).
Definition: Mat4.h:161
tgx::Mat4::mult
TGX_INLINE Vec4< T > mult(const Vec3< T > &V, float w) const
Matrix-vector multiplication.
Definition: Mat4.h:516
tgx::Mat4::setTranslate
void setTranslate(T x, T y, T z)
Set as a translation matrix.
Definition: Mat4.h:329
tgx::Mat4::multScale
void multScale(T x, T y, T z)
Pre-multiply this matrix by a dilatation matrix.
Definition: Mat4.h:420
tgx::Mat4::setIdentity
void setIdentity()
Set as the identity matrix.
Definition: Mat4.h:170
tgx::Mat4::setRotate
void setRotate(T angle, T x, T y, T z)
Set as a rotation matrix.
Definition: Mat4.h:251
tgx::Mat4::Mat4
Mat4(const T *mat)
Constructor from an array (with column major ordering same as M).
Definition: Mat4.h:137
tgx::Mat4::setFrustum
void setFrustum(T left, T right, T bottom, T top, T zNear, T zFar)
Set as a perspective projection matrix.
Definition: Mat4.h:208
tgx::Mat4::multTranslate
void multTranslate(T x, T y, T z)
Pre-multiply this matrix by a translation matrix.
Definition: Mat4.h:362
tgx::Mat4::Mat4
Mat4()
Default constructor.
Definition: Mat4.h:120
tgx::Mat4::setOrtho
void setOrtho(T left, T right, T bottom, T top, T zNear, T zFar)
Set as an orthographic projection matrix.
Definition: Mat4.h:186
tgx::Mat4::operator*=
void operator*=(T a)
Scalar multiplication.
Definition: Mat4.h:563
tgx::Mat4::setLookAt
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:495
tgx::Mat4::multTranslate
void multTranslate(const Vec3< T > v)
Pre-multiply this matrix by a translation matrix.
Definition: Mat4.h:377
tgx::Mat4::operator=
Mat4 & operator=(const Mat4 &mat)=default
Assignement operator.
tgx::Mat4::setRotate
void setRotate(T angle, const Vec3< T > v)
Set as a rotation matrix.
Definition: Mat4.h:285
tgx::Mat4::Mat4
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
tgx::Mat4::invertYaxis
void invertYaxis()
invert the y axis, same as multScale({1,-1,1})
Definition: Mat4.h:444
tgx::Mat4::M
T M[16]
The matrix array in column major ordering:
Definition: Mat4.h:114
tgx::Mat4::Mat4
Mat4(const Mat4 &mat)=default
Copy constructor.
tgx::Vec2::x
T x
'x' coordinate (first dimension)
Definition: Vec2.h:72
tgx::Vec2::y
T y
'y' coordinate (second dimension)
Definition: Vec2.h:73
tgx::Vec3
Generic 3D vector [specializations iVec3, fVec3, dVec3].
Definition: Vec3.h:70
tgx::Vec3::z
T z
'z' coordinate (third dimension)
Definition: Vec3.h:83
tgx::Vec4
Geenric 4D vector [specializations iVec4, fVec4, dVec4].
Definition: Vec4.h:71
tgx::Vec4::w
T w
'w' coordinate (fourth dimension)
Definition: Vec4.h:85