EHS
Loading...
Searching...
No Matches
Mat4.h
Go to the documentation of this file.
1#pragma once
2
3#include "EHS.h"
4#include "Math.h"
5#include "Mat3.h"
6#include "Vec4.h"
7#include "Vec3.h"
8
9namespace ehs
10{
11 template <typename T = float>
12 class Mat4
13 {
14 private:
15 friend class GpuUniform;
16
17 T data[16];
18
19 public:
21 {
22 for (UInt_8 i = 0; i < 16; ++i)
23 data[i] = 0;
24 }
25
26 explicit Mat4(const T* data)
27 {
28 for (UInt_8 i = 0; i < 16; ++i)
29 this->data[i] = data[i];
30 }
31
32 template<typename C>
33 Mat4(const Mat3<C>& mat)
34 {
35 for (UInt_8 i = 0; i < 9; ++i)
36 {
37 UInt_8 row = i / 3;
38 UInt_8 column = i % 3;
39 UInt_8 dst = row * 4 + column;
40
41 data[dst] = (T)mat[i];
42 }
43
44 data[3] = 0;
45 data[7] = 0;
46 data[11] = 0;
47 data[12] = 0;
48 data[13] = 0;
49 data[14] = 0;
50 data[15] = 1;
51 }
52
53 template<typename C>
54 Mat4(const Mat4<C>& mat)
55 {
56 for (UInt_8 i = 0; i < 16; ++i)
57 data[i] = (T)mat.data[i];
58 }
59
60 template<typename C>
62 {
63 if (this == &mat)
64 return *this;
65
66 for (UInt_8 i = 0; i < 16; ++i)
67 data[i] = (T)mat.data[i];
68
69 return *this;
70 }
71
73 {
74 Vec4<T> result;
75 result.x = vec.x * data[0] + vec.y * data[4] + vec.z * data[8] + vec.w * data[12];
76 result.y = vec.x * data[1] + vec.y * data[5] + vec.z * data[9] + vec.w * data[13];
77 result.z = vec.x * data[2] + vec.y * data[6] + vec.z * data[10] + vec.w * data[14];
78 result.w = vec.x * data[3] + vec.y * data[7] + vec.z * data[11] + vec.w * data[15];
79
80 return result;
81 }
82
83 Mat4<T>& operator*=(const T scalar)
84 {
85 for (UInt_8 i = 0; i < 16; ++i)
86 data[i] *= scalar;
87
88 return *this;
89 }
90
91 Mat4<T> operator*(const T scalar) const
92 {
93 Mat4<T> result;
94 for (UInt_8 i = 0; i < 16; ++i)
95 result.data[i] = data[i] * scalar;
96
97 return result;
98 }
99
101 {
102 Mat4 transposed = GetTranspose();
103
104 for (UInt_8 i = 0; i < 16; i++)
105 {
106 UInt_8 row = i / 4 * 4;
107 UInt_8 column = i % 4 * 4;
108 data[i] += transposed.data[column] * mat.data[row];
109 data[i] += transposed.data[column + 1] * mat.data[row + 1];
110 data[i] += transposed.data[column + 2] * mat.data[row + 2];
111 data[i] += transposed.data[column + 3] * mat.data[row + 3];
112 }
113
114 return *this;
115 }
116
117 Mat4<T> operator*(const Mat4<T>& mat) const
118 {
119 Mat4 transposed = GetTranspose();
120
121 Mat4<T> result;
122 for (UInt_8 i = 0; i < 16; i++)
123 {
124 UInt_8 row = i / 4 * 4;
125 UInt_8 column = i % 4 * 4;
126 result.data[i] += transposed.data[column] * mat.data[row];
127 result.data[i] += transposed.data[column + 1] * mat.data[row + 1];
128 result.data[i] += transposed.data[column + 2] * mat.data[row + 2];
129 result.data[i] += transposed.data[column + 3] * mat.data[row + 3];
130 }
131
132 return result;
133 }
134
135 operator const T*() const
136 {
137 return data;
138 }
139
140 operator T*()
141 {
142 return data;
143 }
144
146 {
147 return Vec3<T>(data[0], data[4], data[8]);
148 }
149
151 {
152 return Vec3<T>(data[1], data[5], data[9]);
153 }
154
156 {
157 return Vec3<T>(data[2], data[6], data[10]);
158 }
159
161 {
162 Mat4<T> result;
163 for (UInt_8 i = 0; i < 16; ++i)
164 result.data[i] = data[i % 4 * 4 + i / 4];
165
166 return result;
167 }
168
170 {
171 Mat4<T> old = *this;
172 for (UInt_8 i = 0; i < 16; ++i)
173 data[i] = old.data[4 * (i % 4) + i / 4];
174 }
175
176 Mat3<T> Cut(const UInt_8 row, const UInt_8 column) const
177 {
178 Mat3<T> result;
179 UInt_8 index = 0;
180
181 for (UInt_8 r = 0; r < 4; ++r)
182 {
183 for (UInt_8 c = 0; c < 4; ++c)
184 {
185 if (r == row || c == column)
186 continue;
187
188 result[index++] = data[4 * r + c];
189 }
190 }
191
192 return result;
193 }
194
196 {
197 Mat4<T> result;
198
199 for (UInt_8 r = 0; r < 4; ++r)
200 for (UInt_8 c = 0; c < 4; ++c)
201 result.data[4 * r + c] = Cut(r, c).GetDeterminant();
202
203 return result;
204 }
205
206 void Minor()
207 {
208 Mat4<T> old = *this;
209
210 for (UInt_8 r = 0; r < 4; ++r)
211 for (UInt_8 c = 0; c < 4; ++c)
212 data[4 * r + c] = old.Cut(r, c).GetDeterminant();
213 }
214
216 {
217 Mat4<T> minor = GetMinor();
218 Mat4<T> result;
219
220 for (UInt_8 r = 0; r < 4; ++r)
221 {
222 for (UInt_8 c = 0; c < 4; ++c)
223 {
224 UInt_8 i = 4 * c + r;
225 result.data[i] = minor.data[i] * Math::Pow<T>(-1, r + c);
226 }
227 }
228
229 return result;
230 }
231
232 void Cofactor()
233 {
234 Mat4<T> minor = GetMinor();
235
236 for (UInt_8 r = 0; r < 4; ++r)
237 {
238 for (UInt_8 c = 0; c < 4; ++c)
239 {
240 UInt_8 i = 4 * c + r;
241 data[i] = minor.data[i] * Math::Pow<T>(-1, r + c);
242 }
243 }
244 }
245
247 {
248 Mat4<T> cofactor = GetCofactor();
249 T result = 0;
250
251 for (UInt_8 c = 0; c < 4; ++c)
252 result += data[c] * cofactor[c];
253
254 return result;
255 }
256
258 {
259 return GetCofactor().GetTranspose();
260 }
261
262 void Adjugate()
263 {
264 Cofactor();
265 Transpose();
266 }
267
269 {
270 T det = GetDeterminant();
271 if (Math::ComCmp(det, 0))
272 return {};
273
274 return GetAdjugate() * (1 / det);
275 }
276
277 void Inverse()
278 {
279 T det = GetDeterminant();
280 if (Math::ComCmp(det, 0))
281 return;
282
283 Adjugate();
284 operator*=(1 / det);
285 }
286
288 {
289 Mat4<T> result;
290 result.data[0] = 1;
291 result.data[5] = 1;
292 result.data[10] = 1;
293 result.data[15] = 1;
294 return result;
295 }
296
297 static Mat4<T> Scale(const Vec3<T>& scale)
298 {
299 Mat4<T> result;
300 result.data[0] = scale.x;
301 result.data[5] = scale.y;
302 result.data[10] = scale.z;
303 result.data[15] = 1;
304
305 return result;
306 }
307
308 static Mat4<T> Translate(const Vec3<T>& pos)
309 {
310 Mat4<T> result = Identity();
311 result.data[12] = pos.x;
312 result.data[13] = pos.y;
313 result.data[14] = pos.z;
314
315 return result;
316 }
317
318 static Mat4<T> PitchRotate(const T angle)
319 {
320 T radians = Math::Rads(angle);
321
322 Mat4<T> result;
323 result.data[0] = 1;
324 result.data[5] = Math::Cos(radians);
325 result.data[6] = Math::Sin(radians);
326 result.data[9] = -Math::Sin(radians);
327 result.data[10] = Math::Cos(radians);
328 result.data[15] = 1;
329
330 return result;
331 }
332
333 static Mat4<T> YawRotate(const T angle)
334 {
335 T radians = Math::Rads<T>(angle);
336
337 Mat4<T> result;
338 result.data[0] = Math::Cos<T>(radians);
339 result.data[2] = -Math::Sin<T>(radians);
340 result.data[5] = 1;
341 result.data[8] = Math::Sin<T>(radians);
342 result.data[10] = Math::Cos<T>(radians);
343 result.data[15] = 1;
344
345 return result;
346 }
347
348 static Mat4<T> RollRotate(const T angle)
349 {
350 T radians = Math::Rads<T>(angle);
351
352 Mat4<T> result;
353 result.data[0] = Math::Cos(radians);
354 result.data[1] = Math::Sin(radians);
355 result.data[4] = -Math::Sin(radians);
356 result.data[5] = Math::Cos(radians);
357 result.data[10] = 1;
358 result.data[15] = 1;
359
360 return result;
361 }
362
363 static Mat4<T> Rotate(const Vec3<T>& vec)
364 {
365 return YawRotate(vec.y) * RollRotate(vec.z) * PitchRotate(vec.x);
366 }
367
368 static Mat4<T> RH_Perspective(const T fov, const T aspect, const T zNear, const T zFar)
369 {
370 const T tanHalfFovy = Math::Tan<T>(Math::Rads(fov) / 2.0f);
371
372 Mat4<T> result;
373 result[0] = 1.0f / (aspect * tanHalfFovy);
374 result[5] = -1.0f / tanHalfFovy;
375 result[10] = zFar / (zFar - zNear);
376 result[14] = -(zFar * zNear) / (zFar - zNear);
377
378 return result;
379 }
380
381 static Mat4<T> LH_Perspective(const T fov, const T aspect, const T zNear, const T zFar)
382 {
383 const T tanHalfFovy = Math::Tan<T>(Math::Rads(fov) / 2.0f);
384
385 Mat4<T> result;
386 result[0] = 1.0f / (aspect * tanHalfFovy);
387 result[5] = -1.0f / tanHalfFovy;
388 result[10] = zFar / (zFar - zNear);
389 result[11] = 1.0f;
390 result[14] = -(zFar * zNear) / (zFar - zNear);
391 result[15] = 0.0f;
392
393 return result;
394 }
395
396 static Mat4<T> LH_Orthographic(const T left, const T right, const T top, const T bottom, const T zNear, const T zFar)
397 {
398 Mat4<T> result;
399 result[0] = 2.0f / (right - left); // 0,0 entry
400 result[5] = 2.0f / (bottom - top); // 1,1 entry
401 result[10] = 1.0f / (zFar - zNear); // 2,2 entry
402 result[12] = -(right + left) / (right - left); // 3,0 entry
403 result[13] = -(bottom + top) / (bottom - top); // 3,1 entry
404 result[14] = -zNear / (zFar - zNear); // 3,2 entry
405 result[15] = 1.0f; // 3,3 entry
406
407 return result;
408
409 /*
410 Mat4<T> result;
411 result.data[0] = 2 / (right - left);
412 result.data[5] = 2 / (top - bottom);
413 result.data[10] = 1 / (zFar - zNear);
414 result.data[12] = (left + right) / (left - right);
415 result.data[13] = (top + bottom) / (bottom - top);
416 result.data[14] = zNear / (zNear - zFar);
417 result.data[15] = 1;
418
419 return result;
420 */
421 }
422 };
423
424 template class EHS_LIB_IO Mat4<float>;
425 template class EHS_LIB_IO Mat4<double>;
426
429}
Definition Mat3.h:11
Definition Mat4.h:13
static Mat4< T > RH_Perspective(const T fov, const T aspect, const T zNear, const T zFar)
Definition Mat4.h:368
static Mat4< T > Rotate(const Vec3< T > &vec)
Definition Mat4.h:363
Vec3< T > GetRight() const
Definition Mat4.h:145
Vec3< T > GetUp() const
Definition Mat4.h:150
Mat4< T > GetMinor() const
Definition Mat4.h:195
Mat4< T > GetInverse() const
Definition Mat4.h:268
friend class GpuUniform
Definition Mat4.h:15
Mat4< T > GetTranspose() const
Definition Mat4.h:160
static Mat4< T > LH_Perspective(const T fov, const T aspect, const T zNear, const T zFar)
Definition Mat4.h:381
static Mat4< T > Identity()
Definition Mat4.h:287
void Cofactor()
Definition Mat4.h:232
Mat4< T > GetCofactor() const
Definition Mat4.h:215
static Mat4< T > RollRotate(const T angle)
Definition Mat4.h:348
static Mat4< T > Scale(const Vec3< T > &scale)
Definition Mat4.h:297
Mat3< T > Cut(const UInt_8 row, const UInt_8 column) const
Definition Mat4.h:176
static Mat4< T > LH_Orthographic(const T left, const T right, const T top, const T bottom, const T zNear, const T zFar)
Definition Mat4.h:396
Mat4(const Mat4< C > &mat)
Definition Mat4.h:54
Vec3< T > GetForward() const
Definition Mat4.h:155
Mat4(const T *data)
Definition Mat4.h:26
Mat4< T > GetAdjugate() const
Definition Mat4.h:257
void Minor()
Definition Mat4.h:206
Mat4< T > & operator*=(const T scalar)
Definition Mat4.h:83
Mat4< T > operator*(const Mat4< T > &mat) const
Definition Mat4.h:117
static Mat4< T > Translate(const Vec3< T > &pos)
Definition Mat4.h:308
Mat4()
Definition Mat4.h:20
Vec4< T > operator*(Vec4< T > vec) const
Definition Mat4.h:72
void Adjugate()
Definition Mat4.h:262
T GetDeterminant() const
Definition Mat4.h:246
static Mat4< T > YawRotate(const T angle)
Definition Mat4.h:333
Mat4< T > & operator=(const Mat4< C > &mat)
Definition Mat4.h:61
Mat4(const Mat3< C > &mat)
Definition Mat4.h:33
Mat4< T > operator*(const T scalar) const
Definition Mat4.h:91
Mat4< T > & operator*=(const Mat4< T > &mat)
Definition Mat4.h:100
static Mat4< T > PitchRotate(const T angle)
Definition Mat4.h:318
void Inverse()
Definition Mat4.h:277
void Transpose()
Definition Mat4.h:169
static T Pow(const T base, const I exponent)
Definition Math.h:173
static T Rads(const T from)
Definition Math.h:89
static R Sin(const R angle, const R precision=0.001)
Definition Math.h:257
static R Cos(const R angle, const R precision=0.001)
Definition Math.h:298
static R Tan(const R angle, const R precision=0.001)
Definition Math.h:334
static bool ComCmp(float a, float b)
Combined absolute and relative tolerance comparison for single precision floats.
Definition Math.cpp:26
Definition Vec3.h:14
T x
Definition Vec3.h:16
T z
Definition Vec3.h:18
T y
Definition Vec3.h:17
Definition Vec4.h:15
T z
Definition Vec4.h:19
T y
Definition Vec4.h:18
T x
Definition Vec4.h:17
T w
Definition Vec4.h:20
Definition Anchor.h:6
unsigned char UInt_8
Definition Types.h:43
Mat4< double > Mat4_d
Definition Mat4.h:428
Mat4< float > Mat4_f
Definition Mat4.h:427