diff --git a/include/list/typed_list.h b/include/list/typed_list.h index 891ad3c..c5fddf6 100644 --- a/include/list/typed_list.h +++ b/include/list/typed_list.h @@ -1,7 +1,8 @@ #ifndef TYPED_LIST_H #define TYPED_LIST_H -#include "c_cpp_aliases/aliases.h" +#include "aliases.h" +#include "mem_arena.h" #include #include @@ -17,39 +18,27 @@ u64 count; \ } LIST_TYPE_NAME(T) -#define list_create(T) \ - (LIST_TYPE_NAME(T) *)_create_list(sizeof(T), BASE_LIST_CAPACITY) -#define list_create_with_capacity(T, CAPACITY) \ - (LIST_TYPE_NAME(T) *)_create_list(sizeof(T), CAPACITY) +#define list_create(T, ARENA) \ + (LIST_TYPE_NAME(T) *)_create_list(ARENA, sizeof(T), BASE_LIST_CAPACITY) +#define list_create_with_capacity(T, ARENA, CAPACITY) \ + (LIST_TYPE_NAME(T) *)_create_list(ARENA, sizeof(T), CAPACITY) -#define list_destroy(T, LP) \ - do { \ - munmap(LP->items, sizeof(T) * LP->capacity); \ - LP->items = NULL; \ - LP->count = 0; \ - LP->capacity = 0; \ - munmap(LP, sizeof(LIST_TYPE_NAME(T))); \ - } while (0) - -#define _increase_list_capacity(T, LP, CAP) \ +#define _increase_list_capacity(T, ARENA, LP, CAP) \ do { \ u64 new_capacity = LP->capacity * 2; \ - T *tmp = _alloc_for_list(sizeof(T) * new_capacity); \ + T *tmp = _alloc_for_list(ARENA, sizeof(T) * new_capacity); \ assert(tmp != NULL && "Failed to increase capacity"); \ \ memcpy(tmp, LP->items, sizeof(T) * LP->count); \ \ - i32 deallocated = munmap(LP->items, sizeof(T) * LP->capacity); \ - assert(deallocated == 0 && "Failed to deallocate old memory"); \ - \ LP->capacity = new_capacity; \ LP->items = tmp; \ } while (0) -#define list_append(T, LP, ITEM) \ +#define list_append(T, ARENA, LP, ITEM) \ do { \ if (LP->count + 1 >= LP->capacity) { \ - _increase_list_capacity(T, LP, LP->capacity * 2); \ + _increase_list_capacity(T, ARENA, LP, LP->capacity * 2); \ } \ \ LP->items[(LP->count)++] = ITEM; \ @@ -59,13 +48,13 @@ #define list_get(LP, IDX) LP->items[IDX] -#define list_merge(T, DST, LP1, LP2) \ +#define list_merge(T, ARENA, DST, LP1, LP2) \ do { \ u64 new_count = LP1->count + LP2->count; \ u64 capacity = \ new_count < BASE_LIST_CAPACITY ? BASE_LIST_CAPACITY : new_count * 2; \ \ - DST = (LIST_TYPE_NAME(T) *)_create_list(new_count, capacity); \ + DST = (LIST_TYPE_NAME(T) *)_create_list(ARENA, new_count, capacity); \ assert(DST != NULL && "Failed to allocate new list"); \ \ u64 lp1_copy_size = sizeof(T) * LP1->count; \ @@ -79,7 +68,7 @@ MAKE_LIST_TYPE(void); -list_void_t *_create_list(u64 size, u64 count); -void *_alloc_for_list(u64 size); +list_void_t *_create_list(Arena *arena, u64 size, u64 count); +void *_alloc_for_list(Arena *arena, u64 size); #endif // !TYPED_LIST_H diff --git a/include/rasteriser/rasteriser.h b/include/rasteriser/rasteriser.h index 894a883..1d9a20f 100644 --- a/include/rasteriser/rasteriser.h +++ b/include/rasteriser/rasteriser.h @@ -1,8 +1,9 @@ #ifndef RASTERISER_H #define RASTERISER_H -#include "c_cpp_aliases/aliases.h" +#include "aliases.h" #include "list/typed_list.h" +#include "mem_arena.h" #include "vector/vec.h" #include "window/window.h" @@ -17,11 +18,17 @@ typedef struct { vec2i_t p0; vec2i_t p1; vec2i_t p2; + f32 h0; + f32 h1; + f32 h2; } triangle_t; -void draw_wireframe_triangle(window_t *wnd, triangle_t triangle, +void draw_wireframe_triangle(window_t *wnd, Arena *arena, 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); +void draw_filled_triangle(window_t *wnd, Arena *arena, triangle_t triangle, + colour_t colour); +void draw_shaded_triangle(window_t *wnd, Arena *arena, triangle_t triangle, + colour_t colour); +void draw_line(window_t *wnd, Arena *arena, line_t line, colour_t colour); #endif // !RASTERISER_H diff --git a/include/window/window.h b/include/window/window.h index 3c2f4b1..1ac1d71 100644 --- a/include/window/window.h +++ b/include/window/window.h @@ -1,7 +1,7 @@ #ifndef WINDOW_H #define WINDOW_H -#include "c_cpp_aliases/aliases.h" +#include "aliases.h" #include "vector/vec.h" #include #include diff --git a/src/list/typed_list.c b/src/list/typed_list.c index 2063e7f..80953a3 100644 --- a/src/list/typed_list.c +++ b/src/list/typed_list.c @@ -1,16 +1,18 @@ #include "list/typed_list.h" +#include "mem_arena.h" #include #include #include #include -list_void_t *_create_list(u64 size, u64 count) { - list_void_t *list = (list_void_t *)_alloc_for_list(sizeof(list_void_t)); +list_void_t *_create_list(Arena *arena, u64 size, u64 count) { + list_void_t *list = + (list_void_t *)_alloc_for_list(arena, sizeof(list_void_t)); if (!list) { return NULL; } - list->items = (void *)_alloc_for_list(size * count); + list->items = (void *)_alloc_for_list(arena, size * count); if (!list->items) { munmap(list, sizeof(list_void_t)); return NULL; @@ -23,7 +25,6 @@ list_void_t *_create_list(u64 size, u64 count) { return list; } -void *_alloc_for_list(u64 size) { - return mmap(NULL, size, PROT_READ | PROT_WRITE, - MAP_ANON | MAP_NORESERVE | MAP_SHARED, -1, 0); +void *_alloc_for_list(Arena *arena, u64 size) { + return wapp_mem_arena_alloc(arena, size); } diff --git a/src/rasteriser/main.c b/src/rasteriser/main.c index 4fc2bd1..f2f5f80 100644 --- a/src/rasteriser/main.c +++ b/src/rasteriser/main.c @@ -1,3 +1,5 @@ +#include "mem_arena.h" +#include "mem_utils.h" #include "misc/misc_utils.h" #include "rasteriser/rasteriser.h" #include "vector/vec.h" @@ -27,8 +29,17 @@ int main(void) { .p0 = {-200, -250}, .p1 = {200, 50}, .p2 = {20, 250}, + .h0 = 0, + .h1 = 0, + .h2 = 1, }; + Arena *arena = NULL; + u64 capacity = 10ull * 1024ull * 1024ull * 1024ull; + if (!wapp_mem_arena_init(&arena, capacity, WAPP_MEM_ALLOC_RESERVE, false)) { + return EXIT_FAILURE; + } + while (running) { while (SDL_PollEvent(&event)) { switch (event.type) { @@ -40,13 +51,17 @@ int main(void) { clear_window(&window, bg); - draw_filled_triangle(&window, triangle, (colour_t){.colour = 0x00ff00ff}); - draw_wireframe_triangle(&window, triangle, + draw_shaded_triangle(&window, arena, triangle, + (colour_t){.colour = 0x00ff00ff}); + draw_wireframe_triangle(&window, arena, triangle, (colour_t){.colour = 0x000000ff}); swap_buffers(&window); + + wapp_mem_arena_clear(arena); } + wapp_mem_arena_destroy(&arena); close_window(&window); return EXIT_SUCCESS; diff --git a/src/rasteriser/rasteriser.c b/src/rasteriser/rasteriser.c index 79b61d2..cb404ed 100644 --- a/src/rasteriser/rasteriser.c +++ b/src/rasteriser/rasteriser.c @@ -1,6 +1,8 @@ #include "rasteriser/rasteriser.h" -#include "c_cpp_aliases/aliases.h" +#include "aliases.h" #include "list/typed_list.h" +#include "math/math_utils.h" +#include "mem_arena.h" #include "vector/vec.h" #include "window/window.h" #include @@ -9,20 +11,22 @@ #include #include -internal list_float_t *interpolate(i32 i0, f32 d0, i32 i1, f32 d1); +internal list_float_t *interpolate(Arena *arena, 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, +void draw_wireframe_triangle(window_t *wnd, Arena *arena, 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); + draw_line(wnd, arena, (line_t){triangle.p0, triangle.p1}, colour); + draw_line(wnd, arena, (line_t){triangle.p1, triangle.p2}, colour); + draw_line(wnd, arena, (line_t){triangle.p2, triangle.p0}, colour); } -void draw_filled_triangle(window_t *wnd, triangle_t triangle, colour_t colour) { +void draw_filled_triangle(window_t *wnd, Arena *arena, triangle_t triangle, + colour_t colour) { order_triangle_points(&triangle); i32 x0 = triangle.p0.x; @@ -32,13 +36,13 @@ void draw_filled_triangle(window_t *wnd, triangle_t triangle, colour_t colour) { 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 *x01 = interpolate(arena, y0, x0, y1, x1); + list_float_t *x12 = interpolate(arena, y1, x1, y2, x2); + list_float_t *x02 = interpolate(arena, 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_merge(f32, arena, x012, x01, x12); list_float_t *x_left; list_float_t *x_right; @@ -52,18 +56,86 @@ void draw_filled_triangle(window_t *wnd, triangle_t triangle, colour_t colour) { } for (i64 y = y0; y <= y2; ++y) { - for (i64 x = list_get(x_left, y - y0); x < list_get(x_right, y - y0); ++x) { + i32 index = y - y0; + for (i64 x = (i64)list_get(x_left, index); x < list_get(x_right, index); + ++x) { set_pixel(wnd, x, y, colour); } } } -void draw_line(window_t *wnd, line_t line, colour_t colour) { +void draw_shaded_triangle(window_t *wnd, Arena *arena, 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(arena, y0, x0, y1, x1); + list_float_t *x12 = interpolate(arena, y1, x1, y2, x2); + list_float_t *x02 = interpolate(arena, 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, arena, x012, x01, x12); + + f32 h0 = triangle.h0; + f32 h1 = triangle.h1; + f32 h2 = triangle.h2; + list_float_t *h01 = interpolate(arena, y0, h0, y1, h1); + list_float_t *h12 = interpolate(arena, y1, h1, y2, h2); + list_float_t *h02 = interpolate(arena, y0, h0, y2, h2); + list_float_t *h012 = NULL; + + list_pop(h01); // Last element of h01 is a duplicate of first element in h12 + list_merge(f32, arena, h012, h01, h12); + + list_float_t *x_left; + list_float_t *x_right; + list_float_t *h_left; + list_float_t *h_right; + u64 middle = (u64)(floorf((f32)(x02->count) / 2.0f)); + if (list_get(x02, middle) < list_get(x012, middle)) { + x_left = x02; + h_left = h02; + x_right = x012; + h_right = h012; + } else { + x_left = x012; + h_left = h012; + x_right = x02; + h_right = h02; + } + + list_float_t *h_segment = NULL; + i32 index = -1; + i64 xl = -1; + i64 xr = -1; + colour_t shaded_colour = (colour_t){0}; + + for (i64 y = y0; y <= y2; ++y) { + index = y - y0; + xl = (i64)list_get(x_left, index); + xr = (i64)list_get(x_right, index); + for (i64 x = xl; x < xr; ++x) { + h_segment = interpolate(arena, xl, list_get(h_left, index), xr, + list_get(h_right, index)); + shaded_colour = colour_mul(colour, list_get(h_segment, x - xl)); + set_pixel(wnd, x, y, shaded_colour); + } + } +} + +void draw_line(window_t *wnd, Arena *arena, line_t line, colour_t colour) { list_float_t *values = NULL; if (abs(line.p1.x - line.p0.x) > abs(line.p1.y - line.p0.y)) { if (line.p1.x < line.p0.x) { - vec_swap(vec2i_t, line.p0, line.p1); + swap(vec2i_t, line.p0, line.p1); } i32 x0 = line.p0.x; @@ -71,7 +143,7 @@ void draw_line(window_t *wnd, line_t line, colour_t colour) { i32 x1 = line.p1.x; i32 y1 = line.p1.y; - values = interpolate(x0, y0, x1, y1); + values = interpolate(arena, x0, y0, x1, y1); if (!values) { return; } @@ -81,7 +153,7 @@ void draw_line(window_t *wnd, line_t line, colour_t colour) { } } else { if (line.p1.y < line.p0.y) { - vec_swap(vec2i_t, line.p0, line.p1); + swap(vec2i_t, line.p0, line.p1); } i32 x0 = line.p0.x; @@ -89,7 +161,7 @@ void draw_line(window_t *wnd, line_t line, colour_t colour) { i32 x1 = line.p1.x; i32 y1 = line.p1.y; - values = interpolate(y0, x0, y1, x1); + values = interpolate(arena, y0, x0, y1, x1); if (!values) { return; } @@ -98,22 +170,21 @@ void draw_line(window_t *wnd, line_t line, colour_t colour) { set_pixel(wnd, (i32)(list_get(values, y - y0)), y, colour); } } - - list_destroy(f32, values); } -internal list_float_t *interpolate(i32 i0, f32 d0, i32 i1, f32 d1) { +internal list_float_t *interpolate(Arena *arena, i32 i0, f32 d0, i32 i1, + f32 d1) { list_float_t *values; if (i0 == i1) { - values = list_create_with_capacity(f32, 20); + values = list_create_with_capacity(f32, arena, 20); if (values) { - list_append(f32, values, d0); + list_append(f32, arena, values, d0); } return values; } - values = list_create(f32); + values = list_create(f32, arena); if (!values) { return NULL; } @@ -122,7 +193,7 @@ internal list_float_t *interpolate(i32 i0, f32 d0, i32 i1, f32 d1) { f32 d = d0; for (i32 i = i0; i <= i1; ++i) { - list_append(f32, values, d); + list_append(f32, arena, values, d); d += a; } @@ -131,12 +202,15 @@ internal list_float_t *interpolate(i32 i0, f32 d0, i32 i1, f32 d1) { internal inline void order_triangle_points(triangle_t *triangle) { if (triangle->p1.y < triangle->p0.y) { - vec_swap(vec2i_t, triangle->p0, triangle->p1); + swap(vec2i_t, triangle->p0, triangle->p1); + swap(f32, triangle->h0, triangle->h1); } if (triangle->p2.y < triangle->p0.y) { - vec_swap(vec2i_t, triangle->p0, triangle->p2); + swap(vec2i_t, triangle->p0, triangle->p2); + swap(f32, triangle->h0, triangle->h2); } if (triangle->p2.y < triangle->p1.y) { - vec_swap(vec2i_t, triangle->p1, triangle->p2); + swap(vec2i_t, triangle->p1, triangle->p2); + swap(f32, triangle->h1, triangle->h2); } }