From 6be5527b37cc7953729a57c02cda0650b4f1cabe Mon Sep 17 00:00:00 2001 From: jb Date: Fri, 11 Jul 2025 23:56:41 -0700 Subject: [PATCH] matrix --- CMakeLists.txt | 1 + scripts/main.c | 59 ++++++++++++++++++--------- scripts/matrix.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++ scripts/matrix.h | 21 ++++++++++ scripts/mesh.c | 4 +- scripts/mesh.h | 2 + scripts/vector.c | 18 +++++++++ scripts/vector.h | 7 ++++ 8 files changed, 196 insertions(+), 19 deletions(-) create mode 100644 scripts/matrix.c create mode 100644 scripts/matrix.h diff --git a/CMakeLists.txt b/CMakeLists.txt index dfafb0a..3cb2c56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ set(CMAKE_C_STANDARD 11) add_executable(${PROJECT_NAME} scripts/main.c scripts/array.c scripts/vector.c + scripts/matrix.c scripts/mesh.c scripts/triangle.c scripts/display.c) diff --git a/scripts/main.c b/scripts/main.c index dee8310..d562b9e 100644 --- a/scripts/main.c +++ b/scripts/main.c @@ -8,6 +8,7 @@ #include "mesh.h" #include "vector.h" #include "array.h" +#include "matrix.h" #define STEP 0.075 @@ -113,8 +114,8 @@ void process_input(void) { //////////////////////////////////////////////////////////////////////////////// vec2_t project(vec3_t point) { vec2_t projected_point = { - .x = round((fov_factor * point.x) / point.z), - .y = round((fov_factor * point.y) / point.z), + .x = roundf((fov_factor * point.x) / point.z), + .y = roundf((fov_factor * point.y) / point.z), }; return projected_point; } @@ -131,9 +132,27 @@ void update(void) { previous_frame_time = SDL_GetTicks(); - mesh.rotation.y += 0.01; - mesh.rotation.x -= 0.01; - mesh.rotation.z += 0.01; + mesh.rotation.y += 0.01f; + mesh.rotation.x -= 0.01f; + mesh.rotation.z += 0.01f; + + mesh.translation.x += 0.004f; + mesh.translation.z = 5.0f; + + //mesh.scale.x += 0.002f; + //mesh.scale.y += 0.002f; + + // create scale matrix that will be used + mat4_t scale_matrix = mat4_make_scale(mesh.scale.x, mesh.scale.y, mesh.scale.z); + + // create translation matrix + mat4_t translation_matrix = mat4_make_translation(mesh.translation.x, mesh.translation.y, mesh.translation.z); + + // create rotation matrices + mat4_t rotation_matrix_x = mat4_make_rotation_x(mesh.rotation.x); + mat4_t rotation_matrix_y = mat4_make_rotation_y(mesh.rotation.y); + mat4_t rotation_matrix_z = mat4_make_rotation_z(mesh.rotation.z); + triangles_to_render = NULL; @@ -146,17 +165,21 @@ void update(void) { face_vertices[1] = mesh.vertices[mesh_face.b - 1]; face_vertices[2] = mesh.vertices[mesh_face.c - 1]; - vec3_t transformed_vertices[3]; + vec4_t transformed_vertices[3]; for (int j = 0; j < 3; j++) { - vec3_t transformed_vertex = face_vertices[j]; + vec4_t transformed_vertex = vec4_from_vec3(face_vertices[j]); - transformed_vertex = vec3_rotate_x(transformed_vertex, mesh.rotation.x); - transformed_vertex = vec3_rotate_y(transformed_vertex, mesh.rotation.y); - transformed_vertex = vec3_rotate_z(transformed_vertex, mesh.rotation.z); + // use matrix to scale original matrix + transformed_vertex = mat4_multiply_vec4(scale_matrix, transformed_vertex); - // translate away from camera in z - transformed_vertex.z += 5; + // use matrices to rotate + transformed_vertex = mat4_multiply_vec4(rotation_matrix_x, transformed_vertex); + transformed_vertex = mat4_multiply_vec4(rotation_matrix_y, transformed_vertex); + transformed_vertex = mat4_multiply_vec4(rotation_matrix_z, transformed_vertex); + + // use matrix to translate + transformed_vertex = mat4_multiply_vec4(translation_matrix, transformed_vertex); // save translated vertex in the array of transformed vertices transformed_vertices[j] = transformed_vertex; @@ -164,9 +187,9 @@ void update(void) { if (cull_method == CULL_BACKFACE) { // check backface culling - vec3_t vector_a = transformed_vertices[0]; /* A */ - vec3_t vector_b = transformed_vertices[1]; /* / \ */ - vec3_t vector_c = transformed_vertices[2]; /* C---B */ + vec3_t vector_a = vec3_from_vec4(transformed_vertices[0]); /* A */ + vec3_t vector_b = vec3_from_vec4(transformed_vertices[1]); /* / \ */ + vec3_t vector_c = vec3_from_vec4(transformed_vertices[2]); /* C---B */ // get the vector subtraction of B-A and C-A vec3_t vector_ab = vec3_subtract(vector_b, vector_a); @@ -193,7 +216,7 @@ void update(void) { for (int j = 0; j < 3; j++) { // project the current vertex - vec2_t projected_point = project(transformed_vertices[j]); + vec2_t projected_point = project(vec3_from_vec4(transformed_vertices[j])); // scale and translate the projected points to the center of the screen projected_point.x += (window_width / 2); @@ -221,8 +244,8 @@ int depth_comp(const void* a, const void* b) { triangle_t arg_a = *(const triangle_t*)a; triangle_t arg_b = *(const triangle_t*)b; - if (arg_a.average_depth < arg_b.average_depth) return -1; - if (arg_a.average_depth > arg_b.average_depth) return 1; + if (arg_a.average_depth > arg_b.average_depth) return -1; + if (arg_a.average_depth < arg_b.average_depth) return 1; return 0; } diff --git a/scripts/matrix.c b/scripts/matrix.c new file mode 100644 index 0000000..5ab5d0a --- /dev/null +++ b/scripts/matrix.c @@ -0,0 +1,103 @@ +#include "matrix.h" + +mat4_t mat4_identity(void) { + mat4_t m = {{ + { 1, 0, 0, 0}, + { 0, 1, 0, 0}, + { 0, 0, 1, 0}, + { 0, 0, 0, 1}, + }}; + + return m; +} + +mat4_t mat4_make_scale(float sx, float sy, float sz) { + mat4_t m = mat4_identity(); + m.m[0][0] *= sx; + m.m[1][1] *= sy; + m.m[2][2] *= sz; + + return m; +} + +mat4_t mat4_make_translation(float tx, float ty, float tz) { + /* + * 1 0 0 tx + * 0 1 0 ty + * 0 0 1 tz + * 0 0 0 1 + */ + + mat4_t m = mat4_identity(); + m.m[0][3] = tx; + m.m[1][3] = ty; + m.m[2][3] = tz; + + return m; +} + +mat4_t mat4_make_rotation_y(float ra) { + /* + * cos 0 -sin 0 + * 0 1 0 0 + * sin 0 cos 0 + * 0 0 0 1 + */ + const float cosine = cosf(ra); + const float sine = sinf(ra); + mat4_t m = mat4_identity(); + m.m[0][0] = cosine; + m.m[0][2] = -sine; + m.m[2][0] = sine; + m.m[2][2] = cosine; + + return m; +} + +mat4_t mat4_make_rotation_x(float ra) { + /* + * 1 0 0 0 + * 0 cos sin 0 + * 0 -sin cos 0 + * 0 0 0 1 + */ + const float cosine = cosf(ra); + const float sine = sinf(ra); + mat4_t m = mat4_identity(); + m.m[1][1] = cosine; + m.m[1][2] = sine; + m.m[2][1] = -sine; + m.m[2][2] = cosine; + + return m; +} + + +mat4_t mat4_make_rotation_z(float ra) { + /* + * cos sin 0 0 + * -sin cos 0 0 + * 0 0 1 0 + * 0 0 0 1 + */ + const float cosine = cosf(ra); + const float sine = sinf(ra); + mat4_t m = mat4_identity(); + m.m[0][0] = cosine; + m.m[0][1] = sine; + m.m[1][0] = -sine; + m.m[1][1] = cosine; + + return m; +} + +vec4_t mat4_multiply_vec4(mat4_t m, vec4_t v) { + vec4_t ret = {}; + + ret.x = m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z + m.m[0][3] * v.w; + ret.y = m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z + m.m[1][3] * v.w; + ret.z = m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z + m.m[2][3] * v.w; + ret.w = m.m[3][0] * v.x + m.m[3][1] * v.y + m.m[3][2] * v.z + m.m[3][3] * v.w; + + return ret; +} \ No newline at end of file diff --git a/scripts/matrix.h b/scripts/matrix.h new file mode 100644 index 0000000..2dac80d --- /dev/null +++ b/scripts/matrix.h @@ -0,0 +1,21 @@ +#ifndef MATRIX_H +#define MATRIX_H + +#include +#include "vector.h" + +typedef struct mat4_t mat4_t; +struct mat4_t { + float m[4][4]; +}; + +mat4_t mat4_identity(void); +mat4_t mat4_make_scale(float sx, float sy, float sz); +mat4_t mat4_make_translation(float tx, float ty, float tz); +mat4_t mat4_make_rotation_x(float ra); +mat4_t mat4_make_rotation_y(float ra); +mat4_t mat4_make_rotation_z(float ra); + +vec4_t mat4_multiply_vec4(mat4_t m, vec4_t v); + +#endif \ No newline at end of file diff --git a/scripts/mesh.c b/scripts/mesh.c index 91ac0f8..baab5e9 100644 --- a/scripts/mesh.c +++ b/scripts/mesh.c @@ -11,7 +11,9 @@ mesh_t mesh = { .vertices = NULL, .faces = NULL, - .rotation = { 0, 0, 0 } + .rotation = { 0, 0, 0 }, + .scale = { 1.0, 1.0, 1.0 }, + .translation = { 0, 0, 0 }, }; vec3_t cube_vertices[N_CUBE_VERTICES] = { diff --git a/scripts/mesh.h b/scripts/mesh.h index d0dc32c..5f966c8 100644 --- a/scripts/mesh.h +++ b/scripts/mesh.h @@ -32,6 +32,8 @@ struct mesh_t { vec3_t* vertices; face_t* faces; vec3_t rotation; + vec3_t scale; + vec3_t translation; }; extern mesh_t mesh; diff --git a/scripts/vector.c b/scripts/vector.c index 25ac66f..4366948 100644 --- a/scripts/vector.c +++ b/scripts/vector.c @@ -122,4 +122,22 @@ void vec3_normalize(vec3_t* vertex) { vertex->x /= length; vertex->y /= length; vertex->z /= length; +} + +vec4_t vec4_from_vec3(vec3_t vertex) { + vec4_t ret; + ret.x = vertex.x; + ret.y = vertex.y; + ret.z = vertex.z; + ret.w = 1; + + return ret; +} + +vec3_t vec3_from_vec4(vec4_t v) { + return (vec3_t) { + .x = v.x, + .y = v.y, + .z = v.z, + }; } \ No newline at end of file diff --git a/scripts/vector.h b/scripts/vector.h index 81e1ec9..eeb85ef 100644 --- a/scripts/vector.h +++ b/scripts/vector.h @@ -12,6 +12,10 @@ typedef struct { float z; } vec3_t; +typedef struct { + float x, y, z, w; +} vec4_t; + // TODO: Add functions to manipulate vectors 2D and 3D // ... @@ -36,4 +40,7 @@ float vec3_length(const vec3_t vector); float vec3_dot(const vec3_t a, const vec3_t b); void vec3_normalize(vec3_t* vertex); +vec4_t vec4_from_vec3(vec3_t vertex); +vec3_t vec3_from_vec4(vec4_t v); + #endif