From ea3f43a1f1f96152e77ebb709955a6851433a6b9 Mon Sep 17 00:00:00 2001 From: opfez Date: Sat, 23 Oct 2021 10:51:41 +0200 Subject: [PATCH] starting 3d --- main.c | 172 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 121 insertions(+), 51 deletions(-) diff --git a/main.c b/main.c index dbcf680..383f061 100644 --- a/main.c +++ b/main.c @@ -27,9 +27,17 @@ typedef struct { } sdl_state_t; typedef struct { - int x, y; + double x, y; } vec2_t; +typedef struct { + double x, y, z; +} vec3_t; + +typedef struct { + double range; +} cam_t; + typedef struct { vec2_t a, b, c; } triangle_t; @@ -37,17 +45,25 @@ typedef struct { #define max(x, y) ((x) > (y) ? (x) : (y)) #define min(x, y) ((x) < (y) ? (x) : (y)) #define swap(x, y) do { \ - (x) ^= (y); \ - (y) ^= (x); \ - (x) ^= (y); \ + (x) ^= (y); \ + (y) ^= (x); \ + (x) ^= (y); \ } while (0) +void +swapd(double *a, double *b) +{ + double tmp = *a; + *a = *b; + *b = tmp; +} + void clear_canvas(rgb_t canvas[], rgb_t colour); sdl_state_t init_sdl(void); void free_sdl(sdl_state_t state); void render(sdl_state_t state); void plot_rgb(rgb_t canvas[], uint16_t x, uint16_t y, rgb_t colour); -void draw_line(rgb_t canvas[], rgb_t c, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); +void draw_line(rgb_t canvas[], rgb_t c, vec2_t p0, vec2_t p1); sdl_state_t init_sdl(void) @@ -101,6 +117,19 @@ rgb_to_int(rgb_t c) } /* display the contents of the canvas */ +void +oldrender(sdl_state_t state) +{ + for (size_t y = 0; y < H; y++) { + for (size_t x = 0; x < W; x++) { + rgb_t cur = state.canvas[x + y * W]; + SDL_SetRenderDrawColor(state.renderer, cur.r, cur.g, cur.b, cur.a); + SDL_RenderDrawPoint(state.renderer, x, y); + } + } + SDL_RenderPresent(state.renderer); +} + void render(sdl_state_t state) { @@ -133,8 +162,13 @@ clear_canvas(rgb_t canvas[], rgb_t colour) } void -draw_line(rgb_t canvas[], rgb_t c, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) +draw_line(rgb_t canvas[], rgb_t c, vec2_t p0, vec2_t p1) { + uint16_t x0 = (uint16_t)p0.x, + x1 = (uint16_t)p1.x, + y0 = (uint16_t)p0.y, + y1 = (uint16_t)p1.y; + if (x0 > x1) { swap(x0, x1); swap(y0, y1); @@ -206,9 +240,9 @@ draw_horizontal_line(rgb_t canvas[], rgb_t c, uint16_t x0, uint16_t x1, uint16_t void draw_triangle(rgb_t canvas[], rgb_t c, triangle_t tri) { - draw_line(canvas, c, tri.a.x, tri.a.y, tri.b.x, tri.b.y); - draw_line(canvas, c, tri.b.x, tri.b.y, tri.c.x, tri.c.y); - draw_line(canvas, c, tri.c.x, tri.c.y, tri.a.x, tri.a.y); + draw_line(canvas, c, tri.a, tri.b); + draw_line(canvas, c, tri.b, tri.c); + draw_line(canvas, c, tri.c, tri.a); } void @@ -217,8 +251,8 @@ fill_bottom_flat_triangle(rgb_t canvas[], rgb_t c, triangle_t tri) assert(tri.b.y == tri.c.y); if (tri.b.x > tri.c.x) { - swap(tri.b.y, tri.c.y); - swap(tri.b.x, tri.c.x); + swapd(&tri.b.y, &tri.c.y); + swapd(&tri.b.x, &tri.c.x); } float slope0 = (float)(tri.b.x - tri.a.x) / (float)(tri.b.y - tri.a.y); @@ -240,8 +274,8 @@ fill_top_flat_triangle(rgb_t canvas[], rgb_t c, triangle_t tri) assert(tri.a.y == tri.b.y); if (tri.a.x > tri.b.x) { - swap(tri.a.y, tri.b.y); - swap(tri.a.x, tri.b.x); + swapd(&tri.a.y, &tri.b.y); + swapd(&tri.a.x, &tri.b.x); } float slope0 = (float)(tri.c.x - tri.a.x) / (float)(tri.c.y - tri.a.y); @@ -263,16 +297,16 @@ fill_triangle(rgb_t canvas[], rgb_t c, triangle_t tri) { /* tri.a <= tri.b <= tri.c */ if (tri.b.y < tri.a.y) { - swap(tri.b.y, tri.a.y); - swap(tri.b.x, tri.a.x); + swapd(&tri.b.y, &tri.a.y); + swapd(&tri.b.x, &tri.a.x); } if (tri.c.y < tri.a.y) { - swap(tri.c.y, tri.a.y); - swap(tri.c.x, tri.a.x); + swapd(&tri.c.y, &tri.a.y); + swapd(&tri.c.x, &tri.a.x); } if (tri.c.y < tri.b.y) { - swap(tri.c.y, tri.b.y); - swap(tri.c.x, tri.b.x); + swapd(&tri.c.y, &tri.b.y); + swapd(&tri.c.x, &tri.b.x); } /* simple solutions */ @@ -288,8 +322,8 @@ fill_triangle(rgb_t canvas[], rgb_t c, triangle_t tri) tri.b.y}; if (tri.a.y > tri.b.y) { - swap(tri.a.y, tri.b.y); - swap(tri.a.x, tri.b.x); + swapd(&tri.a.y, &tri.b.y); + swapd(&tri.a.x, &tri.b.x); } fill_bottom_flat_triangle(canvas, c, (triangle_t) { @@ -310,6 +344,13 @@ midpoint(vec2_t a, vec2_t b) }; } +vec2_t +project(cam_t c, vec3_t v) +{ + double r = 200 / (v.z + c.range); + return (vec2_t){W / 2 + r * v.x, H / 2 + r * v.y}; +} + /* saves canvas as a P6 image */ void screenshot(rgb_t canvas[]) @@ -334,24 +375,36 @@ cool_effect(rgb_t canvas[]) { draw_line(canvas, WHITE, - cos(SDL_GetTicks()*0.001) * 300 + W/2, - sin(SDL_GetTicks()*0.001) * 300 + H/2, - W/2, - H/2); + (vec2_t) { + cos(SDL_GetTicks()*0.001) * 300 + W/2, + sin(SDL_GetTicks()*0.001) * 300 + H/2, + }, + (vec2_t) { + W/2, + H/2 + }); draw_line(canvas, WHITE, - cos(SDL_GetTicks()*0.001+1.333*PI) * 300 + W/2, - sin(SDL_GetTicks()*0.001+1.333*PI) * 300 + H/2, - W/2, - H/2); + (vec2_t) { + cos(SDL_GetTicks()*0.001+1.333*PI) * 300 + W/2, + sin(SDL_GetTicks()*0.001+1.333*PI) * 300 + H/2, + }, + (vec2_t) { + W/2, + H/2 + }); draw_line(canvas, WHITE, - cos(SDL_GetTicks()*0.001+0.667*PI) * 300 + W/2, - sin(SDL_GetTicks()*0.001+0.667*PI) * 300 + H/2, - W/2, - H/2); + (vec2_t) { + cos(SDL_GetTicks()*0.001+0.667*PI) * 300 + W/2, + sin(SDL_GetTicks()*0.001+0.667*PI) * 300 + H/2, + }, + (vec2_t) { + W/2, + H/2 + }); /* vec2_t a = {0, 100}, b = {200, 0}, c = {200, 200}; */ @@ -385,34 +438,51 @@ draw_square(rgb_t canvas[], rgb_t col, vec2_t a, vec2_t b, vec2_t c, vec2_t d) draw_triangle(canvas, col, (triangle_t){a, c, d}); } +void +draw_box(rgb_t canvas[], + rgb_t col, + cam_t c, + vec3_t points[8] +) +{ + vec2_t prev = project(c, points[0]); + for (int i = 0; i < 8; i++) { + vec2_t p = project(c, points[i]); + uint16_t x = (uint16_t)p.x; + uint16_t y = (uint16_t)p.y; + + draw_line(canvas, col, p, prev); + + prev = p; + } +} + int main(void) { sdl_state_t state = init_sdl(); + cam_t cam = {180}; SDL_Event event; - vec2_t p = {0,0}; - vec2_t q = {100, 0}; - int selec = 1; for (;;) { - uint32_t buttons; - if (selec) - buttons = SDL_GetMouseState(&p.x, &p.y); - else - buttons = SDL_GetMouseState(&q.x, &q.y); - - if (buttons & SDL_BUTTON(3)) - selec = !selec; - else if (buttons & SDL_BUTTON(1)) + uint32_t buttons = SDL_GetMouseState(NULL, NULL); + if (buttons & SDL_BUTTON(2)) screenshot(state.canvas); clear_canvas(state.canvas, BLACK); - draw_square(state.canvas, - WHITE, - (vec2_t){50, 0}, - q, - p, - (vec2_t){0, 100}); + + vec3_t points[8] = { + (vec3_t){0, 0, 1}, + (vec3_t){100, 0, 1}, + (vec3_t){100, 100, 1}, + (vec3_t){0, 100, 1}, + (vec3_t){0,0,101}, + (vec3_t){100,0,101}, + (vec3_t){100,100,101}, + (vec3_t){0,100,101} + }; + + draw_box(state.canvas, WHITE, cam, points); render(state); if (SDL_PollEvent(&event) && event.type == SDL_QUIT)