starting 3d
This commit is contained in:
parent
5d752080f4
commit
ea3f43a1f1
172
main.c
172
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)
|
||||
|
|
Loading…
Reference in New Issue