philsupertramp/game-math
Loading...
Searching...
No Matches
mat4.h
Go to the documentation of this file.
1#pragma once
2
3#include "../vec/vec4.h"
4#include "mat3.h"
5
10template<class T>
11struct mat4 {
12public:
14 T values[4][4];
15
19 mat4() {
20 // clang-format off
21 values[0][0] = static_cast<T>(0); values[0][1] = static_cast<T>(0); values[0][2] = static_cast<T>(0); values[0][3] = static_cast<T>(0);
22 values[1][0] = static_cast<T>(0); values[1][1] = static_cast<T>(0); values[1][2] = static_cast<T>(0); values[1][3] = static_cast<T>(0);
23 values[2][0] = static_cast<T>(0); values[2][1] = static_cast<T>(0); values[2][2] = static_cast<T>(0); values[2][3] = static_cast<T>(0);
24 values[3][0] = static_cast<T>(0); values[3][1] = static_cast<T>(0); values[3][2] = static_cast<T>(0); values[3][3] = static_cast<T>(0); // clang-format on
25 }
26
27 // clang-format off
47 mat4(const T& _a, const T& _b, const T& _c, const T& _d,
48 const T& _e, const T& _f, const T& _g, const T& _h,
49 const T& _i, const T& _j, const T& _k, const T& _l,
50 const T& _m, const T& _n, const T& _o, const T& _p)
51 {
52 values[0][0] = _a; values[0][1] = _b; values[0][2] = _c; values[0][3] = _d;
53 values[1][0] = _e; values[1][1] = _f; values[1][2] = _g; values[1][3] = _h;
54 values[2][0] = _i; values[2][1] = _j; values[2][2] = _k; values[2][3] = _l;
55 values[3][0] = _m; values[3][1] = _n; values[3][2] = _o; values[3][3] = _p; // clang-format on
56 }
57
65 mat4(const vec4<T>& A, const vec4<T>& B, const vec4<T>& C, const vec4<T>& D) {
66 // clang-format off
67 values[0][0] = A.x; values[0][1] = A.y; values[0][2] = A.z; values[0][3] = A.w;
68 values[1][0] = B.x; values[1][1] = B.y; values[1][2] = B.z; values[1][3] = B.w;
69 values[2][0] = C.x; values[2][1] = C.y; values[2][2] = C.z; values[2][3] = C.w;
70 values[3][0] = D.x; values[3][1] = D.y; values[3][2] = D.z; values[3][3] = D.w; // clang-format on
71 }
72
77 explicit mat4(const T& _a) {
78 // clang-format off
79 values[0][0] = _a; values[0][1] = static_cast<T>(0); values[0][2] = static_cast<T>(0); values[0][3] = static_cast<T>(0);
80 values[1][0] = static_cast<T>(0); values[1][1] = _a; values[1][2] = static_cast<T>(0); values[1][3] = static_cast<T>(0);
81 values[2][0] = static_cast<T>(0); values[2][1] = static_cast<T>(0); values[2][2] = _a; values[2][3] = static_cast<T>(0);
82 values[3][0] = static_cast<T>(0); values[3][1] = static_cast<T>(0); values[3][2] = static_cast<T>(0); values[3][3] = _a; // clang-format on
83 }
84
88 ~mat4() = default;
89
94 static inline mat4<T> Unit() {
95 return mat4<T>( // clang-format off
96 static_cast<T>(1), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0),
97 static_cast<T>(0), static_cast<T>(1), static_cast<T>(0), static_cast<T>(0),
98 static_cast<T>(0), static_cast<T>(0), static_cast<T>(1), static_cast<T>(0),
99 static_cast<T>(0), static_cast<T>(0), static_cast<T>(0), static_cast<T>(1)); // clang-format on
100 }
101
107 static inline mat4<T> Transformation(const mat3<T>& m) {
108 return mat4<T>( // clang-format off
109 m[0][0], m[0][1], m[0][2], static_cast<T>(0),
110 m[1][0], m[1][1], m[1][2], static_cast<T>(0),
111 m[2][0], m[2][1], m[2][2], static_cast<T>(0),
112 static_cast<T>(0), static_cast<T>(0), static_cast<T>(0), static_cast<T>(1)); // clang-format on
113 }
114
120 return mat4<T>( // clang-format off
121 values[0][0], values[1][0], values[2][0], values[3][0],
122 values[0][1], values[1][1], values[2][1], values[3][1],
123 values[0][2], values[1][2], values[2][2], values[3][2],
124 values[0][3], values[1][3], values[2][3], values[3][3]); // clang-format on
125 }
126
131 inline bool IsSymmetric() {
132 return values[0][1] == values[1][0] && values[0][2] == values[2][0] && values[0][3] == values[3][0]
133 && values[2][1] == values[1][2] && values[1][3] == values[3][1] && values[3][2] == values[2][3];
134 }
135
140 inline float Determinant() {
141 return // clang-format off
142 values[2][0] * mat3<T>(values[0][1], values[0][2], values[0][3], values[1][1], values[1][2], values[1][3], values[2][1], values[2][2], values[2][3]).Determinant()
143 - values[2][1] * mat3<T>(values[0][0], values[0][2], values[0][3], values[1][0], values[1][2], values[1][3], values[3][0], values[3][2], values[3][3]).Determinant()
144 + values[2][2] * mat3<T>(values[0][0], values[0][1], values[0][3], values[1][0], values[1][1], values[1][3], values[3][0], values[3][1], values[3][3]).Determinant()
145 - values[2][3] * mat3<T>(values[0][0], values[0][1], values[0][2], values[1][0], values[1][1], values[1][2], values[3][0], values[3][1], values[3][2]).Determinant(); // clang-format on
146 }
147
155 inline mat3<T> getMinor(const size_t& i, const size_t& j) {
156 mat3<T> out;
157 for(size_t row = 0; row < 4; ++row) {
158 for(size_t col = 0; col < 4; ++col) {
159 if(row != i && col != j) out[row][col];
160 }
161 }
162 return out;
163 }
164
169 inline mat4 Inverse() {
170 T SubFactor00 = values[2][2] * values[3][3] - values[3][2] * values[2][3];
171 T SubFactor01 = values[2][1] * values[3][3] - values[3][1] * values[2][3];
172 T SubFactor02 = values[2][1] * values[3][2] - values[3][1] * values[2][2];
173 T SubFactor03 = values[2][0] * values[3][3] - values[3][0] * values[2][3];
174 T SubFactor04 = values[2][0] * values[3][2] - values[3][0] * values[2][2];
175 T SubFactor05 = values[2][0] * values[3][1] - values[3][0] * values[2][1];
176 T SubFactor06 = values[1][2] * values[3][3] - values[3][2] * values[1][3];
177 T SubFactor07 = values[1][1] * values[3][3] - values[3][1] * values[1][3];
178 T SubFactor08 = values[1][1] * values[3][2] - values[3][1] * values[1][2];
179 T SubFactor09 = values[1][0] * values[3][3] - values[3][0] * values[1][3];
180 T SubFactor10 = values[1][0] * values[3][2] - values[3][0] * values[1][2];
181 T SubFactor11 = values[1][0] * values[3][1] - values[3][0] * values[1][1];
182 T SubFactor12 = values[1][2] * values[2][3] - values[2][2] * values[1][3];
183 T SubFactor13 = values[1][1] * values[2][3] - values[2][1] * values[1][3];
184 T SubFactor14 = values[1][1] * values[2][2] - values[2][1] * values[1][2];
185 T SubFactor15 = values[1][0] * values[2][3] - values[2][0] * values[1][3];
186 T SubFactor16 = values[1][0] * values[2][2] - values[2][0] * values[1][2];
187 T SubFactor17 = values[1][0] * values[2][1] - values[2][0] * values[1][1];
188
190 Inverse[0][0] = +(values[1][1] * SubFactor00 - values[1][2] * SubFactor01 + values[1][3] * SubFactor02);
191 Inverse[0][1] = -(values[1][0] * SubFactor00 - values[1][2] * SubFactor03 + values[1][3] * SubFactor04);
192 Inverse[0][2] = +(values[1][0] * SubFactor01 - values[1][1] * SubFactor03 + values[1][3] * SubFactor05);
193 Inverse[0][3] = -(values[1][0] * SubFactor02 - values[1][1] * SubFactor04 + values[1][2] * SubFactor05);
194
195 Inverse[1][0] = -(values[0][1] * SubFactor00 - values[0][2] * SubFactor01 + values[0][3] * SubFactor02);
196 Inverse[1][1] = +(values[0][0] * SubFactor00 - values[0][2] * SubFactor03 + values[0][3] * SubFactor04);
197 Inverse[1][2] = -(values[0][0] * SubFactor01 - values[0][1] * SubFactor03 + values[0][3] * SubFactor05);
198 Inverse[1][3] = +(values[0][0] * SubFactor02 - values[0][1] * SubFactor04 + values[0][2] * SubFactor05);
199
200 Inverse[2][0] = +(values[0][1] * SubFactor06 - values[0][2] * SubFactor07 + values[0][3] * SubFactor08);
201 Inverse[2][1] = -(values[0][0] * SubFactor06 - values[0][2] * SubFactor09 + values[0][3] * SubFactor10);
202 Inverse[2][2] = +(values[0][0] * SubFactor07 - values[0][1] * SubFactor09 + values[0][3] * SubFactor11);
203 Inverse[2][3] = -(values[0][0] * SubFactor08 - values[0][1] * SubFactor10 + values[0][2] * SubFactor11);
204
205 Inverse[3][0] = -(values[0][1] * SubFactor12 - values[0][2] * SubFactor13 + values[0][3] * SubFactor14);
206 Inverse[3][1] = +(values[0][0] * SubFactor12 - values[0][2] * SubFactor15 + values[0][3] * SubFactor16);
207 Inverse[3][2] = -(values[0][0] * SubFactor13 - values[0][1] * SubFactor15 + values[0][3] * SubFactor17);
208 Inverse[3][3] = +(values[0][0] * SubFactor14 - values[0][1] * SubFactor16 + values[0][2] * SubFactor17);
209
210 T Determinant = +values[0][0] * Inverse[0][0] + values[0][1] * Inverse[0][1] + values[0][2] * Inverse[0][2]
211 + values[0][3] * Inverse[0][3];
212
214
215 return Inverse;
216 }
217
224 friend mat4<T> operator+(mat4<T> lhs, const mat4<T>& rhs) { return lhs += rhs; }
231 friend mat4<T> operator-(mat4<T> lhs, const mat4<T>& rhs) { return lhs -= rhs; }
238 friend mat4<T> operator*(mat4<T> lhs, const T& rhs) { return lhs *= rhs; }
239
246 friend vec4<T> operator*(mat4<T> lhs, const vec4<T>& rhs) {
247 return vec4<T>( // clang-format off
248 lhs[0][0] * rhs.x + lhs[0][1] * rhs.y + lhs[0][2] * rhs.z + lhs[0][3] * rhs.w,
249 lhs[1][0] * rhs.x + lhs[1][1] * rhs.y + lhs[1][2] * rhs.z + lhs[1][3] * rhs.w,
250 lhs[2][0] * rhs.x + lhs[2][1] * rhs.y + lhs[2][2] * rhs.z + lhs[2][3] * rhs.w,
251 lhs[3][0] * rhs.x + lhs[3][1] * rhs.y + lhs[3][2] * rhs.z + lhs[3][3] * rhs.w
252 ); // clang-format on
253 }
254
261 friend mat4<T> operator*(mat4<T> lhs, const mat4<T>& rhs) { return lhs *= rhs; }
262
269 friend mat4<T> operator/(mat4<T> lhs, const T& rhs) { return lhs /= rhs; }
270
271 /* compound assignment */
278 // clang-format off
279 values[0][0] += rhs[0][0]; values[0][1] += rhs[0][1]; values[0][2] += rhs[0][2]; values[0][3] += rhs[0][3];
280 values[1][0] += rhs[1][0]; values[1][1] += rhs[1][1]; values[1][2] += rhs[1][2]; values[1][3] += rhs[1][3];
281 values[2][0] += rhs[2][0]; values[2][1] += rhs[2][1]; values[2][2] += rhs[2][2]; values[2][3] += rhs[2][3];
282 values[3][0] += rhs[3][0]; values[3][1] += rhs[3][1]; values[3][2] += rhs[3][2]; values[3][3] += rhs[3][3]; // clang-format on
283 return *this;
284 }
285
292 // clang-format off
293 values[0][0] -= rhs[0][0]; values[0][1] -= rhs[0][1]; values[0][2] -= rhs[0][2]; values[0][3] -= rhs[0][3];
294 values[1][0] -= rhs[1][0]; values[1][1] -= rhs[1][1]; values[1][2] -= rhs[1][2]; values[1][3] -= rhs[1][3];
295 values[2][0] -= rhs[2][0]; values[2][1] -= rhs[2][1]; values[2][2] -= rhs[2][2]; values[2][3] -= rhs[2][3];
296 values[3][0] -= rhs[3][0]; values[3][1] -= rhs[3][1]; values[3][2] -= rhs[3][2]; values[3][3] -= rhs[3][3]; // clang-format on
297 return *this;
298 }
299
306 // clang-format off
307 T _a = values[0][0], _b = values[0][1], _c = values[0][2], _d = values[0][3],
308 _e = values[1][0], _f = values[1][1], _g = values[1][2], _h = values[1][3],
309 _i = values[2][0], _j = values[2][1], _k = values[2][2], _l = values[2][3],
310 _m = values[3][0], _n = values[3][1], _o = values[3][2], _p = values[3][3];
311
312 values[0][0] = _a * rhs[0][0] + _b*rhs[1][0] + _c * rhs[2][0] + _d*rhs[3][0];
313 values[0][1] = _a * rhs[0][1] + _b*rhs[1][1] + _c * rhs[2][1] + _d*rhs[3][1];
314 values[0][2] = _a * rhs[0][2] + _b*rhs[1][2] + _c * rhs[2][2] + _d*rhs[3][2];
315 values[0][3] = _a * rhs[0][3] + _b*rhs[1][3] + _c * rhs[2][3] + _d*rhs[3][3];
316
317 values[1][0] = _e * rhs[0][0] + _f*rhs[1][0] + _g * rhs[2][0] + _h*rhs[3][0];
318 values[1][1] = _e * rhs[0][1] + _f*rhs[1][1] + _g * rhs[2][1] + _h*rhs[3][1];
319 values[1][2] = _e * rhs[0][2] + _f*rhs[1][2] + _g * rhs[2][2] + _h*rhs[3][2];
320 values[1][3] = _e * rhs[0][3] + _f*rhs[1][3] + _g * rhs[2][3] + _h*rhs[3][3];
321
322 values[2][0] = _i * rhs[0][0] + _j*rhs[1][0] + _k * rhs[2][0] + _l*rhs[3][0];
323 values[2][1] = _i * rhs[0][1] + _j*rhs[1][1] + _k * rhs[2][1] + _l*rhs[3][1];
324 values[2][2] = _i * rhs[0][2] + _j*rhs[1][2] + _k * rhs[2][2] + _l*rhs[3][2];
325 values[2][3] = _i * rhs[0][3] + _j*rhs[1][3] + _k * rhs[2][3] + _l*rhs[3][3];
326
327 values[3][0] = _m * rhs[0][0] + _n*rhs[1][0] + _o * rhs[2][0] + _p*rhs[3][0];
328 values[3][1] = _m * rhs[0][1] + _n*rhs[1][1] + _o * rhs[2][1] + _p*rhs[3][1];
329 values[3][2] = _m * rhs[0][2] + _n*rhs[1][2] + _o * rhs[2][2] + _p*rhs[3][2];
330 values[3][3] = _m * rhs[0][3] + _n*rhs[1][3] + _o * rhs[2][3] + _p*rhs[3][3]; // clang-format on
331 return *this;
332 }
333
339 mat4<T>& operator*=(const T& rhs) {
340 // clang-format off
341 values[0][0]*=rhs; values[0][1]*=rhs; values[0][2]*=rhs; values[0][3]*=rhs;
342 values[1][0]*=rhs; values[1][1]*=rhs; values[1][2]*=rhs; values[1][3]*=rhs;
343 values[2][0]*=rhs; values[2][1]*=rhs; values[2][2]*=rhs; values[2][3]*=rhs;
344 values[3][0]*=rhs; values[3][1]*=rhs; values[3][2]*=rhs; values[3][3]*=rhs; // clang-format on
345 return *this;
346 }
347
353 mat4<T>& operator/=(const T& rhs) {
354 // clang-format off
355 values[0][0] /= rhs; values[0][1] /= rhs; values[0][2] /= rhs; values[0][3] /= rhs;
356 values[1][0] /= rhs; values[1][1] /= rhs; values[1][2] /= rhs; values[1][3] /= rhs;
357 values[2][0] /= rhs; values[2][1] /= rhs; values[2][2] /= rhs; values[2][3] /= rhs;
358 values[3][0] /= rhs; values[3][1] /= rhs; values[3][2] /= rhs; values[3][3] /= rhs; // clang-format on
359 return *this;
360 }
361
367 bool operator==(const mat4<T>& rhs) {
368 // clang-format off
369 return (
370 values[0][0] == rhs[0][0] && values[0][1] == rhs[0][1] && values[0][2] == rhs[0][2] && values[0][3] == rhs[0][3] &&
371 values[1][0] == rhs[1][0] && values[1][1] == rhs[1][1] && values[1][2] == rhs[1][2] && values[1][3] == rhs[1][3] &&
372 values[2][0] == rhs[2][0] && values[2][1] == rhs[2][1] && values[2][2] == rhs[2][2] && values[2][3] == rhs[2][3] &&
373 values[3][0] == rhs[3][0] && values[3][1] == rhs[3][1] && values[3][2] == rhs[3][2] && values[3][3] == rhs[3][3]); // clang-format on
374 }
380 bool operator!=(const mat4<T>& rhs) { return !(*this == rhs); }
381
382 /* Member access */
388 T* operator[](int index) { return values[index]; }
394 const T* operator[](int index) const { return values[index]; }
395
396 /* stream operators */
402 template<class U>
403 friend std::ostream& operator<<(std::ostream&, const mat4<U>&);
404};
405
406template<class U>
407std::ostream& operator<<(std::ostream& out, const mat4<U>& mat) {
408 out.precision(17);
409 out << "[\n\t" // clang-format off
410 << mat[0][0] << ", " << mat[0][1] << ", " << mat[0][2] << ", " << mat[0][3] << ";\n\t"
411 << mat[1][0] << ", " << mat[1][1] << ", " << mat[1][2] << ", " << mat[1][3] << ";\n\t"
412 << mat[2][0] << ", " << mat[2][1] << ", " << mat[2][2] << ", " << mat[2][3] << ";\n\t"
413 << mat[3][0] << ", " << mat[3][1] << ", " << mat[3][2] << ", " << mat[3][3] << "\n]\n"; // clang-format on
414 return out;
415}
416
std::ostream & operator<<(std::ostream &out, const mat4< U > &mat)
Definition: mat4.h:407
Definition: mat3.h:10
float Determinant()
Definition: mat3.h:125
Definition: mat4.h:11
mat4< T > & operator+=(const mat4< T > &rhs)
Definition: mat4.h:277
friend vec4< T > operator*(mat4< T > lhs, const vec4< T > &rhs)
Definition: mat4.h:246
mat4< T > & operator*=(const mat4< T > &rhs)
Definition: mat4.h:305
mat4()
Definition: mat4.h:19
mat4< T > & operator/=(const T &rhs)
Definition: mat4.h:353
mat4< T > & operator-=(const mat4< T > &rhs)
Definition: mat4.h:291
bool operator==(const mat4< T > &rhs)
Definition: mat4.h:367
static mat4< T > Transformation(const mat3< T > &m)
Definition: mat4.h:107
friend mat4< T > operator/(mat4< T > lhs, const T &rhs)
Definition: mat4.h:269
T values[4][4]
loosely packed data
Definition: mat4.h:14
friend mat4< T > operator*(mat4< T > lhs, const mat4< T > &rhs)
Definition: mat4.h:261
friend mat4< T > operator*(mat4< T > lhs, const T &rhs)
Definition: mat4.h:238
bool IsSymmetric()
Definition: mat4.h:131
mat4 Inverse()
Definition: mat4.h:169
mat4< T > & operator*=(const T &rhs)
Definition: mat4.h:339
float Determinant()
Definition: mat4.h:140
const T * operator[](int index) const
Definition: mat4.h:394
bool operator!=(const mat4< T > &rhs)
Definition: mat4.h:380
mat4< T > Transpose()
Definition: mat4.h:119
T * operator[](int index)
Definition: mat4.h:388
mat3< T > getMinor(const size_t &i, const size_t &j)
Definition: mat4.h:155
friend std::ostream & operator<<(std::ostream &, const mat4< U > &)
Definition: mat4.h:407
mat4(const T &_a)
Definition: mat4.h:77
friend mat4< T > operator-(mat4< T > lhs, const mat4< T > &rhs)
Definition: mat4.h:231
friend mat4< T > operator+(mat4< T > lhs, const mat4< T > &rhs)
Definition: mat4.h:224
~mat4()=default
static mat4< T > Unit()
Definition: mat4.h:94
mat4(const T &_a, const T &_b, const T &_c, const T &_d, const T &_e, const T &_f, const T &_g, const T &_h, const T &_i, const T &_j, const T &_k, const T &_l, const T &_m, const T &_n, const T &_o, const T &_p)
Definition: mat4.h:47
mat4(const vec4< T > &A, const vec4< T > &B, const vec4< T > &C, const vec4< T > &D)
Definition: mat4.h:65
Definition: vec4.h:11
T w
Definition: vec4.h:29
T y
Definition: vec4.h:29
T z
Definition: vec4.h:29
T x
Definition: vec4.h:29