mesh overhaul, rotation, matrices
This commit is contained in:
parent
553466ea56
commit
2b53462b56
311
main.c
311
main.c
|
@ -48,25 +48,36 @@ typedef struct {
|
|||
} triangle3_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t n;
|
||||
triangle3_t *tris;
|
||||
uint32_t vertex_num;
|
||||
uint32_t tri_num; /* for loops */
|
||||
uint32_t index_num;
|
||||
vec3_t *vertices;
|
||||
uint32_t *indices;
|
||||
} mesh_t;
|
||||
|
||||
typedef struct {
|
||||
double nums[3][3];
|
||||
} matrix3x3_t;
|
||||
|
||||
mesh_t
|
||||
new_mesh(uint16_t n, triangle3_t tris[])
|
||||
new_mesh(uint32_t vertex_num, uint32_t tri_num, uint32_t index_num, vec3_t vertices[], uint32_t indices[])
|
||||
{
|
||||
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];
|
||||
}
|
||||
ret.vertex_num = vertex_num;
|
||||
ret.tri_num = tri_num;
|
||||
ret.index_num = index_num;
|
||||
ret.vertices = malloc(sizeof(vec3_t) * vertex_num);
|
||||
for (uint32_t i = 0; i < vertex_num; i++)
|
||||
ret.vertices[i] = vertices[i];
|
||||
ret.indices = malloc(sizeof(uint32_t) * index_num);
|
||||
for (uint32_t i = 0; i < index_num; i++)
|
||||
ret.indices[i] = indices[i];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void free_mesh(mesh_t mesh) { free(mesh.tris); }
|
||||
void free_mesh(mesh_t mesh) { free(mesh.vertices); free(mesh.indices); }
|
||||
|
||||
#define max(x, y) ((x) > (y) ? (x) : (y))
|
||||
#define min(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
@ -88,7 +99,7 @@ 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 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);
|
||||
|
||||
|
@ -175,26 +186,35 @@ render(sdl_state_t state)
|
|||
|
||||
|
||||
void
|
||||
plot_rgb(rgb_t canvas[], uint16_t x, uint16_t y, rgb_t colour)
|
||||
plot_rgb(rgb_t canvas[], int32_t x, int32_t y, rgb_t colour)
|
||||
{
|
||||
if (x < W && y < H)
|
||||
if (x < W && y < H && x >= 0 && y >= 0)
|
||||
canvas[x + y * W] = colour;
|
||||
}
|
||||
|
||||
void
|
||||
clear_canvas_trailing(rgb_t canvas[], rgb_t 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)
|
||||
{
|
||||
for (size_t i = 0; i < W * H; i++)
|
||||
for (size_t i = 0; i < W * H; i += 2) {
|
||||
canvas[i] = colour;
|
||||
canvas[i+1] = colour;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
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;
|
||||
int32_t x0 = (int32_t)p0.x,
|
||||
x1 = (int32_t)p1.x,
|
||||
y0 = (int32_t)p0.y,
|
||||
y1 = (int32_t)p1.y;
|
||||
|
||||
if (x0 > x1) {
|
||||
swap(x0, x1);
|
||||
|
@ -258,10 +278,13 @@ draw_line(rgb_t canvas[], rgb_t c, vec2_t p0, vec2_t p1)
|
|||
}
|
||||
|
||||
void
|
||||
draw_horizontal_line(rgb_t canvas[], rgb_t c, uint16_t x0, uint16_t x1, uint16_t y)
|
||||
draw_horizontal_line(rgb_t canvas[], rgb_t c, uint32_t x0, uint32_t x1, uint32_t y)
|
||||
{
|
||||
for (uint16_t x = x0; x < x1; x++)
|
||||
canvas[x + y * W] = c;
|
||||
for (uint32_t x = x0; x <= x1; x++) {
|
||||
size_t index = x + y * W;
|
||||
if (index < H * W)
|
||||
canvas[x + y * W] = c;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -282,13 +305,14 @@ fill_bottom_flat_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri)
|
|||
swapd(&tri.b.x, &tri.c.x);
|
||||
}
|
||||
|
||||
float slope0 = (float)(tri.b.x - tri.a.x) / (float)(tri.b.y - tri.a.y);
|
||||
float slope1 = (float)(tri.c.x - tri.a.x) / (float)(tri.c.y - tri.a.y);
|
||||
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);
|
||||
|
||||
float x0, x1;
|
||||
double x0, x1;
|
||||
x0 = x1 = tri.a.x;
|
||||
|
||||
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;
|
||||
|
@ -305,14 +329,18 @@ fill_top_flat_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri)
|
|||
swapd(&tri.a.x, &tri.b.x);
|
||||
}
|
||||
|
||||
float slope0 = (float)(tri.c.x - tri.a.x) / (float)(tri.c.y - tri.a.y);
|
||||
float slope1 = (float)(tri.c.x - tri.b.x) / (float)(tri.c.y - tri.b.y);
|
||||
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);
|
||||
|
||||
float x0, x1;
|
||||
double x0, x1;
|
||||
x0 = x1 = tri.c.x;
|
||||
|
||||
for (int y = tri.c.y; y > tri.a.y; y--) {
|
||||
/* note: the predicate here is y > tri.a.y - 1 because using tri.a.y
|
||||
* directly causes small dots on the points of triangles.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
@ -330,7 +358,7 @@ fill_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri)
|
|||
if (tri.c.y < tri.a.y) {
|
||||
swapd(&tri.c.y, &tri.a.y);
|
||||
swapd(&tri.c.x, &tri.a.x);
|
||||
}
|
||||
}
|
||||
if (tri.c.y < tri.b.y) {
|
||||
swapd(&tri.c.y, &tri.b.y);
|
||||
swapd(&tri.c.x, &tri.b.x);
|
||||
|
@ -345,7 +373,7 @@ fill_triangle(rgb_t canvas[], rgb_t c, triangle2_t tri)
|
|||
}
|
||||
else {
|
||||
vec2_t trid = {
|
||||
(tri.a.x + ((float)(tri.b.y - tri.a.y) / (float)(tri.c.y - tri.a.y)) * (tri.c.x - tri.a.x)),
|
||||
(tri.a.x + (tri.b.y - tri.a.y) / (tri.c.y - tri.a.y) * (tri.c.x - tri.a.x)),
|
||||
tri.b.y};
|
||||
|
||||
if (tri.a.y > tri.b.y) {
|
||||
|
@ -468,27 +496,96 @@ cool_effect(rgb_t canvas[])
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
draw_plane(rgb_t canvas[], cam_t c, rgb_t col, mesh_t plane)
|
||||
{
|
||||
assert(plane.n == 2);
|
||||
/* 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]));
|
||||
}
|
||||
/* 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[],
|
||||
draw_mesh(rgb_t canvas[],
|
||||
rgb_t col,
|
||||
cam_t c,
|
||||
mesh_t box
|
||||
mesh_t mesh
|
||||
)
|
||||
{
|
||||
for (int i = 0; i < 12; i++) {
|
||||
draw_triangle(canvas, col, project_triangle(c, box.tris[i]));
|
||||
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]],
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
#define a r.nums
|
||||
#define b s.nums
|
||||
return (matrix3x3_t) {
|
||||
.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],
|
||||
a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2]},
|
||||
{a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0],
|
||||
a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1],
|
||||
a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2]},
|
||||
{a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0],
|
||||
a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1],
|
||||
a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2]}}
|
||||
};
|
||||
#undef a
|
||||
#undef b
|
||||
}
|
||||
|
||||
matrix3x3_t
|
||||
x_rotation(double deg)
|
||||
{
|
||||
return (matrix3x3_t) {
|
||||
.nums =
|
||||
{{1, 0, 0},
|
||||
{0, cos(deg/360.0), -sin(deg/360.0)},
|
||||
{0, sin(deg/360.0), cos(deg/360.0)}}
|
||||
};
|
||||
}
|
||||
|
||||
matrix3x3_t
|
||||
y_rotation(double deg)
|
||||
{
|
||||
return (matrix3x3_t) {
|
||||
.nums =
|
||||
{{ cos(deg/360.0), 0, sin(deg/360.0)},
|
||||
{ 0, 1, 0},
|
||||
{-sin(deg/360.0), 0, cos(deg/360.0)}}
|
||||
};
|
||||
}
|
||||
|
||||
matrix3x3_t
|
||||
z_rotation(double deg)
|
||||
{
|
||||
return (matrix3x3_t) {
|
||||
.nums =
|
||||
{{cos(deg/360.0), -sin(deg/360.0), 0},
|
||||
{sin(deg/360.0), cos(deg/360.0), 0},
|
||||
{0, 0, 1}}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
|
@ -497,110 +594,72 @@ main(void)
|
|||
|
||||
SDL_Event event;
|
||||
|
||||
triangle3_t tris[12] = {
|
||||
vec3_t vertices[8] = {
|
||||
/* front */
|
||||
{
|
||||
{0, 0, 0},
|
||||
{100, 0, 0},
|
||||
{100, 100, 0},
|
||||
},
|
||||
{
|
||||
{100, 100, 0},
|
||||
{0, 100, 0},
|
||||
{0, 0, 0},
|
||||
},
|
||||
{0, 0, 0},
|
||||
{100, 0, 0},
|
||||
{100, 100, 0},
|
||||
{0, 100, 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},
|
||||
}
|
||||
{0, 0, 100},
|
||||
{100, 0, 100},
|
||||
{100, 100, 100},
|
||||
{0, 100, 100},
|
||||
};
|
||||
mesh_t box = new_mesh(12, tris);
|
||||
uint32_t indices[3 * 12] = {
|
||||
/* front */
|
||||
0, 1, 2,
|
||||
2, 3, 0,
|
||||
/* back */
|
||||
4, 5, 6,
|
||||
6, 7, 4,
|
||||
/* left */
|
||||
0, 4, 7,
|
||||
7, 3, 0,
|
||||
/* right */
|
||||
1, 5, 6,
|
||||
6, 2, 1,
|
||||
/* top */
|
||||
0, 1, 5,
|
||||
5, 4, 0,
|
||||
/* bottom */
|
||||
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);
|
||||
|
||||
uint64_t ticks = 0;
|
||||
uint64_t t = 0;
|
||||
|
||||
for (;;) {
|
||||
uint32_t buttons = SDL_GetMouseState(NULL, NULL);
|
||||
matrix3x3_t m = matrix3x3_multiply(
|
||||
matrix3x3_multiply(
|
||||
z_rotation(0.7 * t),
|
||||
y_rotation(0.8 * t)),
|
||||
x_rotation(0.9 * t));
|
||||
|
||||
int x, y;
|
||||
uint32_t buttons = SDL_GetMouseState(&x, &y);
|
||||
|
||||
if (buttons & SDL_BUTTON(2))
|
||||
screenshot(state.canvas);
|
||||
|
||||
clear_canvas(state.canvas, BLACK);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
for (size_t i = 0; i < box.vertex_num; i++) {
|
||||
box_copy.vertices[i] = vec3_matrix3x3_multiply(box.vertices[i], m);
|
||||
}
|
||||
|
||||
draw_box(state.canvas, WHITE, cam, box);
|
||||
draw_mesh(state.canvas, WHITE, cam, box_copy);
|
||||
|
||||
render(state);
|
||||
if (SDL_PollEvent(&event) && event.type == SDL_QUIT)
|
||||
break;
|
||||
|
||||
ticks++;
|
||||
t++;
|
||||
}
|
||||
|
||||
free_mesh(box);
|
||||
free_mesh(box_copy);
|
||||
free_sdl(state);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue