Playing with shear, scale, rotation and translation matrices
This commit is contained in:
parent
3e2fbf2c58
commit
a05083061b
223
main.c
Normal file
223
main.c
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
/**
|
||||||
|
* Playing around with matrices while studying
|
||||||
|
* https://github.com/ssloy/tinyrenderer/wiki/Lesson-4:-Perspective-projection
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_events.h>
|
||||||
|
#include <SDL2/SDL_rect.h>
|
||||||
|
#include <SDL2/SDL_render.h>
|
||||||
|
#include <SDL2/SDL_video.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define u64 uint64_t
|
||||||
|
#define f32 float
|
||||||
|
|
||||||
|
#define RADIANS(DEGREES) (DEGREES * M_PI / 180.0f)
|
||||||
|
|
||||||
|
typedef struct vec2u V2u;
|
||||||
|
struct vec2u {
|
||||||
|
u64 x;
|
||||||
|
u64 y;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct vec3f V3f;
|
||||||
|
struct vec3f {
|
||||||
|
union {
|
||||||
|
f32 x;
|
||||||
|
f32 col0;
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
f32 y;
|
||||||
|
f32 col1;
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
f32 z;
|
||||||
|
f32 col2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct mat3x3 Mat3x3;
|
||||||
|
struct mat3x3 {
|
||||||
|
V3f row0;
|
||||||
|
V3f row1;
|
||||||
|
V3f row2;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define vec_add(v1, v2) ((V2u){.x = v1.x + v2.x, .y = v1.y + v2.y})
|
||||||
|
#define vec_sub(v1, v2) ((V2u){.x = v1.x - v2.x, .y = v1.y - v2.y})
|
||||||
|
#define vec_div_num(v, n) ((V2u){.x = v.x / n, .y = v.y / 2})
|
||||||
|
#define mat_mul_vec(mat, vec) \
|
||||||
|
((V3f){.x = mat.row0.col0 * vec.x + mat.row0.col1 * vec.y + \
|
||||||
|
mat.row0.col2 * vec.z, \
|
||||||
|
.y = mat.row1.col0 * vec.x + mat.row1.col1 * vec.y + \
|
||||||
|
mat.row1.col2 * vec.z, \
|
||||||
|
.z = mat.row2.col0 * vec.x + mat.row2.col1 * vec.y + \
|
||||||
|
mat.row2.col2 * vec.z})
|
||||||
|
#define project_v3f(v) ((V2u){.x = (u64)(v.x / v.z), .y = (u64)(v.y / v.z)})
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
#define mat_mul(mat1, mat2) \
|
||||||
|
((Mat3x3){ \
|
||||||
|
.row0 = {.col0 = mat1.row0.col0 * mat2.row0.col0 + mat1.row0.col1 * mat2.row1.col0 + mat1.row0.col2 * mat2.row2.col0, \
|
||||||
|
.col1 = mat1.row0.col0 * mat2.row0.col1 + mat1.row0.col1 * mat2.row1.col1 + mat1.row0.col2 * mat2.row2.col1, \
|
||||||
|
.col2 = mat1.row0.col0 * mat2.row0.col2 + mat1.row0.col1 * mat2.row1.col2 + mat1.row0.col2 * mat2.row2.col2}, \
|
||||||
|
.row1 = {.col0 = mat1.row1.col0 * mat2.row0.col0 + mat1.row1.col1 * mat2.row1.col0 + mat1.row1.col2 * mat2.row2.col0, \
|
||||||
|
.col1 = mat1.row1.col0 * mat2.row0.col1 + mat1.row1.col1 * mat2.row1.col1 + mat1.row1.col2 * mat2.row2.col1, \
|
||||||
|
.col2 = mat1.row1.col0 * mat2.row0.col2 + mat1.row1.col1 * mat2.row1.col2 + mat1.row1.col2 * mat2.row2.col2}, \
|
||||||
|
.row2 = {.col0 = mat1.row2.col0 * mat2.row0.col0 + mat1.row2.col1 * mat2.row1.col0 + mat1.row2.col2 * mat2.row2.col0, \
|
||||||
|
.col1 = mat1.row2.col0 * mat2.row0.col1 + mat1.row2.col1 * mat2.row1.col1 + mat1.row2.col2 * mat2.row2.col1, \
|
||||||
|
.col2 = mat1.row2.col0 * mat2.row0.col2 + mat1.row2.col1 * mat2.row1.col2 + mat1.row2.col2 * mat2.row2.col2}, \
|
||||||
|
})
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
#define MAT3x3(r0c0, r0c1, r0c2, r1c0, r1c1, r1c2, r2c0, r2c1, r2c2) \
|
||||||
|
((Mat3x3){{r0c0, r0c1, r0c2}, {r1c0, r1c1, r1c2}, {r2c0, r2c1, r2c2}})
|
||||||
|
|
||||||
|
void draw_line(SDL_Renderer *renderer, const V2u *start, const V2u *end);
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
SDL_Init(0);
|
||||||
|
SDL_Window *wnd =
|
||||||
|
SDL_CreateWindow("Matrices", SDL_WINDOWPOS_CENTERED,
|
||||||
|
SDL_WINDOWPOS_CENTERED, 1200, 800, SDL_WINDOW_SHOWN);
|
||||||
|
SDL_Renderer *renderer = SDL_CreateRenderer(wnd, -1, 0);
|
||||||
|
|
||||||
|
f32 rotation = 0.0f;
|
||||||
|
f32 radians = RADIANS(rotation);
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
Mat3x3 pos_rot_mat, neg_rot_mat;
|
||||||
|
|
||||||
|
Mat3x3 mat0 = MAT3x3(2.0f, -0.5f, 0.0f,
|
||||||
|
0.0f, 2.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f);
|
||||||
|
Mat3x3 mat1 = MAT3x3( 0.5f, 0.0f, 0.0f,
|
||||||
|
0.25f, 0.5f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f);
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
V3f v0p0 = {400.0f, 150.0f, 1.0f};
|
||||||
|
V3f v0p1 = {800.0f, 150.0f, 1.0f};
|
||||||
|
V3f v0p2 = {400.0f, 400.0f, 1.0f};
|
||||||
|
V3f v0p3 = {800.0f, 400.0f, 1.0f};
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
Mat3x3 mid_mat = MAT3x3(0.5f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.5f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f);
|
||||||
|
Mat3x3 neg_v0p0_xf = MAT3x3(1.0f, 0.0f, -(v0p0.x),
|
||||||
|
0.0f, 1.0f, -(v0p0.y),
|
||||||
|
0.0f, 0.0f, 1.0f);
|
||||||
|
Mat3x3 pos_v0p0_xf = MAT3x3(1.0f, 0.0f, v0p0.x,
|
||||||
|
0.0f, 1.0f, v0p0.y,
|
||||||
|
0.0f, 0.0f, 1.0f);
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
Mat3x3 v0_mid_mat = mat_mul(mat_mul(pos_v0p0_xf, mid_mat), neg_v0p0_xf);
|
||||||
|
V3f v0_mid = mat_mul_vec(v0_mid_mat, v0p3);
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
Mat3x3 neg_v0_mid_xf = MAT3x3(1.0f, 0.0f, -(v0_mid.x),
|
||||||
|
0.0f, 1.0f, -(v0_mid.y),
|
||||||
|
0.0f, 0.0f, 1.0f);
|
||||||
|
Mat3x3 pos_v0_mid_xf = MAT3x3(1.0f, 0.0f, v0_mid.x,
|
||||||
|
0.0f, 1.0f, v0_mid.y,
|
||||||
|
0.0f, 0.0f, 1.0f);
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
Mat3x3 v1_mat;
|
||||||
|
V3f v1p0, v1p1, v1p2, v1p3;
|
||||||
|
|
||||||
|
Mat3x3 v2_mat;
|
||||||
|
V3f v2p0, v2p1, v2p2, v2p3;
|
||||||
|
|
||||||
|
// Projection
|
||||||
|
V2u v0_p0 = project_v3f(v0p0);
|
||||||
|
V2u v0_p1 = project_v3f(v0p1);
|
||||||
|
V2u v0_p2 = project_v3f(v0p2);
|
||||||
|
V2u v0_p3 = project_v3f(v0p3);
|
||||||
|
|
||||||
|
V2u v1_p0, v1_p1, v1_p2, v1_p3;
|
||||||
|
V2u v2_p0, v2_p1, v2_p2, v2_p3;
|
||||||
|
|
||||||
|
SDL_Event event;
|
||||||
|
bool running = true;
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_QUIT:
|
||||||
|
running = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rotation += 0.001f;
|
||||||
|
radians = RADIANS(rotation);
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
pos_rot_mat = MAT3x3( cosf(radians), -sinf(radians), 0.0f,
|
||||||
|
sinf(radians), cosf(radians), 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f);
|
||||||
|
neg_rot_mat = MAT3x3(cosf(-radians), -sinf(-radians), 0.0f,
|
||||||
|
sinf(-radians), cosf(-radians), 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f);
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
v1_mat = mat_mul(mat_mul(pos_v0_mid_xf, mat_mul(pos_rot_mat, mat0)),
|
||||||
|
neg_v0_mid_xf);
|
||||||
|
v1p0 = mat_mul_vec(v1_mat, v0p0);
|
||||||
|
v1p1 = mat_mul_vec(v1_mat, v0p1);
|
||||||
|
v1p2 = mat_mul_vec(v1_mat, v0p2);
|
||||||
|
v1p3 = mat_mul_vec(v1_mat, v0p3);
|
||||||
|
|
||||||
|
v2_mat = mat_mul(mat_mul(pos_v0_mid_xf, mat_mul(neg_rot_mat, mat1)),
|
||||||
|
neg_v0_mid_xf);
|
||||||
|
v2p0 = mat_mul_vec(v2_mat, v0p0);
|
||||||
|
v2p1 = mat_mul_vec(v2_mat, v0p1);
|
||||||
|
v2p2 = mat_mul_vec(v2_mat, v0p2);
|
||||||
|
v2p3 = mat_mul_vec(v2_mat, v0p3);
|
||||||
|
|
||||||
|
v1_p0 = project_v3f(v1p0);
|
||||||
|
v1_p1 = project_v3f(v1p1);
|
||||||
|
v1_p2 = project_v3f(v1p2);
|
||||||
|
v1_p3 = project_v3f(v1p3);
|
||||||
|
|
||||||
|
v2_p0 = project_v3f(v2p0);
|
||||||
|
v2_p1 = project_v3f(v2p1);
|
||||||
|
v2_p2 = project_v3f(v2p2);
|
||||||
|
v2_p3 = project_v3f(v2p3);
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255);
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer, 255, 64, 128, 255);
|
||||||
|
draw_line(renderer, &v0_p0, &v0_p1);
|
||||||
|
draw_line(renderer, &v0_p1, &v0_p3);
|
||||||
|
draw_line(renderer, &v0_p3, &v0_p2);
|
||||||
|
draw_line(renderer, &v0_p2, &v0_p0);
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer, 64, 255, 128, 255);
|
||||||
|
draw_line(renderer, &v1_p0, &v1_p1);
|
||||||
|
draw_line(renderer, &v1_p1, &v1_p3);
|
||||||
|
draw_line(renderer, &v1_p3, &v1_p2);
|
||||||
|
draw_line(renderer, &v1_p2, &v1_p0);
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer, 64, 128, 255, 255);
|
||||||
|
draw_line(renderer, &v2_p0, &v2_p1);
|
||||||
|
draw_line(renderer, &v2_p1, &v2_p3);
|
||||||
|
draw_line(renderer, &v2_p3, &v2_p2);
|
||||||
|
draw_line(renderer, &v2_p2, &v2_p0);
|
||||||
|
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_line(SDL_Renderer *renderer, const V2u *start, const V2u *end) {
|
||||||
|
SDL_RenderDrawLine(renderer, start->x, start->y, end->x, end->y);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user