meshes, rotating box

This commit is contained in:
opfez 2021-10-24 11:20:10 +02:00
parent dee6115dc9
commit 553466ea56
1 changed files with 149 additions and 40 deletions

189
main.c
View File

@ -3,6 +3,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <math.h>
#include <SDL2/SDL.h>
@ -40,7 +41,32 @@ typedef struct {
typedef struct {
vec2_t a, b, c;
} triangle_t;
} triangle2_t;
typedef struct {
vec3_t a, b, c;
} triangle3_t;
typedef struct {
uint16_t n;
triangle3_t *tris;
} mesh_t;
mesh_t
new_mesh(uint16_t n, triangle3_t tris[])
{
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];
}
return ret;
}
void free_mesh(mesh_t mesh) { free(mesh.tris); }
#define max(x, y) ((x) > (y) ? (x) : (y))
#define min(x, y) ((x) < (y) ? (x) : (y))
@ -64,6 +90,7 @@ 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, vec2_t p0, vec2_t p1);
vec2_t project(cam_t c, vec3_t v);
sdl_state_t
init_sdl(void)
@ -238,15 +265,15 @@ 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_triangle(rgb_t canvas[], rgb_t col, triangle2_t tri)
{
draw_line(canvas, c, tri.a, tri.b);
draw_line(canvas, c, tri.b, tri.c);
draw_line(canvas, c, tri.c, tri.a);
draw_line(canvas, col, tri.a, tri.b);
draw_line(canvas, col, tri.b, tri.c);
draw_line(canvas, col, tri.c, tri.a);
}
void
fill_bottom_flat_triangle(rgb_t canvas[], rgb_t c, triangle_t tri)
fill_bottom_flat_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri)
{
assert(tri.b.y == tri.c.y);
@ -269,7 +296,7 @@ fill_bottom_flat_triangle(rgb_t canvas[], rgb_t c, triangle_t tri)
}
void
fill_top_flat_triangle(rgb_t canvas[], rgb_t c, triangle_t tri)
fill_top_flat_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri)
{
assert(tri.a.y == tri.b.y);
@ -293,7 +320,7 @@ fill_top_flat_triangle(rgb_t canvas[], rgb_t c, triangle_t tri)
/* http://www.sunshine2k.de/coding/java/TriangleRasterization/TriangleRasterization.html */
void
fill_triangle(rgb_t canvas[], rgb_t c, triangle_t tri)
fill_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri)
{
/* tri.a <= tri.b <= tri.c */
if (tri.b.y < tri.a.y) {
@ -326,10 +353,10 @@ fill_triangle(rgb_t canvas[], rgb_t c, triangle_t tri)
swapd(&tri.a.x, &tri.b.x);
}
fill_bottom_flat_triangle(canvas, c, (triangle_t) {
fill_bottom_flat_triangle(canvas, c, (triangle2_t) {
tri.a, tri.b, trid
});
fill_top_flat_triangle(canvas, c, (triangle_t) {
fill_top_flat_triangle(canvas, c, (triangle2_t) {
tri.b, trid, tri.c
});
}
@ -351,6 +378,16 @@ project(cam_t c, vec3_t v)
return (vec2_t){W / 2 + r * v.x, H / 2 + r * v.y};
}
triangle2_t
project_triangle(cam_t c, triangle3_t tri)
{
return (triangle2_t) {
.a = project(c, tri.a),
.b = project(c, tri.b),
.c = project(c, tri.c),
};
}
/* saves canvas as a P6 image */
void
screenshot(rgb_t canvas[])
@ -421,7 +458,7 @@ cool_effect(rgb_t canvas[])
sin(SDL_GetTicks()*0.001+1.333*PI) * 300 + H/2,
};
for (int i = 0; i < 10; i++) {
fill_triangle(canvas, i % 2 ? BLACK : WHITE, (triangle_t){a, b, c});
fill_triangle(canvas, i % 2 ? BLACK : WHITE, (triangle2_t){a, b, c});
vec2_t tmp_a = midpoint(a, b);
vec2_t tmp_b = midpoint(b, c);
vec2_t tmp_c = midpoint(c, a);
@ -432,32 +469,23 @@ cool_effect(rgb_t canvas[])
}
void
draw_square(rgb_t canvas[], rgb_t col, vec2_t a, vec2_t b, vec2_t c, vec2_t d)
draw_plane(rgb_t canvas[], cam_t c, rgb_t col, mesh_t plane)
{
draw_triangle(canvas, col, (triangle_t){a, b, c});
draw_triangle(canvas, col, (triangle_t){a, c, d});
assert(plane.n == 2);
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[],
rgb_t col,
cam_t c,
vec3_t points[8]
mesh_t box
)
{
vec2_t projected[8];
for (int i = 0; i < 8; i++)
projected[i] = project(c, points[i]);
/* lines along x/y-axes */
for (int i = 0; i < 4; i++) {
draw_line(canvas, col, projected[i], projected[(i+1)]);
draw_line(canvas, col, projected[i+3], projected[(i+4)]);
}
/* lines along z-axis */
for (int i = 0; i < 4; i++) {
draw_line(canvas, col, projected[i], projected[i+4]);
for (int i = 0; i < 12; i++) {
draw_triangle(canvas, col, project_triangle(c, box.tris[i]));
}
}
@ -468,29 +496,110 @@ main(void)
cam_t cam = {180};
SDL_Event event;
triangle3_t tris[12] = {
/* front */
{
{0, 0, 0},
{100, 0, 0},
{100, 100, 0},
},
{
{100, 100, 0},
{0, 100, 0},
{0, 0, 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},
}
};
mesh_t box = new_mesh(12, tris);
uint64_t ticks = 0;
for (;;) {
uint32_t buttons = SDL_GetMouseState(NULL, NULL);
if (buttons & SDL_BUTTON(2))
screenshot(state.canvas);
clear_canvas(state.canvas, BLACK);
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}
};
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);
draw_box(state.canvas, WHITE, cam, points);
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;
}
draw_box(state.canvas, WHITE, cam, box);
render(state);
if (SDL_PollEvent(&event) && event.type == SDL_QUIT)
break;
ticks++;
}
free_sdl(state);