starting 3d

This commit is contained in:
opfez 2021-10-23 10:51:41 +02:00
parent 5d752080f4
commit ea3f43a1f1
1 changed files with 121 additions and 51 deletions

172
main.c
View File

@ -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)