mesh overhaul, rotation, matrices

This commit is contained in:
opfez 2021-10-27 21:51:30 +02:00
parent 553466ea56
commit 2b53462b56
1 changed files with 185 additions and 126 deletions

311
main.c
View File

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