diff --git a/output.png b/output.png index 56e8cbe..c2ebc45 100644 Binary files a/output.png and b/output.png differ diff --git a/src/obj.c b/src/obj.c index d26fb61..a77a4d8 100644 --- a/src/obj.c +++ b/src/obj.c @@ -12,7 +12,6 @@ #include #define TRIANGLE_VERTICES 3 -#define CAMERA_DISTANCE 5.0f #define DEPTH_MAX 255 #define V2(T, ELEM_T, X0, Y0, X1, Y1) \ @@ -23,9 +22,10 @@ #define dot_v2(V1, V2) ((f32)V1.x * (f32)V2.x + (f32)V1.y * (f32)V2.y) #define dot_v3(V1, V2) \ ((f32)V1.x * (f32)V2.x + (f32)V1.y * (f32)V2.y + (f32)V1.z * (f32)V2.z) +#define magnitude_v3(V) (sqrtf(dot_v3(V, V))) #define normalise_v3(V) \ do { \ - f32 magnitude = sqrtf(dot_v3(V, V)); \ + f32 magnitude = magnitude_v3(V); \ V.x /= magnitude; \ V.y /= magnitude; \ V.z /= magnitude; \ @@ -108,6 +108,7 @@ internal void fill_triangle(Render *render, V3f vertices[TRIANGLE_VERTICES], Image *texture, RenderType type); internal M4x4f lookat(V3f eye, V3f target, V3f up); internal M4x4f viewport(f32 x, f32 y, u64 w, u64 h); +internal M4x4f projection(f32 coeff); internal TriangleBBox get_triangle_bbox(const Image *img, V3f vertices[TRIANGLE_VERTICES]); internal V3f get_barycentric_coords(f32 d00, f32 d01, f32 d11, f32 denom, @@ -116,19 +117,10 @@ internal V3f get_barycentric_coords(f32 d00, f32 d01, f32 d11, f32 denom, internal V3f get_viewport_vertex(const V3f *vertex, const Image *img); V3f g_light_dir = {0.0f, 0.0f, 1.0f}; - -// clang-format off -M4x4f g_cam_matrix = { - .row0 = {1.0f, 0.0f, 0.0f, 0.0f}, - .row1 = {0.0f, 1.0f, 0.0f, 0.0f}, - .row2 = {0.0f, 0.0f, 1.0f, 0.0f}, - .row3 = {0.0f, 0.0f, -1.0f / CAMERA_DISTANCE, 1.0f}, -}; -// clang-format on - -V3f g_eye = {0.2f, 0.1f, 0.7f}; +V3f g_eye = {0.2f, 0.1f, 0.75f}; V3f g_target = {0}; V3f g_up = {0.0f, 1.0f, 0.0f}; +M4x4f g_cam_matrix = mat4x4_identity; Model load_obj_file(Arena *arena, const char *filename, const char *texture) { if (!arena) { @@ -225,10 +217,17 @@ bool init_render(Arena *arena, Render *render, u64 width, u64 height) { void render_model(const Model *model, Render *render, Colour colour, RenderType type, ColourType colour_type, - ProjectionType projection) { + ProjectionType projection_type) { Triangle triangle; M4x4f model_view = lookat(g_eye, g_target, g_up); + // Calculate projection matrix + V3f cam = V3(V3f, f32, g_target.x, g_target.y, g_target.z, g_eye.x, g_eye.y, + g_eye.z); + normalise_v3(cam); + f32 coeff = -1.0f / magnitude_v3(cam) * 0.5f; + g_cam_matrix = projection(coeff); + for (u64 i = 0; i < model->triangles->count; ++i) { triangle = list_get(model->triangles, i); if (colour_type == COLOUR_TYPE_RANDOM) { @@ -237,14 +236,14 @@ void render_model(const Model *model, Render *render, Colour colour, .b = rand() % UINT8_MAX, .a = 255}; } - render_triangle(&triangle, model, render, colour, type, projection, + render_triangle(&triangle, model, render, colour, type, projection_type, model_view); } } internal void render_triangle(const Triangle *triangle, const Model *model, Render *render, Colour colour, RenderType type, - ProjectionType projection, M4x4f mv) { + ProjectionType projection_type, M4x4f mv) { Image *img = &(render->img); V3f vertices[TRIANGLE_VERTICES] = { list_get(model->vertices, triangle->p0), @@ -276,8 +275,9 @@ internal void render_triangle(const Triangle *triangle, const Model *model, } // Basic perspective projection - if (projection == PROJECTION_TYPE_PERSPECTIVE) { + if (projection_type == PROJECTION_TYPE_PERSPECTIVE) { V4f vertex; + for (u64 i = 0; i < TRIANGLE_VERTICES; ++i) { vertex = (V4f){ .x = vertices[i].x, @@ -431,6 +431,17 @@ internal M4x4f viewport(f32 x, f32 y, u64 w, u64 h) { return output; } +internal M4x4f projection(f32 coeff) { + // clang-format off + return (M4x4f){ + .row0 = {1.0f, 0.0f, 0.0f, 0.0f}, + .row1 = {0.0f, 1.0f, 0.0f, 0.0f}, + .row2 = {0.0f, 0.0f, 1.0f, 0.0f}, + .row3 = {0.0f, 0.0f, coeff, 1.0f}, + }; + // clang-format on +} + internal TriangleBBox get_triangle_bbox(const Image *img, V3f vertices[TRIANGLE_VERTICES]) { f32 x0 = min(vertices[0].x, min(vertices[1].x, vertices[2].x));