Euphoria
mat4.cc
Go to the documentation of this file.
1 #include "base/mat4.h"
2 
3 
4 namespace eu
5 {
6  float* mat4f::get_column_major() { return data; }
7  const float* mat4f::get_column_major() const { return data; }
8 
9  [[nodiscard]]
10  mat4f
12  (
13  float t00, float t01, float t02, float t03,
14  float t10, float t11, float t12, float t13,
15  float t20, float t21, float t22, float t23,
16  float t30, float t31, float t32, float t33
17  )
18  {
19  return
20  {
21  t00, t01, t02, t03,
22  t10, t11, t12, t13,
23  t20, t21, t22, t23,
24  t30, t31, t32, t33
25  };
26  }
27 
28  [[nodiscard]]
29  mat4f
30  mat4f::from_major(const vec4f& major)
31  {
32  const float zero = 0;
33  return from_row_major
34  (
35  major.x, zero, zero, zero,
36  zero, major.y, zero, zero,
37  zero, zero, major.z, zero,
38  zero, zero, zero, major.w
39  );
40  }
41 
42  [[nodiscard]]
43  mat4f
44  mat4f::from_scale(const Scale3f& scale)
45  {
46  return from_major(vec4f(scale));
47  }
48 
49  [[nodiscard]]
50  mat4f
52  {
53  const float one = 1;
54  const float z = 0;
55  return from_row_major
56  (
57  one, z, z, v.x,
58  z, one, z, v.y,
59  z, z, one, v.z,
60  z, z, z, one
61  );
62  }
63 
64  vec4f
65  mat4f::get_transform(const vec4f& p) const
66  {
67  return *this * p;
68  }
69 
70  vec3f
71  mat4f::get_transform(const vec3f& p, float w) const
72  {
73  return get_transform(vec4f{p, w}).to_vec3(w);
74  }
75 
76  vec3f
78  {
79  return get_transform(p, 1);
80  }
81 
82  vec3f
84  {
85  return get_transform(p, 0);
86  }
87 
88  unit3f
90  {
91  return unit3f::to_unit(get_transform_vec(static_cast<vec3f>(p)));
92  }
93 
94  vec3f
96  {
97  return {get(0, 3), get(1, 3), get(2, 3)};
98  }
99 
100  [[nodiscard]]
101  mat4f
103  {
104  const auto c = cos(a);
105  const auto s = sin(a);
106  return from_row_major
107  (
108  1, 0, 0, 0,
109  0, c, -s, 0,
110  0, s, c, 0,
111  0, 0, 0, 1
112  );
113  }
114 
115  mat4f
117  {
118  const auto c = cos(a);
119  const auto s = sin(a);
120  return from_row_major
121  (
122  c, 0, s, 0,
123  0, 1, 0, 0,
124  -s, 0, c, 0,
125  0, 0, 0, 1
126  );
127  }
128 
129  [[nodiscard]]
130  mat4f
132  {
133  const auto c = cos(a);
134  const auto s = sin(a);
135  return from_row_major
136  (
137  c, -s, 0, 0,
138  s, c, 0, 0,
139  0, 0, 1, 0,
140  0, 0, 0, 1
141  );
142  }
143 
144  [[nodiscard]]
145  mat4f
147  {
148  const float rcos = cos(aa.angle);
149  const float rsin = sin(aa.angle);
150 
151  const auto u = aa.axis.x;
152  const auto v = aa.axis.y;
153  const auto w = aa.axis.z;
154 
155  return mat4f::from_col_major
156  (
157  rcos + u * u * (1 - rcos),
158  w * rsin + v * u * (1 - rcos),
159  -v * rsin + w * u * (1 - rcos),
160  0,
161 
162  -w * rsin + u * v * (1 - rcos),
163  rcos + v * v * (1 - rcos),
164  u * rsin + w * v * (1 - rcos),
165  0,
166 
167  v * rsin + u * w * (1 - rcos),
168  -u * rsin + v * w * (1 - rcos),
169  rcos + w * w * (1 - rcos),
170  0,
171 
172  0,
173  0,
174  0,
175  1
176  );
177  }
178 
179 
180  vec4f
182  {
183  return {get(0, 0), get(1, 1), get(2, 2), get(3, 3)};
184  }
185 
186  unit3f
187  mat4f::get_axis(int col) const
188  {
189  return unit3f::to_unit(get_column(col).to_vec3());
190  }
191 
192  unit3f
194  {
195  return get_axis(0);
196  }
197 
198  unit3f
200  {
201  return get_axis(1);
202  }
203 
204  unit3f
206  {
207  return get_axis(2);
208  }
209 
210  mat4f
212  {
213  // https://www.j3d.org/matrix_faq/matrfaq_latest.html
214  return from_col_major
215  (
216  get(0, 0), get(0, 1), get(0, 2), get(0, 3),
217  get(1, 0), get(1, 1), get(1, 2), get(1, 3),
218  get(2, 0), get(2, 1), get(2, 2), get(2, 3),
219  get(3, 0), get(3, 1), get(3, 2), get(3, 3)
220  );
221  }
222 
223  bool
225  {
226  // from the glu source?
227  // https://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix
228 
229  float inv[16];
230 
231  float* m = data;
232 
233  inv[0] =
234  m[5] * m[10] * m[15] - m[5] * m[11] * m[14] -
235  m[9] * m[6] * m[15] + m[9] * m[7] * m[14] +
236  m[13] * m[6] * m[11] - m[13] * m[7] * m[10]
237  ;
238 
239  inv[4] =
240  -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] +
241  m[8] * m[6] * m[15] - m[8] * m[7] * m[14] -
242  m[12] * m[6] * m[11] + m[12] * m[7] * m[10]
243  ;
244 
245  inv[8] =
246  m[4] * m[9] * m[15] - m[4] * m[11] * m[13] -
247  m[8] * m[5] * m[15] + m[8] * m[7] * m[13] +
248  m[12] * m[5] * m[11] - m[12] * m[7] * m[9]
249  ;
250 
251  inv[12] =
252  -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] +
253  m[8] * m[5] * m[14] - m[8] * m[6] * m[13] -
254  m[12] * m[5] * m[10] + m[12] * m[6] * m[9]
255  ;
256 
257  inv[1] =
258  -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] +
259  m[9] * m[2] * m[15] - m[9] * m[3] * m[14] -
260  m[13] * m[2] * m[11] + m[13] * m[3] * m[10]
261  ;
262 
263  inv[5] =
264  m[0] * m[10] * m[15] - m[0] * m[11] * m[14] -
265  m[8] * m[2] * m[15] + m[8] * m[3] * m[14] +
266  m[12] * m[2] * m[11] - m[12] * m[3] * m[10]
267  ;
268 
269  inv[9] =
270  -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] +
271  m[8] * m[1] * m[15] - m[8] * m[3] * m[13] -
272  m[12] * m[1] * m[11] + m[12] * m[3] * m[9]
273  ;
274 
275  inv[13] =
276  m[0] * m[9] * m[14] - m[0] * m[10] * m[13] -
277  m[8] * m[1] * m[14] + m[8] * m[2] * m[13] +
278  m[12] * m[1] * m[10] - m[12] * m[2] * m[9]
279  ;
280 
281  inv[2] =
282  m[1] * m[6] * m[15] - m[1] * m[7] * m[14] -
283  m[5] * m[2] * m[15] + m[5] * m[3] * m[14] +
284  m[13] * m[2] * m[7] - m[13] * m[3] * m[6]
285  ;
286 
287  inv[6] =
288  -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] +
289  m[4] * m[2] * m[15] - m[4] * m[3] * m[14] -
290  m[12] * m[2] * m[7] + m[12] * m[3] * m[6]
291  ;
292 
293  inv[10] =
294  m[0] * m[5] * m[15] - m[0] * m[7] * m[13] -
295  m[4] * m[1] * m[15] + m[4] * m[3] * m[13] +
296  m[12] * m[1] * m[7] - m[12] * m[3] * m[5]
297  ;
298 
299  inv[14] =
300  -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] +
301  m[4] * m[1] * m[14] - m[4] * m[2] * m[13] -
302  m[12] * m[1] * m[6] + m[12] * m[2] * m[5]
303  ;
304 
305  inv[3] =
306  -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] +
307  m[5] * m[2] * m[11] - m[5] * m[3] * m[10] -
308  m[9] * m[2] * m[7] + m[9] * m[3] * m[6]
309  ;
310 
311  inv[7] =
312  m[0] * m[6] * m[11] - m[0] * m[7] * m[10] -
313  m[4] * m[2] * m[11] + m[4] * m[3] * m[10] +
314  m[8] * m[2] * m[7] - m[8] * m[3] * m[6]
315  ;
316 
317  inv[11] =
318  -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] +
319  m[4] * m[1] * m[11] - m[4] * m[3] * m[9] -
320  m[8] * m[1] * m[7] + m[8] * m[3] * m[5]
321  ;
322 
323  inv[15] =
324  m[0] * m[5] * m[10] - m[0] * m[6] * m[9] -
325  m[4] * m[1] * m[10] + m[4] * m[2] * m[9] +
326  m[8] * m[1] * m[6] - m[8] * m[2] * m[5]
327  ;
328 
329  const auto inv_det =
330  m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] +
331  m[3] * inv[12];
332 
333  if(inv_det == 0)
334  {
335  return false;
336  }
337 
338  const auto det = 1.0f / inv_det;
339 
340  for(int index = 0; index < 16; index += 1)
341  {
342  data[index] = inv[index] * det;
343  }
344 
345  return true;
346  }
347 
348  mat4f
350  {
351  auto r = *this;
352  const auto was_inverted = r.invert();
353  ASSERT(was_inverted);
354  return r;
355  }
356 
357  mat3f
359  {
360  return mat3f::from_row_major
361  (
362  get(0, 0), get(0, 1), get(0, 2),
363  get(1, 0), get(1, 1), get(1, 2),
364  get(2, 0), get(2, 1), get(2, 2)
365  );
366  }
367 
368  void
370  {
371 #define OP(i) data[i] += rhs.data[i]
372  OP(0); OP(1); OP(2); OP(3);
373  OP(4); OP(5); OP(6); OP(7);
374  OP(8); OP(9); OP(10); OP(11);
375  OP(12); OP(13); OP(14); OP(15);
376 #undef OP
377  }
378 
379  void
381  {
382 #define OP(i) data[i] -= rhs.data[i]
383  OP(0); OP(1); OP(2); OP(3);
384  OP(4); OP(5); OP(6); OP(7);
385  OP(8); OP(9); OP(10); OP(11);
386  OP(12); OP(13); OP(14); OP(15);
387 #undef OP
388  }
389 
390  [[nodiscard]]
391  mat4f
392  mat4f::create_ortho(float l, float r, float b, float t, float n, float f)
393  {
394  // http://www.songho.ca/opengl/gl_projectionmatrix.html
395  return from_row_major
396  (
397  2 / (r - l), 0, 0, -(r + l) / (r - l),
398  0, 2 / (t - b), 0, -(t + b) / (t - b),
399  0, 0, -2 / (f - n), -(f + n) / (f - n),
400  0, 0, 0, 1
401  );
402  }
403 
404  [[nodiscard]]
405  mat4f
406  mat4f::create_perspective(const Angle& fov, float a, float near, float far)
407  {
408  const float t = 1 / tan(fov / 2);
409  const float zm = far - near;
410  const float zp = far + near;
411  return from_row_major
412  (
413  t / a, 0, 0, 0,
414  0, t, 0, 0,
415  0, 0, -zp / zm, (-2 * far * near) / zm,
416  0, 0, -1, 0
417  );
418  }
419 
420  mat4f
421  mat4f::get_translated(const vec3f& t) const
422  {
423  return *this * from_translation(t);
424  }
425 
426  mat4f
427  mat4f::get_rotated(const AxisAngle& aa) const
428  {
429  return *this * from_axis_angle(aa);
430  }
431 
432  mat4f
433  mat4f::get_scaled(const Scale3f& scale) const
434  {
435  return *this * from_scale(scale);
436  }
437 
438  const float*
440  {
441  return data;
442  }
443 
444  float*
446  {
447  return data;
448  }
449 
450 
451  float
452  mat4f::get(int row, int col) const
453  {
454  return data[col * 4 + row];
455  }
456 
457  vec4f
458  mat4f::get_column(int col) const
459  {
460  const auto base = col * 4;
461  return
462  {
463  data[base + 0],
464  data[base + 1],
465  data[base + 2],
466  data[base + 3]
467  };
468  }
469 
470  vec4f
471  mat4f::get_row(int r) const
472  {
473  return {get(r, 0), get(r, 1), get(r, 2), get(r, 3)};
474  }
475 
476 
477  std::string to_string(const mat4f& m)
478  {
479  return fmt::format("({}, {}. {}. {})", m.get_row(0), m.get_row(1), m.get_row(2), m.get_row(3));
480  }
481 
482 
483  mat4f
484  operator+(const mat4f& lhs, const mat4f& rhs)
485  {
486  mat4f t = lhs;
487  t += rhs;
488  return t;
489  }
490 
491 
492  mat4f
493  operator-(const mat4f& lhs, const mat4f& rhs)
494  {
495  mat4f t = lhs;
496  t -= rhs;
497  return t;
498  }
499 
500  float
501  get_component_multiply_sum(const vec4f& lhs, const vec4f& rhs)
502  {
503  const auto x = lhs.x * rhs.x;
504  const auto y = lhs.y * rhs.y;
505  const auto z = lhs.z * rhs.z;
506  const auto w = lhs.w* rhs.w;
507  return x + y + z + w;
508  }
509 
510  mat4f operator*(const mat4f& lhs, const mat4f& rhs)
511  {
512  const auto op = [&lhs, &rhs](int r, int c) -> float
513  {
514  return get_component_multiply_sum(lhs.get_row(r), rhs.get_column(c));
515  };
516  return mat4f::from_row_major
517  (
518  op(0, 0), op(0, 1), op(0, 2), op(0, 3),
519  op(1, 0), op(1, 1), op(1, 2), op(1, 3),
520  op(2, 0), op(2, 1), op(2, 2), op(2, 3),
521  op(3, 0), op(3, 1), op(3, 2), op(3, 3)
522  );
523  }
524 
525 
526  vec4f operator*(const mat4f& lhs, const vec4f& rhs)
527  {
528  const auto op = [&lhs, &rhs](int r) -> float
529  {
530  return get_component_multiply_sum(lhs.get_row(r), rhs);
531  };
532 
533  return {op(0), op(1), op(2), op(3)};
534  }
535 }
ParserBase * base
Definition: argparse.cc:887
#define ASSERT(x)
Definition: assert.h:29
#define OP(i)
Definition: assert.h:90
Angle operator+(const Angle &lhs, const Angle &rhs)
Definition: angle.cc:123
Angle operator-(const Angle &lhs, const Angle &rhs)
Definition: angle.cc:132
float tan(const Angle &ang)
Definition: angle.cc:75
std::string to_string(const Aabb &a)
Definition: aabb.cc:110
float cos(const Angle &ang)
Definition: angle.cc:68
float sin(const Angle &ang)
Definition: angle.cc:61
Angle operator*(const Angle &lhs, float rhs)
Definition: angle.cc:149
float get_component_multiply_sum(const vec2f &lhs, const vec2f &rhs)
Definition: mat2.cc:131
unit3f axis
a unit-vector
Definition: axisangle.h:13
Angle angle
rotation according to right-hand rule
Definition: axisangle.h:16
Definition: mat3.h:12
constexpr static mat3f from_row_major(float t00, float t10, float t20, float t01, float t11, float t21, float t02, float t12, float t22)
Definition: mat3.h:43
Definition: mat4.h:14
static mat4f from_axis_angle(const AxisAngle &aa)
Definition: mat4.cc:146
mat4f get_translated(const vec3f &t) const
Definition: mat4.cc:421
float * get_data_ptr()
Definition: mat4.cc:445
vec3f get_transform_point(const vec3f &p) const
Definition: mat4.cc:77
void operator+=(const mat4f &rhs)
Definition: mat4.cc:369
unit3f get_z_axis() const
Definition: mat4.cc:205
float * get_column_major()
Definition: mat4.cc:6
mat4f get_rotated(const AxisAngle &aa) const
Definition: mat4.cc:427
mat4f get_scaled(const Scale3f &scale) const
Definition: mat4.cc:433
unit3f get_axis(int col) const
Definition: mat4.cc:187
float get(int row, int col) const
Definition: mat4.cc:452
static mat4f from_major(const vec4f &major)
Definition: mat4.cc:30
static mat4f from_rot_y(const Angle &a)
Definition: mat4.cc:116
static mat4f from_rot_x(const Angle &a)
Definition: mat4.cc:102
static mat4f from_col_major(float t00, float t01, float t02, float t03, float t10, float t11, float t12, float t13, float t20, float t21, float t22, float t23, float t30, float t31, float t32, float t33)
Definition: mat4.cc:12
static mat4f from_scale(const Scale3f &scale)
Definition: mat4.cc:44
mat4f get_inverted() const
Definition: mat4.cc:349
void operator-=(const mat4f &rhs)
Definition: mat4.cc:380
mat3f get_mat3() const
Definition: mat4.cc:358
bool invert()
Definition: mat4.cc:224
vec3f get_transform_vec(const vec3f &p) const
Definition: mat4.cc:83
static mat4f create_perspective(const Angle &fov, float a, float near, float far)
Definition: mat4.cc:406
constexpr static mat4f from_row_major(float t00, float t10, float t20, float t30, float t01, float t11, float t21, float t31, float t02, float t12, float t22, float t32, float t03, float t13, float t23, float t33)
Definition: mat4.h:24
unit3f get_x_axis() const
Definition: mat4.cc:193
vec4f get_column(int c) const
Definition: mat4.cc:458
vec3f get_translation() const
Definition: mat4.cc:95
static mat4f create_ortho(float l, float r, float b, float t, float n, float f)
Definition: mat4.cc:392
unit3f get_y_axis() const
Definition: mat4.cc:199
vec4f get_major() const
Definition: mat4.cc:181
static mat4f from_translation(const vec3f &v)
Definition: mat4.cc:51
mat4f get_transposed() const
Definition: mat4.cc:211
static mat4f from_rot_z(const Angle &a)
Definition: mat4.cc:131
vec4f get_row(int r) const
Definition: mat4.cc:471
vec4f get_transform(const vec4f &p) const
Definition: mat4.cc:65
static unit3f to_unit(float x, float y, float z)
Definition: vec3.cc:192
Definition: vec3.h:48
float x
Definition: vec3.h:49
float y
Definition: vec3.h:50
float z
Definition: vec3.h:51
Definition: vec4.h:14
float w
Definition: vec4.h:18
float x
Definition: vec4.h:15
float y
Definition: vec4.h:16
float z
Definition: vec4.h:17