From e3c463d2f14915dfcf63bb872b6e9f72be0c7724 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Mon, 24 Jun 2024 00:04:21 +0100 Subject: [PATCH] Add ability to draw filled triangle --- include/rasteriser/rasteriser.h | 1 + src/rasteriser/main.c | 3 +- src/rasteriser/rasteriser.c | 54 +++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/include/rasteriser/rasteriser.h b/include/rasteriser/rasteriser.h index 3cf639c..894a883 100644 --- a/include/rasteriser/rasteriser.h +++ b/include/rasteriser/rasteriser.h @@ -21,6 +21,7 @@ typedef struct { void draw_wireframe_triangle(window_t *wnd, triangle_t triangle, colour_t colour); +void draw_filled_triangle(window_t *wnd, triangle_t triangle, colour_t colour); void draw_line(window_t *wnd, line_t line, colour_t colour); #endif // !RASTERISER_H diff --git a/src/rasteriser/main.c b/src/rasteriser/main.c index 0d9738d..4fc2bd1 100644 --- a/src/rasteriser/main.c +++ b/src/rasteriser/main.c @@ -40,8 +40,9 @@ int main(void) { clear_window(&window, bg); + draw_filled_triangle(&window, triangle, (colour_t){.colour = 0x00ff00ff}); draw_wireframe_triangle(&window, triangle, - (colour_t){.colour = 0xffffffff}); + (colour_t){.colour = 0x000000ff}); swap_buffers(&window); } diff --git a/src/rasteriser/rasteriser.c b/src/rasteriser/rasteriser.c index da68e02..79b61d2 100644 --- a/src/rasteriser/rasteriser.c +++ b/src/rasteriser/rasteriser.c @@ -4,18 +4,60 @@ #include "vector/vec.h" #include "window/window.h" #include +#include #include +#include #include internal list_float_t *interpolate(i32 i0, f32 d0, i32 i1, f32 d1); +internal inline void order_triangle_points(triangle_t *triangle); + void draw_wireframe_triangle(window_t *wnd, triangle_t triangle, colour_t colour) { + order_triangle_points(&triangle); + draw_line(wnd, (line_t){triangle.p0, triangle.p1}, colour); draw_line(wnd, (line_t){triangle.p1, triangle.p2}, colour); draw_line(wnd, (line_t){triangle.p2, triangle.p0}, colour); } +void draw_filled_triangle(window_t *wnd, triangle_t triangle, colour_t colour) { + order_triangle_points(&triangle); + + i32 x0 = triangle.p0.x; + i32 y0 = triangle.p0.y; + i32 x1 = triangle.p1.x; + i32 y1 = triangle.p1.y; + i32 x2 = triangle.p2.x; + i32 y2 = triangle.p2.y; + + list_float_t *x01 = interpolate(y0, x0, y1, x1); + list_float_t *x12 = interpolate(y1, x1, y2, x2); + list_float_t *x02 = interpolate(y0, x0, y2, x2); + list_float_t *x012 = NULL; + + list_pop(x01); // Last element of x01 is a duplicate of first element in x12 + list_merge(f32, x012, x01, x12); + + list_float_t *x_left; + list_float_t *x_right; + u64 middle = (u64)(floorf((f32)(x02->count) / 2.0f)); + if (list_get(x02, middle) < list_get(x012, middle)) { + x_left = x02; + x_right = x012; + } else { + x_left = x012; + x_right = x02; + } + + for (i64 y = y0; y <= y2; ++y) { + for (i64 x = list_get(x_left, y - y0); x < list_get(x_right, y - y0); ++x) { + set_pixel(wnd, x, y, colour); + } + } +} + void draw_line(window_t *wnd, line_t line, colour_t colour) { list_float_t *values = NULL; @@ -86,3 +128,15 @@ internal list_float_t *interpolate(i32 i0, f32 d0, i32 i1, f32 d1) { return values; } + +internal inline void order_triangle_points(triangle_t *triangle) { + if (triangle->p1.y < triangle->p0.y) { + vec_swap(vec2i_t, triangle->p0, triangle->p1); + } + if (triangle->p2.y < triangle->p0.y) { + vec_swap(vec2i_t, triangle->p0, triangle->p2); + } + if (triangle->p2.y < triangle->p1.y) { + vec_swap(vec2i_t, triangle->p1, triangle->p2); + } +}