Add basic function to fill triangle

This commit is contained in:
Abdelrahman Said 2024-01-21 00:19:21 +00:00
parent 63f119c1b2
commit fa82203681
2 changed files with 48 additions and 7 deletions

View File

@ -61,8 +61,8 @@ void clear_window(const window_t *wnd, colour_t colour);
void swap_buffers(const window_t *wnd); void swap_buffers(const window_t *wnd);
void draw_point(const window_t *wnd, point_t p, colour_t colour); 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_line(const window_t *wnd, const line_t *ln, colour_t colour);
void draw_triangle(const window_t *wnd, const triangle_t *triangle, void draw_triangle(const window_t *wnd, triangle_t triangle, colour_t colour);
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 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); void fill_rect(const window_t *wnd, rect_t rect, colour_t colour);

View File

@ -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); 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, void draw_triangle(const window_t *wnd, triangle_t triangle, colour_t colour) {
colour_t colour) { line_t ln0 = {triangle.p0, triangle.p1};
line_t ln0 = {triangle->p0, triangle->p1}; line_t ln1 = {triangle.p0, triangle.p2};
line_t ln1 = {triangle->p0, triangle->p2}; line_t ln2 = {triangle.p1, triangle.p2};
line_t ln2 = {triangle->p1, triangle->p2};
draw_line(wnd, &ln0, colour); draw_line(wnd, &ln0, colour);
draw_line(wnd, &ln1, colour); draw_line(wnd, &ln1, colour);
draw_line(wnd, &ln2, 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) { void draw_rect(const window_t *wnd, rect_t rect, colour_t colour) {
set_colour(wnd, colour); set_colour(wnd, colour);