/** * @file maths.c * @author Omniscient * @brief Linear algebra for 2D and 3D including vectors, matrices, and quaternion functions. * * @copyright Copyright (c) 2024 */ #include vec2 vec2_create(f32 x, f32 y) { return (vec2){ x,y};} vec3 vec3_create(f32 x, f32 y, f32 z) { return (vec3){ x, y, z }; } vec3 vec3_add(vec3 u, vec3 v) { return (vec3){ .x = u.x + v.x, .y = u.y + v.y, .z = u.z + v.z }; } vec3 vec3_sub(vec3 a, vec3 b) { return (vec3){ a.x - b.x, a.y - b.y, a.z - b.z }; } vec3 vec3_mult(vec3 a, f32 s) { return (vec3){ a.x * s, a.y * s, a.z * s }; } vec3 vec3_div(vec3 a, f32 s) { return (vec3){ a.x / s, a.y / s, a.z / s }; } f32 vec3_len_squared(vec3 a) { return (a.x * a.x) + (a.y * a.y) + (a.z * a.z); } f32 vec3_len(vec3 a) { return sqrtf(vec3_len_squared(a)); } vec3 vec3_negate(vec3 a) { return (vec3){ -a.x, -a.y, -a.z }; } vec3 vec3_normalise(vec3 a) { f32 length = vec3_len(a); return vec3_div(a, length); } f32 vec3_dot(vec3 a, vec3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; } vec3 vec3_cross(vec3 a, vec3 b) { return (vec3){ .x = a.y * b.z - a.z * b.y, .y = a.z * b.x - a.x * b.z, .z = a.x * b.y - a.y * b.x }; } vec4 vec4_create(f32 x, f32 y, f32 z, f32 w) { return (vec4){ x, y, z, w }; } f32 quat_dot(quat a, quat b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } quat quat_normalise(quat a) { f32 length = sqrtf(quat_dot(a, a)); // same as len squared return (quat){ a.x / length, a.y / length, a.z / length, a.w / length }; } quat quat_from_axis_angle(vec3 axis, f32 angle, bool normalize) { const f32 half_angle = 0.5f * angle; f32 s = sinf(half_angle); f32 c = cosf(half_angle); quat q = (quat){ s * axis.x, s * axis.y, s * axis.z, c }; if (normalize) { return quat_normalise(q); } return q; } mat4 mat4_ident() { return (mat4){ .x_axis = { 1, 0, 0, 0 }, .y_axis = { 0, 1, 0, 0 }, .z_axis = { 0, 0, 1, 0 }, .w_axis = { 0, 0, 0, 1 }, }; } mat4 mat4_translation(vec3 position) { mat4 out_matrix = mat4_ident(); out_matrix.w_axis.x = position.x; out_matrix.w_axis.y = position.y; out_matrix.w_axis.z = position.z; return out_matrix; } mat4 mat4_scale(vec3 scale) { mat4 out_matrix = mat4_ident(); out_matrix.x_axis.x = scale.x; out_matrix.y_axis.y = scale.y; out_matrix.z_axis.z = scale.z; return out_matrix; } // TODO: double check this mat4 mat4_rotation(quat rotation) { TODO("impl mat4_rotation"); // mat4 out_matrix = mat4_ident(); // quat n = quat_normalise(rotation); // out_matrix.data[0] = 1.0f - 2.0f * n.y * n.y - 2.0f * n.z * n.z; // out_matrix.data[1] = 2.0f * n.x * n.y - 2.0f * n.z * n.w; // out_matrix.data[2] = 2.0f * n.x * n.z + 2.0f * n.y * n.w; // out_matrix.data[4] = 2.0f * n.x * n.y + 2.0f * n.z * n.w; // out_matrix.data[5] = 1.0f - 2.0f * n.x * n.x - 2.0f * n.z * n.z; // out_matrix.data[6] = 2.0f * n.y * n.z - 2.0f * n.x * n.w; // out_matrix.data[8] = 2.0f * n.x * n.z - 2.0f * n.y * n.w; // out_matrix.data[9] = 2.0f * n.y * n.z + 2.0f * n.x * n.w; // out_matrix.data[10] = 1.0f - 2.0f * n.x * n.x - 2.0f * n.y * n.y; // return out_matrix; } mat4 mat4_mult(mat4 lhs, mat4 rhs) { TODO("impl mat4_mult"); // mat4 out_matrix = mat4_ident(); // for (i32 row = 0; row < 4; row++) { // for (i32 col = 0; col < 4; col++) { // f32 sum = 0; // for (i32 i = 0; i < 4; i++) { // // column-major: first matrix columns × second matrix rows // sum += lhs.data[row + i * 4] * rhs.data[i + col * 4]; // } // out_matrix.data[row + col * 4] = sum; // } // } // return out_matrix; } /* */ mat4 mat4_perspective(f32 fov_radians, f32 aspect_ratio, f32 near_z, f32 far_z) { TODO("impl mat4_perspective"); // f32 half_tan_fov = tanf(fov_radians * 0.5f); // mat4 out_matrix = { .data = { 0 } }; // out_matrix.data[0] = 1.0f / (aspect_ratio * half_tan_fov); // out_matrix.data[5] = 1.0f / half_tan_fov; // out_matrix.data[10] = -((far_z + near_z) / (far_z - near_z)); // out_matrix.data[11] = -1.0f; // out_matrix.data[14] = -((2.0f * far_z * near_z) / (far_z - near_z)); // return out_matrix; } mat4 mat4_look_at(vec3 position, vec3 target, vec3 up) { TODO("impl mat4_lookat"); // mat4 out_matrix; // vec3 z_axis; // z_axis.x = target.x - position.x; // z_axis.y = target.y - position.y; // z_axis.z = target.z - position.z; // z_axis = vec3_normalise(z_axis); // vec3 x_axis = vec3_normalise(vec3_cross(z_axis, up)); // vec3 y_axis = vec3_cross(x_axis, z_axis); // out_matrix.data[0] = x_axis.x; // out_matrix.data[1] = y_axis.x; // out_matrix.data[2] = -z_axis.x; // out_matrix.data[3] = 0; // out_matrix.data[4] = x_axis.y; // out_matrix.data[5] = y_axis.y; // out_matrix.data[6] = -z_axis.y; // out_matrix.data[7] = 0; // out_matrix.data[8] = x_axis.z; // out_matrix.data[9] = y_axis.z; // out_matrix.data[10] = -z_axis.z; // out_matrix.data[11] = 0; // out_matrix.data[12] = -vec3_dot(x_axis, position); // out_matrix.data[13] = -vec3_dot(y_axis, position); // out_matrix.data[14] = vec3_dot(z_axis, position); // out_matrix.data[15] = 1.0f; // return out_matrix; } transform transform_from_mat4(mat4 matrix) { TODO("stuff") }