From b81304e7597a85abbfc009b2bc7d6c702e5d23c7 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Sun, 30 Jun 2024 02:40:04 +0100 Subject: [PATCH] Switch to using transformation matrices --- include/camera/camera.h | 4 +- include/rasteriser/rasteriser.h | 12 +- include/vector/vec.h | 27 +++++ src/camera/camera.c | 19 ++-- src/rasteriser/main.c | 99 +++++++++------- src/rasteriser/rasteriser.c | 23 +++- src/vector/vec.c | 194 ++++++++++++++++++++++++++------ 7 files changed, 282 insertions(+), 96 deletions(-) diff --git a/include/camera/camera.h b/include/camera/camera.h index c13a57c..ee1ffc6 100644 --- a/include/camera/camera.h +++ b/include/camera/camera.h @@ -9,7 +9,7 @@ typedef struct { vec3f_t rotation; } camera_t; -vec2i_t project_point(vec3f_t point, const window_t *wnd, - const camera_t *camera, vec3f_t viewport); +mat4x4f_t inverse_camera_translation_matrix(const camera_t *camera); +mat4x4f_t inverse_camera_rotation_matrix(const camera_t *camera); #endif // !CAMERA_H diff --git a/include/rasteriser/rasteriser.h b/include/rasteriser/rasteriser.h index 0029e08..36caf6b 100644 --- a/include/rasteriser/rasteriser.h +++ b/include/rasteriser/rasteriser.h @@ -41,12 +41,18 @@ typedef struct { } model_t; typedef struct { - model_t *model; + f32 scale; + vec3f_t rotation; vec3f_t position; +} transform_t; + +typedef struct { + model_t *model; + transform_t transform; } instance_t; -void render_instance(window_t *wnd, Arena *arena, const camera_t *camera, - vec3f_t viewport, const instance_t *instance_t); +void render_instance(window_t *wnd, Arena *arena, mat3x4f_t proj_cam_mat, + const instance_t *instance); void draw_wireframe_triangle(window_t *wnd, Arena *arena, triangle_t triangle); void draw_filled_triangle(window_t *wnd, Arena *arena, triangle_t triangle); void draw_shaded_triangle(window_t *wnd, Arena *arena, triangle_t triangle); diff --git a/include/vector/vec.h b/include/vector/vec.h index 599e403..b0c8299 100644 --- a/include/vector/vec.h +++ b/include/vector/vec.h @@ -39,6 +39,25 @@ typedef struct { f32 w; } vec4f_t; +typedef struct { + vec3f_t row0; + vec3f_t row1; + vec3f_t row2; +} mat3x3f_t; + +typedef struct { + vec4f_t row0; + vec4f_t row1; + vec4f_t row2; +} mat3x4f_t; + +typedef struct { + vec4f_t row0; + vec4f_t row1; + vec4f_t row2; + vec4f_t row3; +} mat4x4f_t; + #define vec_add(T, v1, v2) vec_add_##T(v1, v2) #define vec_sub(T, v1, v2) vec_sub_##T(v1, v2) #define vec_mul(T, v1, v2) vec_mul_##T(v1, v2) @@ -103,4 +122,12 @@ f32 vec_dot_vec4f_t(vec4f_t v1, vec4f_t v2); f32 vec_magnitude_vec4f_t(vec4f_t v); vec4f_t vec_unit_vec4f_t(vec4f_t v); +mat4x4f_t get_translation_matrix(vec3f_t translation); +mat4x4f_t get_rotation_matrix(vec3f_t rotation); +mat4x4f_t get_scaling_matrix(vec3f_t scale); +mat3x3f_t get_rotation_mat3x3f(vec3f_t rotation); +vec3f_t mul_mat3x4f_by_vec4f(mat3x4f_t mat, vec4f_t vec); +mat3x4f_t mul_mat3x4f_by_mat4x4f(mat3x4f_t mat1, mat4x4f_t mat2); +mat4x4f_t mul_mat4x4f(mat4x4f_t mat1, mat4x4f_t mat2); + #endif // !VEC_H diff --git a/src/camera/camera.c b/src/camera/camera.c index 70a7e6f..152a054 100644 --- a/src/camera/camera.c +++ b/src/camera/camera.c @@ -1,15 +1,12 @@ #include "camera/camera.h" #include "vector/vec.h" -#include "window/window.h" -vec2i_t project_point(vec3f_t point, const window_t *wnd, - const camera_t *camera, vec3f_t viewport) { - if (point.z == 0.0f) { - return (vec2i_t){.x = 0, .y = 0}; - } - - f32 x = point.x * viewport.z / point.z; - f32 y = point.y * viewport.z / point.z; - - return viewport_to_window(wnd, x, y, viewport); +mat4x4f_t inverse_camera_translation_matrix(const camera_t *camera) { + vec3f_t inverse_translation = vec_mul_num(vec3f_t, camera->position, -1.0f); + return get_translation_matrix(inverse_translation); +} + +mat4x4f_t inverse_camera_rotation_matrix(const camera_t *camera) { + vec3f_t inverse_rotation = vec_mul_num(vec3f_t, camera->rotation, -1.0f); + return get_rotation_matrix(inverse_rotation); } diff --git a/src/rasteriser/main.c b/src/rasteriser/main.c index f33506f..3eb555b 100644 --- a/src/rasteriser/main.c +++ b/src/rasteriser/main.c @@ -2,6 +2,7 @@ #include "list/typed_list.h" #include "mem_arena.h" #include "mem_utils.h" +#include "misc/misc_utils.h" #include "rasteriser/rasteriser.h" #include "vector/vec.h" #include "window/window.h" @@ -36,50 +37,67 @@ int main(void) { return EXIT_FAILURE; } // Vertices - list_append(vec3f_t, arena, vertices, ((vec3f_t){1, 1, 1})); - list_append(vec3f_t, arena, vertices, ((vec3f_t){-1, 1, 1})); - list_append(vec3f_t, arena, vertices, ((vec3f_t){-1, -1, 1})); - list_append(vec3f_t, arena, vertices, ((vec3f_t){1, -1, 1})); - list_append(vec3f_t, arena, vertices, ((vec3f_t){1, 1, -1})); - list_append(vec3f_t, arena, vertices, ((vec3f_t){-1, 1, -1})); - list_append(vec3f_t, arena, vertices, ((vec3f_t){-1, -1, -1})); - list_append(vec3f_t, arena, vertices, ((vec3f_t){1, -1, -1})); + vec3f_t verts[] = { + (vec3f_t){1, 1, 1}, (vec3f_t){-1, 1, 1}, (vec3f_t){-1, -1, 1}, + (vec3f_t){1, -1, 1}, (vec3f_t){1, 1, -1}, (vec3f_t){-1, 1, -1}, + (vec3f_t){-1, -1, -1}, (vec3f_t){1, -1, -1}, + }; + for (u64 i = 0; i < ARR_LEN(verts); ++i) { + list_append(vec3f_t, arena, vertices, verts[i]); + } list_scene_triangle_t *triangles = list_create(scene_triangle_t, arena); if (!triangles) { return EXIT_FAILURE; } // Triangles - list_append(scene_triangle_t, arena, triangles, - ((scene_triangle_t){0, 1, 2, (colour_t){.colour = 0xff0000ff}})); - list_append(scene_triangle_t, arena, triangles, - ((scene_triangle_t){0, 2, 3, (colour_t){.colour = 0xff0000ff}})); - list_append(scene_triangle_t, arena, triangles, - ((scene_triangle_t){4, 0, 3, (colour_t){.colour = 0x00ff00ff}})); - list_append(scene_triangle_t, arena, triangles, - ((scene_triangle_t){4, 3, 7, (colour_t){.colour = 0x00ff00ff}})); - list_append(scene_triangle_t, arena, triangles, - ((scene_triangle_t){5, 4, 7, (colour_t){.colour = 0x0000ffff}})); - list_append(scene_triangle_t, arena, triangles, - ((scene_triangle_t){5, 7, 6, (colour_t){.colour = 0x0000ffff}})); - list_append(scene_triangle_t, arena, triangles, - ((scene_triangle_t){1, 5, 6, (colour_t){.colour = 0xffff00ff}})); - list_append(scene_triangle_t, arena, triangles, - ((scene_triangle_t){1, 6, 2, (colour_t){.colour = 0xffff00ff}})); - list_append(scene_triangle_t, arena, triangles, - ((scene_triangle_t){4, 5, 1, (colour_t){.colour = 0xff00ffff}})); - list_append(scene_triangle_t, arena, triangles, - ((scene_triangle_t){4, 1, 0, (colour_t){.colour = 0xff00ffff}})); - list_append(scene_triangle_t, arena, triangles, - ((scene_triangle_t){2, 6, 7, (colour_t){.colour = 0x00ffffff}})); - list_append(scene_triangle_t, arena, triangles, - ((scene_triangle_t){2, 7, 3, (colour_t){.colour = 0x00ffffff}})); + scene_triangle_t tris[] = { + (scene_triangle_t){0, 1, 2, (colour_t){.colour = 0xff0000ff}}, + (scene_triangle_t){0, 2, 3, (colour_t){.colour = 0xff0000ff}}, + (scene_triangle_t){4, 0, 3, (colour_t){.colour = 0x00ff00ff}}, + (scene_triangle_t){4, 3, 7, (colour_t){.colour = 0x00ff00ff}}, + (scene_triangle_t){5, 4, 7, (colour_t){.colour = 0x0000ffff}}, + (scene_triangle_t){5, 7, 6, (colour_t){.colour = 0x0000ffff}}, + (scene_triangle_t){1, 5, 6, (colour_t){.colour = 0xffff00ff}}, + (scene_triangle_t){1, 6, 2, (colour_t){.colour = 0xffff00ff}}, + (scene_triangle_t){4, 5, 1, (colour_t){.colour = 0xff00ffff}}, + (scene_triangle_t){4, 1, 0, (colour_t){.colour = 0xff00ffff}}, + (scene_triangle_t){2, 6, 7, (colour_t){.colour = 0x00ffffff}}, + (scene_triangle_t){2, 7, 3, (colour_t){.colour = 0x00ffffff}}, + }; + for (u64 i = 0; i < ARR_LEN(tris); ++i) { + list_append(scene_triangle_t, arena, triangles, tris[i]); + } model_t cube = {.vertices = vertices, .triangles = triangles}; - instance_t cube_01 = {.model = &cube, - .position = (vec3f_t){-1.5f, 0.0f, 8.0f}}; - instance_t cube_02 = {.model = &cube, - .position = (vec3f_t){1.7f, 1.5f, 7.0f}}; + instance_t cube_01 = { + .model = &cube, + .transform = + { + .scale = 1.0f, + .rotation = (vec3f_t){0}, + .position = (vec3f_t){-1.5f, 0.0f, 8.0f}, + }, + }; + instance_t cube_02 = { + .model = &cube, + .transform = + { + .scale = 1.0f, + .rotation = {0}, + .position = (vec3f_t){1.7f, 1.5f, 7.0f}, + }, + }; + + mat3x4f_t proj_matrix = { + (vec4f_t){viewport.z * window.width / viewport.x, 0.0f, 0.0f, 0.0f}, + (vec4f_t){0.0f, viewport.z * window.height / viewport.y, 0.0f, 0.0f}, + (vec4f_t){0.0f, 0.0f, 1.0f, 0.0f}, + }; + mat4x4f_t cam_inverse_rotation = {0}; + mat4x4f_t cam_inverse_translation = {0}; + mat4x4f_t cam_matrix = {0}; + mat3x4f_t proj_cam_matrix = {0}; bool running = true; SDL_Event event = {0}; @@ -105,10 +123,15 @@ int main(void) { } } + cam_inverse_rotation = inverse_camera_rotation_matrix(&camera); + cam_inverse_translation = inverse_camera_translation_matrix(&camera); + cam_matrix = mul_mat4x4f(cam_inverse_rotation, cam_inverse_translation); + proj_cam_matrix = mul_mat3x4f_by_mat4x4f(proj_matrix, cam_matrix); + clear_window(&window, bg); - render_instance(&window, arena, &camera, viewport, &cube_01); - render_instance(&window, arena, &camera, viewport, &cube_02); + render_instance(&window, arena, proj_cam_matrix, &cube_01); + render_instance(&window, arena, proj_cam_matrix, &cube_02); swap_buffers(&window); diff --git a/src/rasteriser/rasteriser.c b/src/rasteriser/rasteriser.c index 49c66c1..0914fba 100644 --- a/src/rasteriser/rasteriser.c +++ b/src/rasteriser/rasteriser.c @@ -12,23 +12,34 @@ #include internal list_float *interpolate(Arena *arena, i32 i0, f32 d0, i32 i1, f32 d1); - internal inline void order_triangle_points(triangle_t *triangle); -void render_instance(window_t *wnd, Arena *arena, const camera_t *camera, - vec3f_t viewport, const instance_t *instance) { +void render_instance(window_t *wnd, Arena *arena, mat3x4f_t proj_cam_mat, + const instance_t *instance) { list_vec2i_t *projected = list_create_with_capacity( vec2i_t, arena, instance->model->vertices->count * sizeof(vec3f_t)); if (!projected) { return; } + mat4x4f_t t_mat = get_translation_matrix(instance->transform.position); + mat4x4f_t r_mat = get_rotation_matrix(instance->transform.rotation); + mat4x4f_t s_mat = get_scaling_matrix((vec3f_t){instance->transform.scale, + instance->transform.scale, + instance->transform.scale}); + mat4x4f_t tr_mat = mul_mat4x4f(t_mat, r_mat); + mat4x4f_t trs_mat = mul_mat4x4f(tr_mat, s_mat); + + mat3x4f_t xf_proj_mat = mul_mat3x4f_by_mat4x4f(proj_cam_mat, trs_mat); + vec3f_t vertex = {0}; + vec2i_t point = {0}; for (u64 i = 0; i < instance->model->vertices->count; ++i) { vertex = list_get(instance->model->vertices, i); - vertex = vec_add(vec3f_t, vertex, instance->position); - list_append(vec2i_t, arena, projected, - project_point(vertex, wnd, camera, viewport)); + vertex = mul_mat3x4f_by_vec4f( + xf_proj_mat, (vec4f_t){vertex.x, vertex.y, vertex.z, 1.0f}); + point = (vec2i_t){(i32)(vertex.x / vertex.z), (i32)(vertex.y / vertex.z)}; + list_append(vec2i_t, arena, projected, point); } for (u64 i = 0; i < instance->model->triangles->count; ++i) { diff --git a/src/vector/vec.c b/src/vector/vec.c index 3a9d929..133d7e4 100644 --- a/src/vector/vec.c +++ b/src/vector/vec.c @@ -2,12 +2,6 @@ #include "math/math_utils.h" #include -typedef struct { - vec3f_t row0; - vec3f_t row1; - vec3f_t row2; -} mat3x3f_t; - vec2i_t vec_add_vec2i_t(vec2i_t v1, vec2i_t v2) { return (vec2i_t){.x = v1.x + v2.x, .y = v1.y + v2.y}; } @@ -145,36 +139,7 @@ vec3f_t vec_unit_vec3f_t(vec3f_t v) { } vec3f_t vec_rotate_vec3f_t(vec3f_t original, vec3f_t rotation) { - f32 x_rad = RADIANS(rotation.x); - f32 y_rad = RADIANS(rotation.y); - f32 z_rad = RADIANS(rotation.z); - - f32 cos_x = cosf(x_rad); - f32 sin_x = sinf(x_rad); - - f32 cos_y = cosf(y_rad); - f32 sin_y = sinf(y_rad); - - f32 cos_z = cosf(z_rad); - f32 sin_z = sinf(z_rad); - - f32 row0_col0 = cos_z * cos_y; - f32 row0_col1 = cos_z * sin_y * sin_x - sin_z * cos_x; - f32 row0_col2 = cos_z * sin_y * cos_x + sin_z * sin_x; - - f32 row1_col0 = sin_z * cos_y; - f32 row1_col1 = sin_z * sin_y * sin_x + cos_z * cos_x; - f32 row1_col2 = sin_z * sin_y * cos_x - cos_z * sin_x; - - f32 row2_col0 = -sin_y; - f32 row2_col1 = cos_y * sin_x; - f32 row2_col2 = cos_y * cos_x; - - mat3x3f_t matrix = { - .row0 = {row0_col0, row0_col1, row0_col2}, - .row1 = {row1_col0, row1_col1, row1_col2}, - .row2 = {row2_col0, row2_col1, row2_col2}, - }; + mat3x3f_t matrix = get_rotation_mat3x3f(rotation); // clang-format off return (vec3f_t){ @@ -264,3 +229,160 @@ vec4f_t vec_unit_vec4f_t(vec4f_t v) { return (vec4f_t){v.x / magnitude, v.y / magnitude, v.z / magnitude, v.w / magnitude}; } + +mat4x4f_t get_scaling_matrix(vec3f_t scale) { + // clang-format off + return (mat4x4f_t){ + (vec4f_t){scale.x, 0.0f, 0.0f, 0.0f}, + (vec4f_t){0.0f, scale.y, 0.0f, 0.0f}, + (vec4f_t){0.0f, 0.0f, scale.z, 0.0f}, + (vec4f_t){0.0f, 0.0f, 0.0f, 1.0f}, + }; + // clang-format on +} + +mat3x3f_t get_rotation_mat3x3f(vec3f_t rotation) { + f32 x_rad = RADIANS(rotation.x); + f32 y_rad = RADIANS(rotation.y); + f32 z_rad = RADIANS(rotation.z); + + f32 cos_x = cosf(x_rad); + f32 sin_x = sinf(x_rad); + + f32 cos_y = cosf(y_rad); + f32 sin_y = sinf(y_rad); + + f32 cos_z = cosf(z_rad); + f32 sin_z = sinf(z_rad); + + f32 row0_col0 = cos_z * cos_y; + f32 row0_col1 = cos_z * sin_y * sin_x - sin_z * cos_x; + f32 row0_col2 = cos_z * sin_y * cos_x + sin_z * sin_x; + + f32 row1_col0 = sin_z * cos_y; + f32 row1_col1 = sin_z * sin_y * sin_x + cos_z * cos_x; + f32 row1_col2 = sin_z * sin_y * cos_x - cos_z * sin_x; + + f32 row2_col0 = -sin_y; + f32 row2_col1 = cos_y * sin_x; + f32 row2_col2 = cos_y * cos_x; + + return (mat3x3f_t){ + .row0 = {row0_col0, row0_col1, row0_col2}, + .row1 = {row1_col0, row1_col1, row1_col2}, + .row2 = {row2_col0, row2_col1, row2_col2}, + }; +} + +mat4x4f_t get_translation_matrix(vec3f_t translation) { + return (mat4x4f_t){ + (vec4f_t){1.0f, 0.0f, 0.0f, translation.x}, + (vec4f_t){0.0f, 1.0f, 0.0f, translation.y}, + (vec4f_t){0.0f, 0.0f, 1.0f, translation.z}, + (vec4f_t){0.0f, 0.0f, 0.0f, 1.0f}, + }; +} + +mat4x4f_t get_rotation_matrix(vec3f_t rotation) { + mat3x3f_t mat = get_rotation_mat3x3f(rotation); + + // clang-format off + return (mat4x4f_t){ + (vec4f_t){mat.row0.x, mat.row0.y, mat.row0.z, 0.0f}, + (vec4f_t){mat.row1.x, mat.row1.y, mat.row1.z, 0.0f}, + (vec4f_t){mat.row2.x, mat.row2.y, mat.row2.z, 0.0f}, + (vec4f_t){ 0.0f, 0.0f, 0.0f, 1.0f}, + }; + // clang-format on +} + +vec3f_t mul_mat3x4f_by_vec4f(mat3x4f_t mat, vec4f_t vec) { + f32 x = mat.row0.x * vec.x + mat.row0.y * vec.y + mat.row0.z * vec.z + + mat.row0.w * vec.w; + f32 y = mat.row1.x * vec.x + mat.row1.y * vec.y + mat.row1.z * vec.z + + mat.row1.w * vec.w; + f32 z = mat.row2.x * vec.x + mat.row2.y * vec.y + mat.row2.z * vec.z + + mat.row2.w * vec.w; + + return (vec3f_t){x, y, z}; +} + +mat3x4f_t mul_mat3x4f_by_mat4x4f(mat3x4f_t mat1, mat4x4f_t mat2) { + f32 row0_col0 = mat1.row0.x * mat2.row0.x + mat1.row0.y * mat2.row1.x + + mat1.row0.z * mat2.row2.x + mat1.row0.w * mat2.row3.x; + f32 row0_col1 = mat1.row0.x * mat2.row0.y + mat1.row0.y * mat2.row1.y + + mat1.row0.z * mat2.row2.y + mat1.row0.w * mat2.row3.y; + f32 row0_col2 = mat1.row0.x * mat2.row0.z + mat1.row0.y * mat2.row1.z + + mat1.row0.z * mat2.row2.z + mat1.row0.w * mat2.row3.z; + f32 row0_col3 = mat1.row0.x * mat2.row0.w + mat1.row0.y * mat2.row1.w + + mat1.row0.z * mat2.row2.w + mat1.row0.w * mat2.row3.w; + + f32 row1_col0 = mat1.row1.x * mat2.row0.x + mat1.row1.y * mat2.row1.x + + mat1.row1.z * mat2.row2.x + mat1.row1.w * mat2.row3.x; + f32 row1_col1 = mat1.row1.x * mat2.row0.y + mat1.row1.y * mat2.row1.y + + mat1.row1.z * mat2.row2.y + mat1.row1.w * mat2.row3.y; + f32 row1_col2 = mat1.row1.x * mat2.row0.z + mat1.row1.y * mat2.row1.z + + mat1.row1.z * mat2.row2.z + mat1.row1.w * mat2.row3.z; + f32 row1_col3 = mat1.row1.x * mat2.row0.w + mat1.row1.y * mat2.row1.w + + mat1.row1.z * mat2.row2.w + mat1.row1.w * mat2.row3.w; + + f32 row2_col0 = mat1.row2.x * mat2.row0.x + mat1.row2.y * mat2.row1.x + + mat1.row2.z * mat2.row2.x + mat1.row2.w * mat2.row3.x; + f32 row2_col1 = mat1.row2.x * mat2.row0.y + mat1.row2.y * mat2.row1.y + + mat1.row2.z * mat2.row2.y + mat1.row2.w * mat2.row3.y; + f32 row2_col2 = mat1.row2.x * mat2.row0.z + mat1.row2.y * mat2.row1.z + + mat1.row2.z * mat2.row2.z + mat1.row2.w * mat2.row3.z; + f32 row2_col3 = mat1.row2.x * mat2.row0.w + mat1.row2.y * mat2.row1.w + + mat1.row2.z * mat2.row2.w + mat1.row2.w * mat2.row3.w; + + return (mat3x4f_t){ + (vec4f_t){row0_col0, row0_col1, row0_col2, row0_col3}, + (vec4f_t){row1_col0, row1_col1, row1_col2, row1_col3}, + (vec4f_t){row2_col0, row2_col1, row2_col2, row2_col3}, + }; +} + +mat4x4f_t mul_mat4x4f(mat4x4f_t mat1, mat4x4f_t mat2) { + f32 row0_col0 = mat1.row0.x * mat2.row0.x + mat1.row0.y * mat2.row1.x + + mat1.row0.z * mat2.row2.x + mat1.row0.w * mat2.row3.x; + f32 row0_col1 = mat1.row0.x * mat2.row0.y + mat1.row0.y * mat2.row1.y + + mat1.row0.z * mat2.row2.y + mat1.row0.w * mat2.row3.y; + f32 row0_col2 = mat1.row0.x * mat2.row0.z + mat1.row0.y * mat2.row1.z + + mat1.row0.z * mat2.row2.z + mat1.row0.w * mat2.row3.z; + f32 row0_col3 = mat1.row0.x * mat2.row0.w + mat1.row0.y * mat2.row1.w + + mat1.row0.z * mat2.row2.w + mat1.row0.w * mat2.row3.w; + + f32 row1_col0 = mat1.row1.x * mat2.row0.x + mat1.row1.y * mat2.row1.x + + mat1.row1.z * mat2.row2.x + mat1.row1.w * mat2.row3.x; + f32 row1_col1 = mat1.row1.x * mat2.row0.y + mat1.row1.y * mat2.row1.y + + mat1.row1.z * mat2.row2.y + mat1.row1.w * mat2.row3.y; + f32 row1_col2 = mat1.row1.x * mat2.row0.z + mat1.row1.y * mat2.row1.z + + mat1.row1.z * mat2.row2.z + mat1.row1.w * mat2.row3.z; + f32 row1_col3 = mat1.row1.x * mat2.row0.w + mat1.row1.y * mat2.row1.w + + mat1.row1.z * mat2.row2.w + mat1.row1.w * mat2.row3.w; + + f32 row2_col0 = mat1.row2.x * mat2.row0.x + mat1.row2.y * mat2.row1.x + + mat1.row2.z * mat2.row2.x + mat1.row2.w * mat2.row3.x; + f32 row2_col1 = mat1.row2.x * mat2.row0.y + mat1.row2.y * mat2.row1.y + + mat1.row2.z * mat2.row2.y + mat1.row2.w * mat2.row3.y; + f32 row2_col2 = mat1.row2.x * mat2.row0.z + mat1.row2.y * mat2.row1.z + + mat1.row2.z * mat2.row2.z + mat1.row2.w * mat2.row3.z; + f32 row2_col3 = mat1.row2.x * mat2.row0.w + mat1.row2.y * mat2.row1.w + + mat1.row2.z * mat2.row2.w + mat1.row2.w * mat2.row3.w; + + f32 row3_col0 = mat1.row3.x * mat2.row0.x + mat1.row3.y * mat2.row1.x + + mat1.row3.z * mat2.row2.x + mat1.row3.w * mat2.row3.x; + f32 row3_col1 = mat1.row3.x * mat2.row0.y + mat1.row3.y * mat2.row1.y + + mat1.row3.z * mat2.row2.y + mat1.row3.w * mat2.row3.y; + f32 row3_col2 = mat1.row3.x * mat2.row0.z + mat1.row3.y * mat2.row1.z + + mat1.row3.z * mat2.row2.z + mat1.row3.w * mat2.row3.z; + f32 row3_col3 = mat1.row3.x * mat2.row0.w + mat1.row3.y * mat2.row1.w + + mat1.row3.z * mat2.row2.w + mat1.row3.w * mat2.row3.w; + + return (mat4x4f_t){ + (vec4f_t){row0_col0, row0_col1, row0_col2, row0_col3}, + (vec4f_t){row1_col0, row1_col1, row1_col2, row1_col3}, + (vec4f_t){row2_col0, row2_col1, row2_col2, row2_col3}, + (vec4f_t){row3_col0, row3_col1, row3_col2, row3_col3}, + }; +}