refactor, start work on camera
This commit is contained in:
parent
2b53462b56
commit
b6c3dd298c
6
Makefile
6
Makefile
|
@ -1,5 +1,5 @@
|
|||
CFLAGS = -Wall -Wextra -std=c99 -pedantic -O2
|
||||
CFLAGS = -Wall -Wextra -std=c99 -pedantic -O2 -g
|
||||
LIBS = -lSDL2 -lm
|
||||
|
||||
out: main.c
|
||||
$(CC) $(CFLAGS) $(LIBS) $< -o $@
|
||||
out: main.c types.h
|
||||
$(CC) $(CFLAGS) $(LIBS) main.c -o $@
|
||||
|
|
499
main.c
499
main.c
|
@ -1,3 +1,5 @@
|
|||
#define DEBUG
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -7,67 +9,97 @@
|
|||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
/* cursed struct definitions, thanks bx */
|
||||
#include "types.h"
|
||||
|
||||
#define W 800
|
||||
#define H 600
|
||||
#define PI 3.14159265358979323844
|
||||
|
||||
int wireframe = 0;
|
||||
|
||||
void
|
||||
die(char *msg)
|
||||
{
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
unsigned char r, g, b, a;
|
||||
} rgb_t;
|
||||
const rgb_t WHITE = {255, 255, 255, 255};
|
||||
const rgb_t BLACK = {0, 0, 0, 255};
|
||||
const rgb_t RED = {255, 0, 0, 255};
|
||||
const rgb_t GREEN = {0, 255, 0, 255};
|
||||
const rgb_t BLUE = {0, 0, 255, 255};
|
||||
} rgb;
|
||||
const rgb WHITE = {255, 255, 255, 255};
|
||||
const rgb BLACK = {0, 0, 0, 255};
|
||||
const rgb RED = {255, 0, 0, 255};
|
||||
const rgb GREEN = {0, 255, 0, 255};
|
||||
const rgb BLUE = {0, 0, 255, 255};
|
||||
|
||||
typedef struct {
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Window *window;
|
||||
SDL_Texture *tex;
|
||||
rgb_t *canvas;
|
||||
} sdl_state_t;
|
||||
rgb *canvas;
|
||||
} sdl_state;
|
||||
|
||||
typedef struct {
|
||||
double x, y;
|
||||
} vec2_t;
|
||||
vec2 a, b, c;
|
||||
} triangle2;
|
||||
|
||||
typedef struct {
|
||||
double x, y, z;
|
||||
} vec3_t;
|
||||
|
||||
typedef struct {
|
||||
double range;
|
||||
} cam_t;
|
||||
|
||||
typedef struct {
|
||||
vec2_t a, b, c;
|
||||
} triangle2_t;
|
||||
|
||||
typedef struct {
|
||||
vec3_t a, b, c;
|
||||
} triangle3_t;
|
||||
vec3 a, b, c;
|
||||
} triangle3;
|
||||
|
||||
typedef struct {
|
||||
uint32_t vertex_num;
|
||||
uint32_t tri_num; /* for loops */
|
||||
uint32_t index_num;
|
||||
vec3_t *vertices;
|
||||
vec3 *vertices;
|
||||
uint32_t *indices;
|
||||
} mesh_t;
|
||||
} mesh;
|
||||
|
||||
typedef struct {
|
||||
double nums[3][3];
|
||||
} matrix3x3_t;
|
||||
} matrix3x3;
|
||||
|
||||
mesh_t
|
||||
new_mesh(uint32_t vertex_num, uint32_t tri_num, uint32_t index_num, vec3_t vertices[], uint32_t indices[])
|
||||
vec3
|
||||
vec3_matrix3x3_multiply(vec3 v, matrix3x3 r)
|
||||
{
|
||||
mesh_t ret;
|
||||
return (vec3) {
|
||||
.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])
|
||||
};
|
||||
}
|
||||
|
||||
camera
|
||||
new_camera(double range, vec3 pos, vec3 target, vec3 up)
|
||||
{
|
||||
if (pos.x == target.x &&
|
||||
pos.y == target.y &&
|
||||
pos.z == target.z)
|
||||
die("cannot create camera with same target and position");
|
||||
|
||||
camera ret = {
|
||||
.range = range,
|
||||
.pos = pos,
|
||||
.target = target,
|
||||
.up = up,
|
||||
};
|
||||
ret.dir = vec3_normalize(vec3_sub(pos, target));
|
||||
ret.right = vec3_normalize(vec3_cross(up, ret.dir));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
mesh
|
||||
new_mesh(uint32_t vertex_num, uint32_t tri_num, uint32_t index_num, vec3 vertices[], uint32_t indices[])
|
||||
{
|
||||
mesh ret;
|
||||
|
||||
ret.vertex_num = vertex_num;
|
||||
ret.tri_num = tri_num;
|
||||
ret.index_num = index_num;
|
||||
ret.vertices = malloc(sizeof(vec3_t) * vertex_num);
|
||||
ret.vertices = malloc(sizeof(vec3) * vertex_num);
|
||||
for (uint32_t i = 0; i < vertex_num; i++)
|
||||
ret.vertices[i] = vertices[i];
|
||||
ret.indices = malloc(sizeof(uint32_t) * index_num);
|
||||
|
@ -77,7 +109,7 @@ new_mesh(uint32_t vertex_num, uint32_t tri_num, uint32_t index_num, vec3_t verti
|
|||
return ret;
|
||||
}
|
||||
|
||||
void free_mesh(mesh_t mesh) { free(mesh.vertices); free(mesh.indices); }
|
||||
void free_mesh(mesh mesh) { free(mesh.vertices); free(mesh.indices); }
|
||||
|
||||
#define max(x, y) ((x) > (y) ? (x) : (y))
|
||||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
@ -86,6 +118,7 @@ void free_mesh(mesh_t mesh) { free(mesh.vertices); free(mesh.indices); }
|
|||
(y) ^= (x); \
|
||||
(x) ^= (y); \
|
||||
} while (0)
|
||||
#define clamp(x, min, max) (((x) >= (min)) ? ((x) <= (max)) ? (x) : (max) : (min))
|
||||
|
||||
void
|
||||
swapd(double *a, double *b)
|
||||
|
@ -95,20 +128,20 @@ swapd(double *a, double *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[], 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);
|
||||
void clear_canvas(rgb canvas[], rgb colour);
|
||||
sdl_state init_sdl(void);
|
||||
void free_sdl(sdl_state state);
|
||||
void render(sdl_state state);
|
||||
void plot_rgb(rgb canvas[], int32_t x, int32_t y, rgb colour);
|
||||
void draw_line(rgb canvas[], rgb c, vec2 p0, vec2 p1);
|
||||
vec2 project(camera c, vec3 v);
|
||||
|
||||
sdl_state_t
|
||||
sdl_state
|
||||
init_sdl(void)
|
||||
{
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
sdl_state_t ret;
|
||||
sdl_state ret;
|
||||
|
||||
ret.window = SDL_CreateWindow("Game",
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
|
@ -129,14 +162,14 @@ init_sdl(void)
|
|||
SDL_TEXTUREACCESS_STATIC,
|
||||
W, H);
|
||||
|
||||
ret.canvas = malloc(sizeof(rgb_t) * W * H);
|
||||
clear_canvas(ret.canvas, (rgb_t){0, 0, 0, 255});
|
||||
ret.canvas = malloc(sizeof(rgb) * W * H);
|
||||
clear_canvas(ret.canvas, (rgb){0, 0, 0, 255});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
free_sdl(sdl_state_t state)
|
||||
free_sdl(sdl_state state)
|
||||
{
|
||||
SDL_DestroyRenderer(state.renderer);
|
||||
SDL_DestroyWindow(state.window);
|
||||
|
@ -146,7 +179,7 @@ free_sdl(sdl_state_t state)
|
|||
}
|
||||
|
||||
uint32_t
|
||||
rgb_to_int(rgb_t c)
|
||||
rgb_to_int(rgb c)
|
||||
{
|
||||
return (((uint32_t)c.a << 24)
|
||||
| ((uint32_t)c.r << 16)
|
||||
|
@ -156,20 +189,7 @@ 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)
|
||||
render(sdl_state state)
|
||||
{
|
||||
uint32_t pixels[H*W];
|
||||
for (size_t y = 0; y < H; y++) {
|
||||
|
@ -186,21 +206,21 @@ render(sdl_state_t state)
|
|||
|
||||
|
||||
void
|
||||
plot_rgb(rgb_t canvas[], int32_t x, int32_t y, rgb_t colour)
|
||||
plot_rgb(rgb canvas[], int32_t x, int32_t y, rgb colour)
|
||||
{
|
||||
if (x < W && y < H && x >= 0 && y >= 0)
|
||||
canvas[x + y * W] = colour;
|
||||
}
|
||||
|
||||
void
|
||||
clear_canvas_trailing(rgb_t canvas[], rgb_t colour)
|
||||
clear_canvas_trailing(rgb canvas[], rgb 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)
|
||||
clear_canvas(rgb canvas[], rgb colour)
|
||||
{
|
||||
for (size_t i = 0; i < W * H; i += 2) {
|
||||
canvas[i] = colour;
|
||||
|
@ -209,7 +229,7 @@ clear_canvas(rgb_t canvas[], rgb_t colour)
|
|||
}
|
||||
|
||||
void
|
||||
draw_line(rgb_t canvas[], rgb_t c, vec2_t p0, vec2_t p1)
|
||||
draw_line(rgb canvas[], rgb c, vec2 p0, vec2 p1)
|
||||
{
|
||||
int32_t x0 = (int32_t)p0.x,
|
||||
x1 = (int32_t)p1.x,
|
||||
|
@ -278,17 +298,19 @@ draw_line(rgb_t canvas[], rgb_t c, vec2_t p0, vec2_t p1)
|
|||
}
|
||||
|
||||
void
|
||||
draw_horizontal_line(rgb_t canvas[], rgb_t c, uint32_t x0, uint32_t x1, uint32_t y)
|
||||
draw_horizontal_line(rgb canvas[], rgb c, int32_t x0, int32_t x1, int32_t y)
|
||||
{
|
||||
for (uint32_t x = x0; x <= x1; x++) {
|
||||
size_t index = x + y * W;
|
||||
if (index < H * W)
|
||||
canvas[x + y * W] = c;
|
||||
}
|
||||
if (y < 0) return;
|
||||
if (x0 < 0) x0 = 0;
|
||||
if (x1 >= W) x1 = W - 1;
|
||||
if (y >= H) return;
|
||||
|
||||
for (int32_t x = x0; x <= x1; x++)
|
||||
canvas[x + y * W] = c;
|
||||
}
|
||||
|
||||
void
|
||||
draw_triangle(rgb_t canvas[], rgb_t col, triangle2_t tri)
|
||||
draw_triangle(rgb canvas[], rgb col, triangle2 tri)
|
||||
{
|
||||
draw_line(canvas, col, tri.a, tri.b);
|
||||
draw_line(canvas, col, tri.b, tri.c);
|
||||
|
@ -296,59 +318,118 @@ draw_triangle(rgb_t canvas[], rgb_t col, triangle2_t tri)
|
|||
}
|
||||
|
||||
void
|
||||
fill_bottom_flat_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri)
|
||||
fill_bottom_flat_triangle(rgb canvas[], rgb c, triangle2 tri)
|
||||
{
|
||||
assert(tri.b.y == tri.c.y);
|
||||
|
||||
if (tri.b.x > tri.c.x) {
|
||||
swapd(&tri.b.y, &tri.c.y);
|
||||
if (tri.b.x > tri.c.x)
|
||||
swapd(&tri.b.x, &tri.c.x);
|
||||
}
|
||||
|
||||
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);
|
||||
/* tri.a x
|
||||
* / \
|
||||
* / \
|
||||
* tri.b x_____x tri.c
|
||||
*/
|
||||
|
||||
double x0, x1;
|
||||
x0 = x1 = tri.a.x;
|
||||
int32_t ax = (int32_t)tri.a.x,
|
||||
bx = (int32_t)tri.b.x,
|
||||
cx = (int32_t)tri.c.x,
|
||||
ay = (int32_t)tri.a.y,
|
||||
by = (int32_t)tri.b.y,
|
||||
cy = (int32_t)tri.c.y;
|
||||
|
||||
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;
|
||||
assert(ay <= cy);
|
||||
assert(ay <= by);
|
||||
|
||||
assert(bx <= cx);
|
||||
|
||||
int32_t dx_right = abs(cx - ax);
|
||||
int32_t dy_right = abs(cy - ay);
|
||||
int32_t dx_left = abs(bx - ax);
|
||||
int32_t dy_left = abs(by - ay);
|
||||
|
||||
int32_t eps_r = 0;
|
||||
int32_t eps_l = 0;
|
||||
int32_t xr = ax;
|
||||
int32_t xl = ax;
|
||||
|
||||
int32_t xr_change = ax < cx ? 1 : -1;
|
||||
int32_t xl_change = ax < bx ? 1 : -1;
|
||||
|
||||
for (int32_t y = ay; y < by; y++) {
|
||||
eps_r += dx_right;
|
||||
eps_l += dx_left;
|
||||
while (eps_r > 0) {
|
||||
eps_r -= dy_right;
|
||||
xr += xr_change;
|
||||
}
|
||||
while (eps_l > 0) {
|
||||
eps_l -= dy_left;
|
||||
xl += xl_change;
|
||||
}
|
||||
draw_horizontal_line(canvas, c, xl, xr, y);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fill_top_flat_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri)
|
||||
fill_top_flat_triangle(rgb canvas[], rgb c, triangle2 tri)
|
||||
{
|
||||
assert(tri.a.y == tri.b.y);
|
||||
|
||||
if (tri.a.x > tri.b.x) {
|
||||
swapd(&tri.a.y, &tri.b.y);
|
||||
if (tri.a.x > tri.b.x)
|
||||
swapd(&tri.a.x, &tri.b.x);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
double x0, x1;
|
||||
x0 = x1 = tri.c.x;
|
||||
|
||||
/* note: the predicate here is y > tri.a.y - 1 because using tri.a.y
|
||||
* directly causes small dots on the points of triangles.
|
||||
/* tri.a x_____x tri.b
|
||||
* \ /
|
||||
* \ /
|
||||
* tri.c x
|
||||
*/
|
||||
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;
|
||||
|
||||
int32_t ax = (int32_t)tri.a.x,
|
||||
bx = (int32_t)tri.b.x,
|
||||
cx = (int32_t)tri.c.x,
|
||||
ay = (int32_t)tri.a.y,
|
||||
by = (int32_t)tri.b.y,
|
||||
cy = (int32_t)tri.c.y;
|
||||
|
||||
assert(cy >= ay);
|
||||
assert(cy >= by);
|
||||
|
||||
assert(ax <= bx);
|
||||
|
||||
int32_t dx_right = abs(cx - bx);
|
||||
int32_t dy_right = abs(cy - by);
|
||||
int32_t dx_left = abs(cx - ax);
|
||||
int32_t dy_left = abs(cy - ay);
|
||||
|
||||
int32_t eps_r = 0;
|
||||
int32_t eps_l = 0;
|
||||
int32_t xr = cx;
|
||||
int32_t xl = cx;
|
||||
|
||||
int32_t xr_change = cx < bx ? 1 : -1;
|
||||
int32_t xl_change = cx < ax ? 1 : -1;
|
||||
|
||||
int32_t y;
|
||||
for (y = cy; y > by; y--) {
|
||||
eps_r += dx_right;
|
||||
eps_l += dx_left;
|
||||
while (eps_r > 0) {
|
||||
eps_r -= dy_right;
|
||||
xr += xr_change;
|
||||
}
|
||||
while (eps_l > 0) {
|
||||
eps_l -= dy_left;
|
||||
xl += xl_change;
|
||||
}
|
||||
draw_horizontal_line(canvas, c, xl, xr, y);
|
||||
}
|
||||
|
||||
/* We're missing one line, but setting the loop conditional to be y >= by
|
||||
* messes up the drawing.
|
||||
*/
|
||||
draw_horizontal_line(canvas, c, xl, xr, y);
|
||||
}
|
||||
|
||||
/* http://www.sunshine2k.de/coding/java/TriangleRasterization/TriangleRasterization.html */
|
||||
void
|
||||
fill_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri)
|
||||
fill_triangle(rgb canvas[], rgb c, triangle2 tri)
|
||||
{
|
||||
/* tri.a <= tri.b <= tri.c */
|
||||
if (tri.b.y < tri.a.y) {
|
||||
|
@ -365,14 +446,14 @@ fill_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri)
|
|||
}
|
||||
|
||||
/* simple solutions */
|
||||
if (tri.b.y == tri.c.y) {
|
||||
if ((int32_t)tri.b.y == (int32_t)tri.c.y) {
|
||||
fill_bottom_flat_triangle(canvas, c, tri);
|
||||
}
|
||||
else if (tri.a.y == tri.b.y) {
|
||||
else if ((int32_t)tri.a.y == (int32_t)tri.b.y) {
|
||||
fill_top_flat_triangle(canvas, c, tri);
|
||||
}
|
||||
else {
|
||||
vec2_t trid = {
|
||||
vec2 trid = {
|
||||
(tri.a.x + (tri.b.y - tri.a.y) / (tri.c.y - tri.a.y) * (tri.c.x - tri.a.x)),
|
||||
tri.b.y};
|
||||
|
||||
|
@ -381,35 +462,35 @@ fill_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri)
|
|||
swapd(&tri.a.x, &tri.b.x);
|
||||
}
|
||||
|
||||
fill_bottom_flat_triangle(canvas, c, (triangle2_t) {
|
||||
tri.a, tri.b, trid
|
||||
});
|
||||
fill_top_flat_triangle(canvas, c, (triangle2_t) {
|
||||
fill_top_flat_triangle(canvas, c, (triangle2) {
|
||||
tri.b, trid, tri.c
|
||||
});
|
||||
fill_bottom_flat_triangle(canvas, c, (triangle2) {
|
||||
tri.a, tri.b, trid
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
vec2_t
|
||||
midpoint(vec2_t a, vec2_t b)
|
||||
vec2
|
||||
midpoint(vec2 a, vec2 b)
|
||||
{
|
||||
return (vec2_t) {
|
||||
return (vec2) {
|
||||
(a.x + b.x) / 2,
|
||||
(a.y + b.y) / 2
|
||||
};
|
||||
}
|
||||
|
||||
vec2_t
|
||||
project(cam_t c, vec3_t v)
|
||||
vec2
|
||||
project(camera c, vec3 v)
|
||||
{
|
||||
double r = 200 / (v.z + c.range);
|
||||
return (vec2_t){W / 2 + r * v.x, H / 2 + r * v.y};
|
||||
return (vec2){W / 2 + r * v.x, H / 2 + r * v.y};
|
||||
}
|
||||
|
||||
triangle2_t
|
||||
project_triangle(cam_t c, triangle3_t tri)
|
||||
triangle2
|
||||
project_triangle(camera c, triangle3 tri)
|
||||
{
|
||||
return (triangle2_t) {
|
||||
return (triangle2) {
|
||||
.a = project(c, tri.a),
|
||||
.b = project(c, tri.b),
|
||||
.c = project(c, tri.c),
|
||||
|
@ -418,7 +499,7 @@ project_triangle(cam_t c, triangle3_t tri)
|
|||
|
||||
/* saves canvas as a P6 image */
|
||||
void
|
||||
screenshot(rgb_t canvas[])
|
||||
screenshot(rgb canvas[])
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
char output[64];
|
||||
|
@ -427,7 +508,7 @@ screenshot(rgb_t canvas[])
|
|||
fprintf(out, "P6\n%d %d\n255\n", W, H);
|
||||
for (int y = 0; y < H; y++) {
|
||||
for (int x = 0; x < W; x++) {
|
||||
rgb_t cur = canvas[x + y * W];
|
||||
rgb cur = canvas[x + y * W];
|
||||
fprintf(out, "%c%c%c", cur.r, cur.g, cur.b);
|
||||
}
|
||||
}
|
||||
|
@ -436,107 +517,30 @@ screenshot(rgb_t canvas[])
|
|||
}
|
||||
|
||||
void
|
||||
cool_effect(rgb_t canvas[])
|
||||
{
|
||||
draw_line(canvas,
|
||||
WHITE,
|
||||
(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,
|
||||
(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,
|
||||
(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}; */
|
||||
vec2_t a = {
|
||||
cos(SDL_GetTicks()*0.001) * 300 + W/2,
|
||||
sin(SDL_GetTicks()*0.001) * 300 + H/2
|
||||
};
|
||||
vec2_t b = {
|
||||
cos(SDL_GetTicks()*0.001+0.667*PI) * 300 + W/2,
|
||||
sin(SDL_GetTicks()*0.001+0.667*PI) * 300 + H/2
|
||||
};
|
||||
vec2_t c = {
|
||||
cos(SDL_GetTicks()*0.001+1.333*PI) * 300 + W/2,
|
||||
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, (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);
|
||||
a = tmp_a;
|
||||
b = tmp_b;
|
||||
c = tmp_c;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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])); */
|
||||
/* } */
|
||||
|
||||
void
|
||||
draw_mesh(rgb_t canvas[],
|
||||
rgb_t col,
|
||||
cam_t c,
|
||||
mesh_t mesh
|
||||
)
|
||||
draw_mesh(rgb canvas[], rgb col, camera c, mesh mesh)
|
||||
{
|
||||
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]],
|
||||
}));
|
||||
if (wireframe)
|
||||
draw_triangle(canvas, col, project_triangle(c, (triangle3) {
|
||||
mesh.vertices[mesh.indices[3*i ]],
|
||||
mesh.vertices[mesh.indices[3*i+1]],
|
||||
mesh.vertices[mesh.indices[3*i+2]],
|
||||
}));
|
||||
else
|
||||
fill_triangle(canvas, col, project_triangle(c, (triangle3) {
|
||||
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)
|
||||
matrix3x3
|
||||
matrix3x3_multiply(matrix3x3 r, matrix3x3 s)
|
||||
{
|
||||
#define a r.nums
|
||||
#define b s.nums
|
||||
return (matrix3x3_t) {
|
||||
return (matrix3x3) {
|
||||
.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],
|
||||
|
@ -552,49 +556,57 @@ matrix3x3_multiply(matrix3x3_t r, matrix3x3_t s)
|
|||
#undef b
|
||||
}
|
||||
|
||||
matrix3x3_t
|
||||
double
|
||||
to_deg(double deg)
|
||||
{
|
||||
return deg * 2 * PI / 360.0;
|
||||
}
|
||||
|
||||
matrix3x3
|
||||
x_rotation(double deg)
|
||||
{
|
||||
return (matrix3x3_t) {
|
||||
return (matrix3x3) {
|
||||
.nums =
|
||||
{{1, 0, 0},
|
||||
{0, cos(deg/360.0), -sin(deg/360.0)},
|
||||
{0, sin(deg/360.0), cos(deg/360.0)}}
|
||||
{{1, 0, 0},
|
||||
{0, cos(to_deg(deg)), -sin(to_deg(deg))},
|
||||
{0, sin(to_deg(deg)), cos(to_deg(deg))}}
|
||||
};
|
||||
}
|
||||
|
||||
matrix3x3_t
|
||||
matrix3x3
|
||||
y_rotation(double deg)
|
||||
{
|
||||
return (matrix3x3_t) {
|
||||
return (matrix3x3) {
|
||||
.nums =
|
||||
{{ cos(deg/360.0), 0, sin(deg/360.0)},
|
||||
{ 0, 1, 0},
|
||||
{-sin(deg/360.0), 0, cos(deg/360.0)}}
|
||||
{{ cos(to_deg(deg)), 0, sin(to_deg(deg))},
|
||||
{ 0, 1, 0},
|
||||
{-sin(to_deg(deg)), 0, cos(to_deg(deg))}}
|
||||
};
|
||||
}
|
||||
|
||||
matrix3x3_t
|
||||
matrix3x3
|
||||
z_rotation(double deg)
|
||||
{
|
||||
return (matrix3x3_t) {
|
||||
return (matrix3x3) {
|
||||
.nums =
|
||||
{{cos(deg/360.0), -sin(deg/360.0), 0},
|
||||
{sin(deg/360.0), cos(deg/360.0), 0},
|
||||
{0, 0, 1}}
|
||||
{{cos(to_deg(deg)), -sin(to_deg(deg)), 0},
|
||||
{sin(to_deg(deg)), cos(to_deg(deg)), 0},
|
||||
{0, 0, 1}}
|
||||
};
|
||||
}
|
||||
|
||||
#include "other.h"
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
sdl_state_t state = init_sdl();
|
||||
cam_t cam = {180};
|
||||
sdl_state state = init_sdl();
|
||||
camera cam = new_camera(180, (vec3){0, 0, 3}, (vec3){0, 0, 0}, UP);
|
||||
print_camera(&cam);
|
||||
|
||||
SDL_Event event;
|
||||
|
||||
vec3_t vertices[8] = {
|
||||
vec3 vertices[8] = {
|
||||
/* front */
|
||||
{0, 0, 0},
|
||||
{100, 0, 0},
|
||||
|
@ -626,23 +638,27 @@ main(void)
|
|||
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);
|
||||
const mesh box = new_mesh(8, 12, 3 * 12, vertices, indices);
|
||||
mesh box_copy = new_mesh(8, 12, 3 * 12, vertices, indices);
|
||||
|
||||
uint64_t t = 0;
|
||||
|
||||
for (;;) {
|
||||
matrix3x3_t m = matrix3x3_multiply(
|
||||
double elapsed, start = SDL_GetPerformanceCounter();
|
||||
|
||||
matrix3x3 m = matrix3x3_multiply(
|
||||
matrix3x3_multiply(
|
||||
z_rotation(0.7 * t),
|
||||
y_rotation(0.8 * t)),
|
||||
x_rotation(0.9 * t));
|
||||
z_rotation(1.2 * t),
|
||||
y_rotation(1.1 * t)),
|
||||
x_rotation(1.0 * t));
|
||||
|
||||
int x, y;
|
||||
uint32_t buttons = SDL_GetMouseState(&x, &y);
|
||||
|
||||
if (buttons & SDL_BUTTON(2))
|
||||
screenshot(state.canvas);
|
||||
else if (buttons & (SDL_BUTTON(1)))
|
||||
wireframe = !wireframe;
|
||||
|
||||
clear_canvas(state.canvas, BLACK);
|
||||
|
||||
|
@ -656,6 +672,9 @@ main(void)
|
|||
if (SDL_PollEvent(&event) && event.type == SDL_QUIT)
|
||||
break;
|
||||
|
||||
elapsed = (SDL_GetPerformanceCounter() - start) / (double)SDL_GetPerformanceFrequency() * 1000.0;
|
||||
SDL_Delay(clamp(16.666f - elapsed, 0, 1000));
|
||||
|
||||
t++;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
void
|
||||
cool_effect(rgb canvas[])
|
||||
{
|
||||
draw_line(canvas,
|
||||
WHITE,
|
||||
(vec2) {
|
||||
cos(SDL_GetTicks()*0.001) * 300 + W/2,
|
||||
sin(SDL_GetTicks()*0.001) * 300 + H/2,
|
||||
},
|
||||
(vec2) {
|
||||
W/2,
|
||||
H/2
|
||||
});
|
||||
|
||||
draw_line(canvas,
|
||||
WHITE,
|
||||
(vec2) {
|
||||
cos(SDL_GetTicks()*0.001+1.333*PI) * 300 + W/2,
|
||||
sin(SDL_GetTicks()*0.001+1.333*PI) * 300 + H/2,
|
||||
},
|
||||
(vec2) {
|
||||
W/2,
|
||||
H/2
|
||||
});
|
||||
|
||||
draw_line(canvas,
|
||||
WHITE,
|
||||
(vec2) {
|
||||
cos(SDL_GetTicks()*0.001+0.667*PI) * 300 + W/2,
|
||||
sin(SDL_GetTicks()*0.001+0.667*PI) * 300 + H/2,
|
||||
},
|
||||
(vec2) {
|
||||
W/2,
|
||||
H/2
|
||||
});
|
||||
|
||||
|
||||
/* vec2 a = {0, 100}, b = {200, 0}, c = {200, 200}; */
|
||||
vec2 a = {
|
||||
cos(SDL_GetTicks()*0.001) * 300 + W/2,
|
||||
sin(SDL_GetTicks()*0.001) * 300 + H/2
|
||||
};
|
||||
vec2 b = {
|
||||
cos(SDL_GetTicks()*0.001+0.667*PI) * 300 + W/2,
|
||||
sin(SDL_GetTicks()*0.001+0.667*PI) * 300 + H/2
|
||||
};
|
||||
vec2 c = {
|
||||
cos(SDL_GetTicks()*0.001+1.333*PI) * 300 + W/2,
|
||||
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, (triangle2){a, b, c});
|
||||
vec2 tmp_a = midpoint(a, b);
|
||||
vec2 tmp_b = midpoint(b, c);
|
||||
vec2 tmp_c = midpoint(c, a);
|
||||
a = tmp_a;
|
||||
b = tmp_b;
|
||||
c = tmp_c;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
#ifdef SUB_INCLUDE_TYPES
|
||||
#undef SUB_INCLUDE_TYPES
|
||||
|
||||
STRUCT(vec2)
|
||||
FIELD(x, double)
|
||||
FIELD(y, double)
|
||||
END_STRUCT
|
||||
|
||||
STRUCT(vec3)
|
||||
FIELD(x, double)
|
||||
FIELD(y, double)
|
||||
FIELD(z, double)
|
||||
END_STRUCT
|
||||
|
||||
STRUCT(vec4)
|
||||
FIELD(x, double)
|
||||
FIELD(y, double)
|
||||
FIELD(z, double)
|
||||
FIELD(w, double)
|
||||
END_STRUCT
|
||||
|
||||
STRUCT(camera)
|
||||
FIELD(range, double)
|
||||
FIELD(pos, vec3)
|
||||
FIELD(target, vec3)
|
||||
FIELD(up, vec3)
|
||||
FIELD(dir, vec3)
|
||||
FIELD(right, vec3)
|
||||
END_STRUCT
|
||||
|
||||
#else // sub include guard
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define STRUCT(N) typedef struct N N; struct N {
|
||||
#define END_STRUCT };
|
||||
#define FIELD(N, T) T N;
|
||||
#define SUB_INCLUDE_TYPES
|
||||
#include __FILE__
|
||||
// undefs to get rid of redef warnings
|
||||
#undef STRUCT
|
||||
#undef FIELD
|
||||
#undef END_STRUCT
|
||||
|
||||
void print_double(double *d) {
|
||||
printf(" %f ", *d);
|
||||
}
|
||||
|
||||
#define STRUCT(N) \
|
||||
void print_##N (N *s) { \
|
||||
printf("(" #N ") {");
|
||||
#define FIELD(N, T) \
|
||||
print_##T(&s -> N);
|
||||
#define END_STRUCT \
|
||||
printf("}\n"); \
|
||||
}
|
||||
#define SUB_INCLUDE_TYPES
|
||||
#include __FILE__
|
||||
// undefs to get rid of redef warnings
|
||||
#undef STRUCT
|
||||
#undef FIELD
|
||||
#undef END_STRUCT
|
||||
|
||||
const vec3 UP = {0, 1, 0};
|
||||
|
||||
vec3
|
||||
vec3_add(vec3 u, vec3 v)
|
||||
{
|
||||
return (vec3) {
|
||||
.x = u.x + v.x,
|
||||
.y = u.y + v.y,
|
||||
.z = u.z + v.z,
|
||||
};
|
||||
}
|
||||
|
||||
vec3
|
||||
vec3_sub(vec3 u, vec3 v)
|
||||
{
|
||||
return (vec3) {
|
||||
.x = u.x - v.x,
|
||||
.y = u.y - v.y,
|
||||
.z = u.z - v.z,
|
||||
};
|
||||
}
|
||||
|
||||
vec3
|
||||
vec3_cross(vec3 u, vec3 v)
|
||||
{
|
||||
return (vec3) {
|
||||
.x = u.y * v.z - u.z * v.y,
|
||||
.y = u.z * v.x - u.x * v.z,
|
||||
.z = u.x * v.y - u.y * v.x,
|
||||
};
|
||||
}
|
||||
|
||||
vec3
|
||||
vec3_normalize(vec3 u)
|
||||
{
|
||||
double len = sqrt(u.x*u.x + u.y*u.y + u.z*u.z);
|
||||
return (vec3) {
|
||||
.x = u.x / len,
|
||||
.y = u.y / len,
|
||||
.z = u.z / len,
|
||||
};
|
||||
}
|
||||
|
||||
vec4
|
||||
vec4_add(vec4 u, vec4 v)
|
||||
{
|
||||
return (vec4) {
|
||||
.x = u.x + v.x,
|
||||
.y = u.y + v.y,
|
||||
.z = u.z + v.z,
|
||||
};
|
||||
}
|
||||
|
||||
vec4
|
||||
vec4_sub(vec4 u, vec4 v)
|
||||
{
|
||||
return (vec4) {
|
||||
.x = u.x - v.x,
|
||||
.y = u.y - v.y,
|
||||
.z = u.z - v.z,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif /* SUB_INCLUDE_TYPES */
|
Loading…
Reference in New Issue