aboutsummaryrefslogtreecommitdiff
path: root/include/math/mat4.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/math/mat4.h')
-rw-r--r--include/math/mat4.h162
1 files changed, 86 insertions, 76 deletions
diff --git a/include/math/mat4.h b/include/math/mat4.h
index 3ceb75b..e808d73 100644
--- a/include/math/mat4.h
+++ b/include/math/mat4.h
@@ -20,9 +20,9 @@ typedef struct mat4 {
20/// [ m10 m11 m12 m13 ] 20/// [ m10 m11 m12 m13 ]
21/// [ m20 m21 m22 m23 ] 21/// [ m20 m21 m22 m23 ]
22/// [ m30 m31 m32 m33 ] 22/// [ m30 m31 m32 m33 ]
23static inline mat4 mat4_make(R m00, R m01, R m02, R m03, R m10, R m11, R m12, 23static inline mat4 mat4_make(
24 R m13, R m20, R m21, R m22, R m23, R m30, R m31, 24 R m00, R m01, R m02, R m03, R m10, R m11, R m12, R m13, R m20, R m21, R m22,
25 R m32, R m33) { 25 R m23, R m30, R m31, R m32, R m33) {
26 mat4 m; 26 mat4 m;
27 m.val[0][0] = m00; 27 m.val[0][0] = m00;
28 m.val[0][1] = m10; 28 m.val[0][1] = m10;
@@ -73,22 +73,24 @@ static inline mat4 mat4_from_array(const R M[16]) {
73 73
74/// Construct the identity matrix. 74/// Construct the identity matrix.
75static inline mat4 mat4_id() { 75static inline mat4 mat4_id() {
76 return mat4_make(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 76 return mat4_make(
77 0.0, 0.0, 0.0, 1.0); 77 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
78 1.0);
78} 79}
79 80
80/// Construct a matrix from 4 column vectors. 81/// Construct a matrix from 4 column vectors.
81static inline mat4 mat4_from_vec4(vec4 v0, vec4 v1, vec4 v2, vec4 v3) { 82static inline mat4 mat4_from_vec4(vec4 v0, vec4 v1, vec4 v2, vec4 v3) {
82 return mat4_make(v0.x, v0.y, v0.z, v0.w, v1.x, v1.y, v1.z, v1.w, v2.x, v2.y, 83 return mat4_make(
83 v2.z, v2.w, v3.x, v3.y, v3.z, v3.w); 84 v0.x, v0.y, v0.z, v0.w, v1.x, v1.y, v1.z, v1.w, v2.x, v2.y, v2.z, v2.w,
85 v3.x, v3.y, v3.z, v3.w);
84} 86}
85 87
86/// Construct a transformation matrix from 4 vectors. 88/// Construct a transformation matrix from 4 vectors.
87static inline mat4 mat4_from_vec3(vec3 right, vec3 up, vec3 forward, 89static inline mat4 mat4_from_vec3(
88 vec3 position) { 90 vec3 right, vec3 up, vec3 forward, vec3 position) {
89 return mat4_make(right.x, right.y, right.z, 0.0, up.x, up.y, up.z, 0.0, 91 return mat4_make(
90 forward.x, forward.y, forward.z, 0.0, position.x, position.y, 92 right.x, right.y, right.z, 0.0, up.x, up.y, up.z, 0.0, forward.x,
91 position.z, 1.0); 93 forward.y, forward.z, 0.0, position.x, position.y, position.z, 1.0);
92} 94}
93 95
94/// Return the value at the specified position. 96/// Return the value at the specified position.
@@ -205,23 +207,25 @@ static inline mat4 mat4_mul(mat4 A, mat4 B) {
205 mat4_at(A, 3, 2) * mat4_at(B, 2, 3) + 207 mat4_at(A, 3, 2) * mat4_at(B, 2, 3) +
206 mat4_at(A, 3, 3) * mat4_at(B, 3, 3); 208 mat4_at(A, 3, 3) * mat4_at(B, 3, 3);
207 209
208 return mat4_make(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, 210 return mat4_make(
209 m30, m31, m32, m33); 211 m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32,
212 m33);
210} 213}
211 214
212/// Return the translation component of the matrix. 215/// Return the translation component of the matrix.
213static inline mat4 mat4_translation(mat4 m) { 216static inline mat4 mat4_translation(mat4 m) {
214 return mat4_make(1.0, 0.0, 0.0, mat4_at(m, 0, 3), 0.0, 1.0, 0.0, 217 return mat4_make(
215 mat4_at(m, 1, 3), 0.0, 0.0, 1.0, mat4_at(m, 2, 3), 0.0, 0.0, 218 1.0, 0.0, 0.0, mat4_at(m, 0, 3), 0.0, 1.0, 0.0, mat4_at(m, 1, 3), 0.0,
216 0.0, 1.0); 219 0.0, 1.0, mat4_at(m, 2, 3), 0.0, 0.0, 0.0, 1.0);
217} 220}
218 221
219/// Return the rotation component of the matrix. 222/// Return the rotation component of the matrix.
220static inline mat4 mat4_rotation(mat4 m) { 223static inline mat4 mat4_rotation(mat4 m) {
221 return mat4_make(mat4_at(m, 0, 0), mat4_at(m, 0, 1), mat4_at(m, 0, 2), 0.0, 224 return mat4_make(
222 mat4_at(m, 1, 0), mat4_at(m, 1, 1), mat4_at(m, 1, 2), 0.0, 225 mat4_at(m, 0, 0), mat4_at(m, 0, 1), mat4_at(m, 0, 2), 0.0,
223 mat4_at(m, 2, 0), mat4_at(m, 2, 1), mat4_at(m, 2, 2), 0.0, 226 mat4_at(m, 1, 0), mat4_at(m, 1, 1), mat4_at(m, 1, 2), 0.0,
224 0.0, 0.0, 0.0, 1.0); 227 mat4_at(m, 2, 0), mat4_at(m, 2, 1), mat4_at(m, 2, 2), 0.0, 0.0, 0.0, 0.0,
228 1.0);
225} 229}
226 230
227/// Create an X-axis rotation matrix. 231/// Create an X-axis rotation matrix.
@@ -247,22 +251,22 @@ static inline mat4 mat4_rotz(R angle) {
247 251
248/// Create a rotation matrix. 252/// Create a rotation matrix.
249static inline mat4 mat4_rot(vec3 axis, R angle) { 253static inline mat4 mat4_rot(vec3 axis, R angle) {
250 const R s = sin(angle); 254 const R s = sin(angle);
251 const R c = cos(angle); 255 const R c = cos(angle);
252 const R x = axis.x; 256 const R x = axis.x;
253 const R y = axis.y; 257 const R y = axis.y;
254 const R z = axis.z; 258 const R z = axis.z;
255 const R xy = x * y; 259 const R xy = x * y;
256 const R xz = x * z; 260 const R xz = x * z;
257 const R yz = y * z; 261 const R yz = y * z;
258 const R sx = s * x; 262 const R sx = s * x;
259 const R sy = s * y; 263 const R sy = s * y;
260 const R sz = s * z; 264 const R sz = s * z;
261 const R omc = 1.0 - c; 265 const R omc = 1.0 - c;
262 return mat4_make(c + omc * x * x, omc * xy - sz, omc * xz + sy, 0, 266 return mat4_make(
263 omc * xy + sz, c + omc * y * y, omc * yz - sx, 0, 267 c + omc * x * x, omc * xy - sz, omc * xz + sy, 0, omc * xy + sz,
264 omc * xz - sy, omc * yz + sx, c + omc * z * z, 0, 0, 0, 0, 268 c + omc * y * y, omc * yz - sx, 0, omc * xz - sy, omc * yz + sx,
265 1); 269 c + omc * z * z, 0, 0, 0, 0, 1);
266} 270}
267 271
268/// Create a scaling matrix. 272/// Create a scaling matrix.
@@ -295,15 +299,16 @@ static inline mat4 mat4_from_forward(vec3 forward) {
295 const vec3 f = vec3_normalize(forward); 299 const vec3 f = vec3_normalize(forward);
296 const vec3 r = vec3_normalize(vec3_cross(f, up3())); 300 const vec3 r = vec3_normalize(vec3_cross(f, up3()));
297 const vec3 u = vec3_normalize(vec3_cross(r, f)); 301 const vec3 u = vec3_normalize(vec3_cross(r, f));
298 return mat4_make(r.x, u.x, -f.x, 0.0, r.y, u.y, -f.y, 0.0, r.z, u.z, -f.z, 302 return mat4_make(
299 0.0, 0.0, 0.0, 0.0, 1.0); 303 r.x, u.x, -f.x, 0.0, r.y, u.y, -f.y, 0.0, r.z, u.z, -f.z, 0.0, 0.0, 0.0,
304 0.0, 1.0);
300} 305}
301 306
302/// Create a transformation matrix. 307/// Create a transformation matrix.
303static inline mat4 mat4_lookat(vec3 position, vec3 target, vec3 up) { 308static inline mat4 mat4_lookat(vec3 position, vec3 target, vec3 up) {
304 const vec3 fwd = vec3_normalize(vec3_sub(target, position)); 309 const vec3 fwd = vec3_normalize(vec3_sub(target, position));
305 const vec3 right = vec3_normalize(vec3_cross(fwd, up)); 310 const vec3 right = vec3_normalize(vec3_cross(fwd, up));
306 up = vec3_normalize(vec3_cross(right, fwd)); 311 up = vec3_normalize(vec3_cross(right, fwd));
307 return mat4_from_vec3(right, up, fwd, position); 312 return mat4_from_vec3(right, up, fwd, position);
308} 313}
309 314
@@ -318,8 +323,9 @@ static inline mat4 mat4_ortho(R left, R right, R bottom, R top, R near, R far) {
318 const R tx = -(right + left) / (right - left); 323 const R tx = -(right + left) / (right - left);
319 const R ty = -(top + bottom) / (top - bottom); 324 const R ty = -(top + bottom) / (top - bottom);
320 const R tz = -(far + near) / (far - near); 325 const R tz = -(far + near) / (far - near);
321 return mat4_make(2 / (right - left), 0, 0, tx, 0, 2 / (top - bottom), 0, ty, 326 return mat4_make(
322 0, 0, -2 / (far - near), tz, 0, 0, 0, 1); 327 2 / (right - left), 0, 0, tx, 0, 2 / (top - bottom), 0, ty, 0, 0,
328 -2 / (far - near), tz, 0, 0, 0, 1);
323} 329}
324 330
325/// Create a perspective projection matrix. 331/// Create a perspective projection matrix.
@@ -332,9 +338,11 @@ static inline mat4 mat4_perspective(R fovy, R aspect, R near, R far) {
332 R f = tan(fovy / 2.0); 338 R f = tan(fovy / 2.0);
333 assert(f > 0.0); 339 assert(f > 0.0);
334 f = 1.0 / f; 340 f = 1.0 / f;
341
335 const R a = near - far; 342 const R a = near - far;
336 return mat4_make(f / aspect, 0, 0, 0, 0, f, 0, 0, 0, 0, (far + near) / a, 343 return mat4_make(
337 (2 * far * near / a), 0, 0, -1, 0); 344 f / aspect, 0, 0, 0, 0, f, 0, 0, 0, 0, (far + near) / a,
345 (2 * far * near / a), 0, 0, -1, 0);
338} 346}
339 347
340/// Create the inverse of a perspective projection matrix. 348/// Create the inverse of a perspective projection matrix.
@@ -346,18 +354,18 @@ static inline mat4 mat4_perspective(R fovy, R aspect, R near, R far) {
346static inline mat4 mat4_perspective_inverse(R fovy, R aspect, R near, R far) { 354static inline mat4 mat4_perspective_inverse(R fovy, R aspect, R near, R far) {
347 R f = tan(fovy / 2.0); 355 R f = tan(fovy / 2.0);
348 assert(f > 0.0); 356 assert(f > 0.0);
349 f = 1.0 / f; 357 f = 1.0 / f;
350 const R a = far * near; 358 const R a = far * near;
351 const R P32 = 0.5 * (near - far) / a; 359 const R P32 = 0.5 * (near - far) / a;
352 const R P33 = 0.5 * (far + near) / a; 360 const R P33 = 0.5 * (far + near) / a;
353 return mat4_make(aspect / f, 0, 0, 0, 0, 1.0f / f, 0, 0, 0, 0, 0, -1, 0, 0, 361 return mat4_make(
354 P32, P33); 362 aspect / f, 0, 0, 0, 0, 1.0f / f, 0, 0, 0, 0, 0, -1, 0, 0, P32, P33);
355} 363}
356 364
357/// Return the matrix's determinant. 365/// Return the matrix's determinant.
358static inline R mat4_det(mat4 m) { 366static inline R mat4_det(mat4 m) {
359 const R* M = (const R*)(m.val); 367 const R* M = (const R*)(m.val);
360 const R inv0 = M[5] * M[10] * M[15] - M[5] * M[11] * M[14] - 368 const R inv0 = M[5] * M[10] * M[15] - M[5] * M[11] * M[14] -
361 M[9] * M[6] * M[15] + M[9] * M[7] * M[14] + 369 M[9] * M[6] * M[15] + M[9] * M[7] * M[14] +
362 M[13] * M[6] * M[11] - M[13] * M[7] * M[10]; 370 M[13] * M[6] * M[11] - M[13] * M[7] * M[10];
363 const R inv1 = -M[4] * M[10] * M[15] + M[4] * M[11] * M[14] + 371 const R inv1 = -M[4] * M[10] * M[15] + M[4] * M[11] * M[14] +
@@ -413,10 +421,11 @@ static inline mat4 mat4_inverse(mat4 m) {
413 R det = M[0] * inv[0] + M[1] * inv[4] + M[2] * inv[8] + M[3] * inv[12]; 421 R det = M[0] * inv[0] + M[1] * inv[4] + M[2] * inv[8] + M[3] * inv[12];
414 assert(det != 0.0); 422 assert(det != 0.0);
415 det = 1.0 / det; 423 det = 1.0 / det;
416 return mat4_make(inv[0] * det, inv[4] * det, inv[8] * det, inv[12] * det, 424 return mat4_make(
417 inv[1] * det, inv[5] * det, inv[9] * det, inv[13] * det, 425 inv[0] * det, inv[4] * det, inv[8] * det, inv[12] * det, inv[1] * det,
418 inv[2] * det, inv[6] * det, inv[10] * det, inv[14] * det, 426 inv[5] * det, inv[9] * det, inv[13] * det, inv[2] * det, inv[6] * det,
419 inv[3] * det, inv[7] * det, inv[11] * det, inv[15] * det); 427 inv[10] * det, inv[14] * det, inv[3] * det, inv[7] * det, inv[11] * det,
428 inv[15] * det);
420} 429}
421 430
422/// Invert the transformation matrix. 431/// Invert the transformation matrix.
@@ -428,9 +437,9 @@ static inline mat4 mat4_inverse_transform(mat4 m) {
428 const vec3 u = mat4_v1(m); 437 const vec3 u = mat4_v1(m);
429 const vec3 f = mat4_v2(m); 438 const vec3 f = mat4_v2(m);
430 const vec3 t = mat4_v3(m); 439 const vec3 t = mat4_v3(m);
431 return mat4_make(r.x, r.y, r.z, -vec3_dot(r, t), u.x, u.y, u.z, 440 return mat4_make(
432 -vec3_dot(u, t), f.x, f.y, f.z, -vec3_dot(f, t), 0.0, 0.0, 441 r.x, r.y, r.z, -vec3_dot(r, t), u.x, u.y, u.z, -vec3_dot(u, t), f.x, f.y,
433 0.0, 1.0); 442 f.z, -vec3_dot(f, t), 0.0, 0.0, 0.0, 1.0);
434} 443}
435 444
436/// Transpose the matrix. 445/// Transpose the matrix.
@@ -473,23 +482,24 @@ static inline vec4 mat4_mul_vec4(mat4 m, vec4 v) {
473/// within |eps|, false if there is at least one ij-value difference that is 482/// within |eps|, false if there is at least one ij-value difference that is
474/// greater than eps. 483/// greater than eps.
475static inline bool mat4_eq(mat4 m, mat4 w, float eps) { 484static inline bool mat4_eq(mat4 m, mat4 w, float eps) {
476 return (float_eq(mat4_at(m, 0, 0), mat4_at(w, 0, 0), eps) && 485 return (
477 float_eq(mat4_at(m, 0, 1), mat4_at(w, 0, 1), eps) && 486 float_eq(mat4_at(m, 0, 0), mat4_at(w, 0, 0), eps) &&
478 float_eq(mat4_at(m, 0, 2), mat4_at(w, 0, 2), eps) && 487 float_eq(mat4_at(m, 0, 1), mat4_at(w, 0, 1), eps) &&
479 float_eq(mat4_at(m, 0, 3), mat4_at(w, 0, 3), eps) && 488 float_eq(mat4_at(m, 0, 2), mat4_at(w, 0, 2), eps) &&
480 489 float_eq(mat4_at(m, 0, 3), mat4_at(w, 0, 3), eps) &&
481 float_eq(mat4_at(m, 1, 0), mat4_at(w, 1, 0), eps) && 490
482 float_eq(mat4_at(m, 1, 1), mat4_at(w, 1, 1), eps) && 491 float_eq(mat4_at(m, 1, 0), mat4_at(w, 1, 0), eps) &&
483 float_eq(mat4_at(m, 1, 2), mat4_at(w, 1, 2), eps) && 492 float_eq(mat4_at(m, 1, 1), mat4_at(w, 1, 1), eps) &&
484 float_eq(mat4_at(m, 1, 3), mat4_at(w, 1, 3), eps) && 493 float_eq(mat4_at(m, 1, 2), mat4_at(w, 1, 2), eps) &&
485 494 float_eq(mat4_at(m, 1, 3), mat4_at(w, 1, 3), eps) &&
486 float_eq(mat4_at(m, 2, 0), mat4_at(w, 2, 0), eps) && 495
487 float_eq(mat4_at(m, 2, 1), mat4_at(w, 2, 1), eps) && 496 float_eq(mat4_at(m, 2, 0), mat4_at(w, 2, 0), eps) &&
488 float_eq(mat4_at(m, 2, 2), mat4_at(w, 2, 2), eps) && 497 float_eq(mat4_at(m, 2, 1), mat4_at(w, 2, 1), eps) &&
489 float_eq(mat4_at(m, 2, 3), mat4_at(w, 2, 3), eps) && 498 float_eq(mat4_at(m, 2, 2), mat4_at(w, 2, 2), eps) &&
490 499 float_eq(mat4_at(m, 2, 3), mat4_at(w, 2, 3), eps) &&
491 float_eq(mat4_at(m, 3, 0), mat4_at(w, 3, 0), eps) && 500
492 float_eq(mat4_at(m, 3, 1), mat4_at(w, 3, 1), eps) && 501 float_eq(mat4_at(m, 3, 0), mat4_at(w, 3, 0), eps) &&
493 float_eq(mat4_at(m, 3, 2), mat4_at(w, 3, 2), eps) && 502 float_eq(mat4_at(m, 3, 1), mat4_at(w, 3, 1), eps) &&
494 float_eq(mat4_at(m, 3, 3), mat4_at(w, 3, 3), eps)); 503 float_eq(mat4_at(m, 3, 2), mat4_at(w, 3, 2), eps) &&
504 float_eq(mat4_at(m, 3, 3), mat4_at(w, 3, 3), eps));
495} 505}