#include "linear_alg.h" #include vec3_t vec3_add(vec3_t v, vec3_t u) { return (vec3_t) { v.x + u.x, v.y + u.y, v.z + u.z }; } vec3_t vec3_sub(vec3_t v, vec3_t u) { return (vec3_t) { v.x - u.x, v.y - u.y, v.z - u.z }; } vec3_t vec3_scale(float s, vec3_t v) { return (vec3_t) { s * v.x, s * v.y, s * v.z }; } float vec3_len(vec3_t v) { return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); } vec3_t vec3_norm(vec3_t v) { const float l = vec3_len(v); return vec3_scale(1 / l, v); } float vec3_dot(vec3_t v, vec3_t u) { return v.x * u.x + v.y * u.y + v.z * u.z; } vec3_t vec3_cross(vec3_t v, vec3_t u) { return (vec3_t) { v.y * u.z - v.z * u.y, v.z * u.x - v.x * u.z, v.x * u.y - v.y * u.x, }; } vec4_t vec4_add(vec4_t v, vec4_t u) { return (vec4_t) { v.x + u.x, v.y + u.y, v.z + u.z, v.w + u.w }; } vec4_t vec4_scale(float s, vec4_t v) { return (vec4_t) { s * v.x, s * v.y, s * v.z, s * v.w }; } float vec4_dot(vec4_t v, vec4_t u) { return v.x * u.x + v.y * u.y + v.z * u.z + v.w * u.w; } mat4_t mat4_mul(mat4_t m, mat4_t n) { #define ELEM(i, j) m.x.i *n.j.x + m.y.i *n.j.y + m.z.i *n.j.z + m.w.i *n.j.w return (mat4_t) { { ELEM(x, x), ELEM(y, x), ELEM(z, x), ELEM(w, x) }, { ELEM(x, y), ELEM(y, y), ELEM(z, y), ELEM(w, y) }, { ELEM(x, z), ELEM(y, z), ELEM(z, z), ELEM(w, z) }, { ELEM(x, w), ELEM(y, w), ELEM(z, w), ELEM(w, w) }, }; #undef ELEM } mat4_t mat4_lookat(vec3_t camera, vec3_t target, vec3_t up) { const vec3_t s = vec3_sub(target, camera); const vec3_t s_hat = vec3_norm(s); const vec3_t u_hat = vec3_norm(vec3_cross(up, s_hat)); const vec3_t v_hat = vec3_cross(s_hat, u_hat); return (mat4_t) { { u_hat.x, v_hat.x, s_hat.x, 0 }, { u_hat.y, v_hat.y, s_hat.y, 0 }, { u_hat.z, v_hat.z, s_hat.z, 0 }, { -vec3_dot(u_hat, camera), -vec3_dot(v_hat, camera), -vec3_dot(s_hat, camera), 1, }, }; } mat4_t mat4_perspective(float aspect, float fov, float near, float far) { const float r = 2 * near * tanf(fov / 2); const float t = r * aspect; return (mat4_t) { { near / t, 0, 0, 0 }, { 0, -near / r, 0, 0 }, { 0, 0, far / (far - near), 1 }, { 0, 0, -far * near / (far - near), 0 }, }; } mat4_t mat4_orthographic(float width, float height, float near, float far) { return (mat4_t) { { 1 / width, 0, 0, 0 }, { 0, -1 / height, 0, 0 }, { 0, 0, 1 / (far - near), 0 }, { 0, 0, -near / (far - near), 1 }, }; } mat4_t mat4_translate_vec3(vec3_t v) { return (mat4_t) { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { v.x, v.y, v.z, 1 }, }; } mat4_t mat4_scale_vec3(vec3_t v) { return (mat4_t) { { v.x, 0, 0, 0 }, { 0, v.y, 0, 0 }, { 0, 0, v.z, 0 }, { 0, 0, 0, 1 }, }; } mat4_t mat4_rotate_quaternion(vec4_t q) { const float xx = q.x * q.x; const float xy = q.x * q.y; const float xz = q.x * q.z; const float xw = q.x * q.w; const float yy = q.y * q.y; const float yz = q.y * q.z; const float yw = q.y * q.w; const float zz = q.z * q.z; const float zw = q.z * q.w; return (mat4_t) { { 1 - 2 * (yy + zz), 2 * (xy + zw), 2 * (xz - yw), 0, }, { 2 * (xy - zw), 1 - 2 * (xx + zz), 2 * (yz + xw), 0, }, { 2 * (xz + yw), 2 * (yz - xw), 1 - 2 * (xx + yy), 0, }, { 0, 0, 0, 1 }, }; }