diff --git a/include/window.h b/include/window.h index b1aadd1..58943b6 100644 --- a/include/window.h +++ b/include/window.h @@ -61,8 +61,8 @@ void clear_window(const window_t *wnd, colour_t colour); void swap_buffers(const window_t *wnd); void draw_point(const window_t *wnd, point_t p, colour_t colour); void draw_line(const window_t *wnd, const line_t *ln, colour_t colour); -void draw_triangle(const window_t *wnd, const triangle_t *triangle, - colour_t colour); +void draw_triangle(const window_t *wnd, triangle_t triangle, colour_t colour); +void fill_triangle(const window_t *wnd, triangle_t triangle, colour_t colour); void draw_rect(const window_t *wnd, rect_t rect, colour_t colour); void fill_rect(const window_t *wnd, rect_t rect, colour_t colour); diff --git a/src/window.c b/src/window.c index de0c873..9f299fe 100644 --- a/src/window.c +++ b/src/window.c @@ -79,17 +79,58 @@ void draw_line(const window_t *wnd, const line_t *ln, colour_t colour) { SDL_RenderDrawLine(wnd->renderer, ln->p0.x, ln->p0.y, ln->p1.x, ln->p1.y); } -void draw_triangle(const window_t *wnd, const triangle_t *triangle, - colour_t colour) { - line_t ln0 = {triangle->p0, triangle->p1}; - line_t ln1 = {triangle->p0, triangle->p2}; - line_t ln2 = {triangle->p1, triangle->p2}; +void draw_triangle(const window_t *wnd, triangle_t triangle, colour_t colour) { + line_t ln0 = {triangle.p0, triangle.p1}; + line_t ln1 = {triangle.p0, triangle.p2}; + line_t ln2 = {triangle.p1, triangle.p2}; draw_line(wnd, &ln0, colour); draw_line(wnd, &ln1, colour); draw_line(wnd, &ln2, colour); } +INTERNAL inline i32 min(i32 a, i32 b, i32 c) { + i32 _min = a <= b ? a : b; + return _min <= c ? _min : c; +} + +INTERNAL inline i32 max(i32 a, i32 b, i32 c) { + i32 _max = a >= b ? a : b; + return _max >= c ? _max : c; +} + +INTERNAL inline i32 half_space(i32 x1, i32 x2, i32 y1, i32 y2, i32 x, i32 y) { + return (x2 - x1) * (y - y1) - (y2 - y1) * (x - x1); +} + +void fill_triangle(const window_t *wnd, triangle_t triangle, colour_t colour) { + // Basic triangle filling algorithm from + // https://web.archive.org/web/20050408192410/http://sw-shader.sourceforge.net/rasterizer.html + i32 x1 = triangle.p0.x; + i32 x2 = triangle.p1.x; + i32 x3 = triangle.p2.x; + + i32 y1 = triangle.p0.y; + i32 y2 = triangle.p1.y; + i32 y3 = triangle.p2.y; + + // Find bounding rect + i32 min_x = min(x1, x2, x3); + i32 max_x = max(x1, x2, x3); + i32 min_y = min(y1, y2, y3); + i32 max_y = max(y1, y2, y3); + + for (i32 y = min_y; y < max_y; ++y) { + for (i32 x = min_x; x < max_x; ++x) { + if (half_space(x2, x1, y2, y1, x, y) > 0 && + half_space(x3, x2, y3, y2, x, y) > 0 && + half_space(x1, x3, y1, y3, x, y) > 0) { + draw_point(wnd, (point_t){x, y}, colour); + } + } + } +} + void draw_rect(const window_t *wnd, rect_t rect, colour_t colour) { set_colour(wnd, colour);