From 2b53462b56f8915c86bccb16b2231958a04abc48 Mon Sep 17 00:00:00 2001 From: opfez Date: Wed, 27 Oct 2021 21:51:30 +0200 Subject: [PATCH] mesh overhaul, rotation, matrices --- main.c | 311 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 185 insertions(+), 126 deletions(-) diff --git a/main.c b/main.c index 42b02f5..fef2f21 100644 --- a/main.c +++ b/main.c @@ -48,25 +48,36 @@ typedef struct { } triangle3_t; typedef struct { - uint16_t n; - triangle3_t *tris; + uint32_t vertex_num; + uint32_t tri_num; /* for loops */ + uint32_t index_num; + vec3_t *vertices; + uint32_t *indices; } mesh_t; +typedef struct { + double nums[3][3]; +} matrix3x3_t; + mesh_t -new_mesh(uint16_t n, triangle3_t tris[]) +new_mesh(uint32_t vertex_num, uint32_t tri_num, uint32_t index_num, vec3_t vertices[], uint32_t indices[]) { mesh_t ret; - ret.n = n; - ret.tris = malloc(sizeof(triangle3_t) * ret.n); - for (uint16_t i = 0; i < n; i++) { - ret.tris[i] = tris[i]; - } + ret.vertex_num = vertex_num; + ret.tri_num = tri_num; + ret.index_num = index_num; + ret.vertices = malloc(sizeof(vec3_t) * vertex_num); + for (uint32_t i = 0; i < vertex_num; i++) + ret.vertices[i] = vertices[i]; + ret.indices = malloc(sizeof(uint32_t) * index_num); + for (uint32_t i = 0; i < index_num; i++) + ret.indices[i] = indices[i]; return ret; } -void free_mesh(mesh_t mesh) { free(mesh.tris); } +void free_mesh(mesh_t mesh) { free(mesh.vertices); free(mesh.indices); } #define max(x, y) ((x) > (y) ? (x) : (y)) #define min(x, y) ((x) < (y) ? (x) : (y)) @@ -88,7 +99,7 @@ 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 plot_rgb(rgb_t canvas[], int32_t x, int32_t y, rgb_t colour); void draw_line(rgb_t canvas[], rgb_t c, vec2_t p0, vec2_t p1); vec2_t project(cam_t c, vec3_t v); @@ -175,26 +186,35 @@ render(sdl_state_t state) void -plot_rgb(rgb_t canvas[], uint16_t x, uint16_t y, rgb_t colour) +plot_rgb(rgb_t canvas[], int32_t x, int32_t y, rgb_t colour) { - if (x < W && y < H) + if (x < W && y < H && x >= 0 && y >= 0) canvas[x + y * W] = colour; } +void +clear_canvas_trailing(rgb_t canvas[], rgb_t colour) +{ + for (size_t i = 0; i < W * H; i++) + if ((rand()&31)==0) canvas[i] = colour; +} + void clear_canvas(rgb_t canvas[], rgb_t colour) { - for (size_t i = 0; i < W * H; i++) + for (size_t i = 0; i < W * H; i += 2) { canvas[i] = colour; + canvas[i+1] = colour; + } } void 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; + int32_t x0 = (int32_t)p0.x, + x1 = (int32_t)p1.x, + y0 = (int32_t)p0.y, + y1 = (int32_t)p1.y; if (x0 > x1) { swap(x0, x1); @@ -258,10 +278,13 @@ draw_line(rgb_t canvas[], rgb_t c, vec2_t p0, vec2_t p1) } void -draw_horizontal_line(rgb_t canvas[], rgb_t c, uint16_t x0, uint16_t x1, uint16_t y) +draw_horizontal_line(rgb_t canvas[], rgb_t c, uint32_t x0, uint32_t x1, uint32_t y) { - for (uint16_t x = x0; x < x1; x++) - canvas[x + y * W] = c; + for (uint32_t x = x0; x <= x1; x++) { + size_t index = x + y * W; + if (index < H * W) + canvas[x + y * W] = c; + } } void @@ -282,13 +305,14 @@ fill_bottom_flat_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri) swapd(&tri.b.x, &tri.c.x); } - float slope0 = (float)(tri.b.x - tri.a.x) / (float)(tri.b.y - tri.a.y); - float slope1 = (float)(tri.c.x - tri.a.x) / (float)(tri.c.y - tri.a.y); + double slope0 = (tri.b.x - tri.a.x) / (tri.b.y - tri.a.y); + double slope1 = (tri.c.x - tri.a.x) / (tri.c.y - tri.a.y); - float x0, x1; + double x0, x1; x0 = x1 = tri.a.x; for (int y = tri.a.y; y <= tri.b.y; y++) { + /* draw_line(canvas, c, (vec2_t){x0, y}, (vec2_t){x1, y}); */ draw_horizontal_line(canvas, c, x0, x1, y); x0 += slope0; x1 += slope1; @@ -305,14 +329,18 @@ fill_top_flat_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri) swapd(&tri.a.x, &tri.b.x); } - float slope0 = (float)(tri.c.x - tri.a.x) / (float)(tri.c.y - tri.a.y); - float slope1 = (float)(tri.c.x - tri.b.x) / (float)(tri.c.y - tri.b.y); + double slope0 = (tri.c.x - tri.a.x) / (tri.c.y - tri.a.y); + double slope1 = (tri.c.x - tri.b.x) / (tri.c.y - tri.b.y); - float x0, x1; + double x0, x1; x0 = x1 = tri.c.x; - for (int y = tri.c.y; y > tri.a.y; y--) { + /* note: the predicate here is y > tri.a.y - 1 because using tri.a.y + * directly causes small dots on the points of triangles. + */ + for (int y = tri.c.y; y > tri.a.y - 1; y--) { draw_horizontal_line(canvas, c, x0, x1, y); + /* draw_line(canvas, c, (vec2_t){x0, y}, (vec2_t){x1, y}); */ x0 -= slope0; x1 -= slope1; } @@ -330,7 +358,7 @@ fill_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri) if (tri.c.y < tri.a.y) { swapd(&tri.c.y, &tri.a.y); swapd(&tri.c.x, &tri.a.x); - } + } if (tri.c.y < tri.b.y) { swapd(&tri.c.y, &tri.b.y); swapd(&tri.c.x, &tri.b.x); @@ -345,7 +373,7 @@ fill_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri) } else { vec2_t trid = { - (tri.a.x + ((float)(tri.b.y - tri.a.y) / (float)(tri.c.y - tri.a.y)) * (tri.c.x - tri.a.x)), + (tri.a.x + (tri.b.y - tri.a.y) / (tri.c.y - tri.a.y) * (tri.c.x - tri.a.x)), tri.b.y}; if (tri.a.y > tri.b.y) { @@ -468,27 +496,96 @@ cool_effect(rgb_t canvas[]) } } -void -draw_plane(rgb_t canvas[], cam_t c, rgb_t col, mesh_t plane) -{ - assert(plane.n == 2); +/* void */ +/* draw_plane(rgb_t canvas[], cam_t c, rgb_t col, mesh_t plane) */ +/* { */ +/* assert(plane.n == 2); */ - draw_triangle(canvas, col, project_triangle(c, plane.tris[0])); - draw_triangle(canvas, col, project_triangle(c, plane.tris[1])); -} +/* draw_triangle(canvas, col, project_triangle(c, plane.tris[0])); */ +/* draw_triangle(canvas, col, project_triangle(c, plane.tris[1])); */ +/* } */ void -draw_box(rgb_t canvas[], +draw_mesh(rgb_t canvas[], rgb_t col, cam_t c, - mesh_t box + mesh_t mesh ) { - for (int i = 0; i < 12; i++) { - draw_triangle(canvas, col, project_triangle(c, box.tris[i])); + for (uint32_t i = 0; i < mesh.tri_num; i++) { + draw_triangle(canvas, col, project_triangle(c, (triangle3_t) { + mesh.vertices[mesh.indices[3*i ]], + mesh.vertices[mesh.indices[3*i+1]], + mesh.vertices[mesh.indices[3*i+2]], + })); } } +vec3_t +vec3_matrix3x3_multiply(vec3_t v, matrix3x3_t r) +{ + return (vec3_t) { + .x = (v.x * r.nums[0][0]) + (v.y * r.nums[0][1]) + (v.z * r.nums[0][2]), + .y = (v.x * r.nums[1][0]) + (v.y * r.nums[1][1]) + (v.z * r.nums[1][2]), + .z = (v.x * r.nums[2][0]) + (v.y * r.nums[2][1]) + (v.z * r.nums[2][2]) + }; +} + +matrix3x3_t +matrix3x3_multiply(matrix3x3_t r, matrix3x3_t s) +{ + #define a r.nums + #define b s.nums + return (matrix3x3_t) { + .nums = + {{a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0], + a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1], + a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2]}, + {a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0], + a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1], + a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2]}, + {a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0], + a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1], + a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2]}} + }; + #undef a + #undef b +} + +matrix3x3_t +x_rotation(double deg) +{ + return (matrix3x3_t) { + .nums = + {{1, 0, 0}, + {0, cos(deg/360.0), -sin(deg/360.0)}, + {0, sin(deg/360.0), cos(deg/360.0)}} + }; +} + +matrix3x3_t +y_rotation(double deg) +{ + return (matrix3x3_t) { + .nums = + {{ cos(deg/360.0), 0, sin(deg/360.0)}, + { 0, 1, 0}, + {-sin(deg/360.0), 0, cos(deg/360.0)}} + }; +} + +matrix3x3_t +z_rotation(double deg) +{ + return (matrix3x3_t) { + .nums = + {{cos(deg/360.0), -sin(deg/360.0), 0}, + {sin(deg/360.0), cos(deg/360.0), 0}, + {0, 0, 1}} + }; +} + + int main(void) { @@ -497,110 +594,72 @@ main(void) SDL_Event event; - triangle3_t tris[12] = { + vec3_t vertices[8] = { /* front */ - { - {0, 0, 0}, - {100, 0, 0}, - {100, 100, 0}, - }, - { - {100, 100, 0}, - {0, 100, 0}, - {0, 0, 0}, - }, + {0, 0, 0}, + {100, 0, 0}, + {100, 100, 0}, + {0, 100, 0}, /* back */ - { - {0, 0, 100}, - {100, 0, 100}, - {100, 100, 100}, - }, - { - {100, 100, 100}, - {0, 100, 100}, - {0, 0, 100}, - }, - /* left */ - { - {0, 0, 0}, - {0, 0, 100}, - {0, 100, 100} - }, - { - {0, 100, 100}, - {0, 100, 0}, - {0, 0, 0}, - }, - /* right */ - { - {100, 0, 0}, - {100, 0, 100}, - {100, 100, 100} - }, - { - {100, 100, 100}, - {100, 100, 0}, - {100, 0, 0}, - }, - /* top */ - { - {0, 0, 0}, - {0, 0, 100}, - {100, 0, 100}, - }, - { - {100, 0, 100}, - {100, 0, 0}, - {0, 0, 0}, - }, - /* bottom */ - { - {0, 100, 0}, - {0, 100, 100}, - {100, 100, 100}, - }, - { - {100, 100, 100}, - {100, 100, 0}, - {0, 100, 0}, - } + {0, 0, 100}, + {100, 0, 100}, + {100, 100, 100}, + {0, 100, 100}, }; - mesh_t box = new_mesh(12, tris); + uint32_t indices[3 * 12] = { + /* front */ + 0, 1, 2, + 2, 3, 0, + /* back */ + 4, 5, 6, + 6, 7, 4, + /* left */ + 0, 4, 7, + 7, 3, 0, + /* right */ + 1, 5, 6, + 6, 2, 1, + /* top */ + 0, 1, 5, + 5, 4, 0, + /* bottom */ + 3, 2, 6, + 6, 7, 3, + }; + const mesh_t box = new_mesh(8, 12, 3 * 12, vertices, indices); + mesh_t box_copy = new_mesh(8, 12, 3 * 12, vertices, indices); - uint64_t ticks = 0; + uint64_t t = 0; for (;;) { - uint32_t buttons = SDL_GetMouseState(NULL, NULL); + matrix3x3_t m = matrix3x3_multiply( + matrix3x3_multiply( + z_rotation(0.7 * t), + y_rotation(0.8 * t)), + x_rotation(0.9 * t)); + + int x, y; + uint32_t buttons = SDL_GetMouseState(&x, &y); + if (buttons & SDL_BUTTON(2)) screenshot(state.canvas); + clear_canvas(state.canvas, BLACK); - for (int i = 0; i < 12; i++) { - double a_x = box.tris[i].a.x * cos(1.0/360.0) - box.tris[i].a.z * sin(1.0/360.0); - double a_z = box.tris[i].a.x * sin(1.0/360.0) + box.tris[i].a.z * cos(1.0/360.0); - - double b_x = box.tris[i].b.x * cos(1.0/360.0) - box.tris[i].b.z * sin(1.0/360.0); - double b_z = box.tris[i].b.x * sin(1.0/360.0) + box.tris[i].b.z * cos(1.0/360.0); - - double c_x = box.tris[i].c.x * cos(1.0/360.0) - box.tris[i].c.z * sin(1.0/360.0); - double c_z = box.tris[i].c.x * sin(1.0/360.0) + box.tris[i].c.z * cos(1.0/360.0); - - box.tris[i].a.x = a_x; - box.tris[i].a.z = a_z; - box.tris[i].b.x = b_x; - box.tris[i].b.z = b_z; - box.tris[i].c.x = c_x; - box.tris[i].c.z = c_z; + for (size_t i = 0; i < box.vertex_num; i++) { + box_copy.vertices[i] = vec3_matrix3x3_multiply(box.vertices[i], m); } - draw_box(state.canvas, WHITE, cam, box); + draw_mesh(state.canvas, WHITE, cam, box_copy); render(state); if (SDL_PollEvent(&event) && event.type == SDL_QUIT) break; - ticks++; + t++; } + free_mesh(box); + free_mesh(box_copy); free_sdl(state); }