meshes, rotating box
This commit is contained in:
parent
dee6115dc9
commit
553466ea56
189
main.c
189
main.c
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue