From 7097b7fb57e7db34f62ead564a8940ac216d7b07 Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Mon, 13 Oct 2025 16:22:10 +0100 Subject: [PATCH] Implement simple line drawing --- build.sh | 4 ++-- main.c | 11 ++++++++++- maths.c | 15 +++++++++++++++ maths.h | 24 ++++++++++++++++++++++++ renderer.c | 55 ++++++++++++++++++++++++++++++++++++++++++------------ renderer.h | 5 ++++- 6 files changed, 98 insertions(+), 16 deletions(-) create mode 100644 maths.c create mode 100644 maths.h diff --git a/build.sh b/build.sh index 0093132..6465096 100755 --- a/build.sh +++ b/build.sh @@ -3,9 +3,9 @@ cc="gcc" warn="-std=c23 -pedantic -Wall -Wextra" opt="-O2 -march=native" -libs="-I/usr/include/libdrm -ldrm" +libs="-I/usr/include/libdrm -ldrm -lm" defs="-D_POSIX_C_SOURCE=200809L" $cc $flags $libs $defs \ -o asteroids \ - fb.c input.c main.c renderer.c + fb.c input.c main.c maths.c renderer.c diff --git a/main.c b/main.c index 63aac51..216787c 100644 --- a/main.c +++ b/main.c @@ -5,9 +5,17 @@ #include #define MAX(a, b) ((a) < (b) ? (b) : (a)) +#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) static bool quit = false; +static const vec2_t ship[] = { + { 0.0, 0.1 }, + { 0.05, -0.1 }, + { 0.0, -0.05 }, + { -0.05, -0.1 }, +}; + static void key_press_callback(int key) { switch (key) { @@ -45,7 +53,8 @@ int main() if (FD_ISSET(drm_fd, &set)) { renderer_handle(); - renderer_draw(); + renderer_clear(); + renderer_draw(ship, NELEMS(ship)); renderer_swap(); } } diff --git a/maths.c b/maths.c new file mode 100644 index 0000000..126c4c4 --- /dev/null +++ b/maths.c @@ -0,0 +1,15 @@ +#include "maths.h" + +vec3_t vec2_extend(vec2_t v) +{ + return (vec3_t) { v.x, v.y, 1 }; +} + +vec3_t mat3_mul_vec3(mat3_t m, vec3_t v) +{ + return (vec3_t) { + .x = m.x.x * v.x + m.y.x * v.y + m.z.x * v.z, + .y = m.x.y * v.x + m.y.y * v.y + m.z.y * v.z, + .z = m.x.z * v.x + m.y.z * v.y + m.z.z * v.z, + }; +} diff --git a/maths.h b/maths.h new file mode 100644 index 0000000..c38348a --- /dev/null +++ b/maths.h @@ -0,0 +1,24 @@ +#ifndef MATHS_H +#define MATHS_H + +typedef struct { + float x; + float y; +} vec2_t; + +typedef struct { + float x; + float y; + float z; +} vec3_t; + +typedef struct { + vec3_t x; + vec3_t y; + vec3_t z; +} mat3_t; + +vec3_t vec2_extend(vec2_t v); +vec3_t mat3_mul_vec3(mat3_t m, vec3_t v); + +#endif diff --git a/renderer.c b/renderer.c index bc8ceb1..a413217 100644 --- a/renderer.c +++ b/renderer.c @@ -4,10 +4,14 @@ #include #include +#include +#include #include #include #include +#define MAX_VERTS_PER_DRAW 8U + static int drm_fd; static drmModeConnector *conn; static drmModeCrtc *crtc; @@ -17,18 +21,35 @@ static fb_info_t fbs[2]; static int front, back; static uint32_t width, height; +static mat3_t view; + +static vec3_t vert_buf[MAX_VERTS_PER_DRAW]; + static void page_flip_handler(int, unsigned, unsigned, unsigned, void *) { } -static void -set_pixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) +static void set_pixel(uint32_t x, uint32_t y) { - /* x %= width; */ - /* y %= height; */ + x %= width; + y %= height; const uint32_t offset = y * (fbs[back].pitch / 4) + x; - assert(offset < fbs[back].size); - fbs[back].buf[offset] = (r << 16) | (g << 8) | b; + fbs[back].buf[offset] = 0xff'ff'ff; +} + +static void draw_line(vec3_t v1, vec3_t v2) +{ + const float delta_x = v2.x - v1.x; + const float delta_y = v2.y - v1.y; + const float step = fmaxf(fabsf(delta_x), fabsf(delta_y)); + if (step != 0.0) { + const float step_x = delta_x / step; + const float step_y = delta_y / step; + for (unsigned i = 0; i <= step; ++i) + set_pixel(roundf(v1.x + i * step_x), roundf(v1.y + i * step_y)); + } else { + set_pixel(roundf(v1.x), roundf(v1.y)); + } } renderer_params_t renderer_init() @@ -59,9 +80,17 @@ renderer_params_t renderer_init() width = mode.hdisplay; height = mode.vdisplay; + const float aspect = (float)width / (float)height; + const float scale = (float)height / 2.0f; + view = (mat3_t) { + { scale, 0, 0 }, + { 0, -scale, 0 }, + { aspect * scale, scale, 1 }, + }; + return (renderer_params_t) { .drm_fd = drm_fd, - .aspect = (float)mode.hdisplay / (float)mode.vdisplay, + .aspect = aspect, }; } @@ -103,10 +132,12 @@ void renderer_swap() back = (back + 1) & 1; } -void renderer_draw() +void renderer_draw(const vec2_t *vs, unsigned count) { - for (unsigned y = 0; y < height; ++y) { - for (unsigned x = 0; x < width; ++x) - set_pixel(x, y, (x * 255) / width, (y * 255) / height, 128); - } + assert(count < MAX_VERTS_PER_DRAW); + for (unsigned i = 0; i < count; ++i) + vert_buf[i] = mat3_mul_vec3(view, vec2_extend(vs[i])); + for (unsigned i = 1; i < count; ++i) + draw_line(vert_buf[i - 1], vert_buf[i]); + draw_line(vert_buf[count - 1], vert_buf[0]); } diff --git a/renderer.h b/renderer.h index c562d79..71fed06 100644 --- a/renderer.h +++ b/renderer.h @@ -1,6 +1,8 @@ #ifndef RENDERER_H #define RENDERER_H +#include "maths.h" + #include typedef struct { @@ -15,5 +17,6 @@ void renderer_handle(); void renderer_clear(); void renderer_swap(); -void renderer_draw(); +void renderer_draw(const vec2_t *vs, unsigned count); + #endif