diff options
Diffstat (limited to 'include/math/mat4.h')
-rw-r--r-- | include/math/mat4.h | 162 |
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 ] |
23 | static inline mat4 mat4_make(R m00, R m01, R m02, R m03, R m10, R m11, R m12, | 23 | static 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. |
75 | static inline mat4 mat4_id() { | 75 | static 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. |
81 | static inline mat4 mat4_from_vec4(vec4 v0, vec4 v1, vec4 v2, vec4 v3) { | 82 | static 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. |
87 | static inline mat4 mat4_from_vec3(vec3 right, vec3 up, vec3 forward, | 89 | static 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. |
213 | static inline mat4 mat4_translation(mat4 m) { | 216 | static 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. |
220 | static inline mat4 mat4_rotation(mat4 m) { | 223 | static 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. |
249 | static inline mat4 mat4_rot(vec3 axis, R angle) { | 253 | static 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. |
303 | static inline mat4 mat4_lookat(vec3 position, vec3 target, vec3 up) { | 308 | static 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) { | |||
346 | static inline mat4 mat4_perspective_inverse(R fovy, R aspect, R near, R far) { | 354 | static 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. |
358 | static inline R mat4_det(mat4 m) { | 366 | static 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. |
475 | static inline bool mat4_eq(mat4 m, mat4 w, float eps) { | 484 | static 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 | } |