Upload files to "/"
This commit is contained in:
343
main.c
Normal file
343
main.c
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
#include <SDL3/SDL_events.h>
|
||||||
|
#include <SDL3/SDL_init.h>
|
||||||
|
#include <SDL3/SDL_oldnames.h>
|
||||||
|
#include <SDL3/SDL_rect.h>
|
||||||
|
#include <SDL3/SDL_render.h>
|
||||||
|
#include <SDL3/SDL_timer.h>
|
||||||
|
#include <SDL3/SDL_video.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
typedef float Vec3[3];
|
||||||
|
typedef float Mat3x3[3*3];
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float v[4];
|
||||||
|
} Vec4;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float m[4*4];
|
||||||
|
} Mat4;
|
||||||
|
|
||||||
|
static inline Vec4 Vec4_make(float x, float y, float z, float w) {
|
||||||
|
Vec4 r = { .v = {x,y,z,w} };
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Mat4 Mat4_make(float a00,float a01,float a02,float a03,
|
||||||
|
float a10,float a11,float a12,float a13,
|
||||||
|
float a20,float a21,float a22,float a23,
|
||||||
|
float a30,float a31,float a32,float a33) {
|
||||||
|
Mat4 m = {
|
||||||
|
.m = {
|
||||||
|
a00,a01,a02,a03,
|
||||||
|
a10,a11,a12,a13,
|
||||||
|
a20,a21,a22,a23,
|
||||||
|
a30,a31,a32,a33
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print a Vec4 in the form [x y z w] */
|
||||||
|
static inline void Vec4_print(const Vec4 *v, FILE *out) {
|
||||||
|
if (!out) out = stdout;
|
||||||
|
fprintf(out, "[%g %g %g %g]\n", v->v[0], v->v[1], v->v[2], v->v[3]);
|
||||||
|
}
|
||||||
|
/* Print a Mat4 in 4 rows */
|
||||||
|
static inline void Mat4_print(const Mat4 *m, FILE *out) {
|
||||||
|
if (!out) out = stdout;
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
fprintf(out, "[%g %g %g %g]\n",
|
||||||
|
m->m[i*4 + 0], m->m[i*4 + 1],
|
||||||
|
m->m[i*4 + 2], m->m[i*4 + 3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static inline Vec4 Mat4_mulVec4(const Mat4 m, const Vec4 v) {
|
||||||
|
Vec4 r;
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
r.v[i] = m.m[i*4 + 0]*v.v[0]
|
||||||
|
+ m.m[i*4 + 1]*v.v[1]
|
||||||
|
+ m.m[i*4 + 2]*v.v[2]
|
||||||
|
+ m.m[i*4 + 3]*v.v[3];
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* helpers */
|
||||||
|
static inline Mat4 Mat4_identity(void) {
|
||||||
|
Mat4 r = { .m = {
|
||||||
|
1,0,0,0,
|
||||||
|
0,1,0,0,
|
||||||
|
0,0,1,0,
|
||||||
|
0,0,0,1
|
||||||
|
} };
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Mat4 Mat4_mul(const Mat4 a, const Mat4 b) {
|
||||||
|
Mat4 c;
|
||||||
|
for (int i = 0; i < 4; ++i){
|
||||||
|
for (int j = 0; j < 4; ++j) {
|
||||||
|
float s = 0.0f;
|
||||||
|
for (int k = 0; k < 4; ++k)
|
||||||
|
s += a.m[i*4 + k] * b.m[k*4 + j];
|
||||||
|
c.m[i*4 + j] = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Mat4 Mat4_mul_n(size_t n, const Mat4 *mats) {
|
||||||
|
Mat4 result = Mat4_identity();
|
||||||
|
/* multiply right-to-left so the last matrix is applied first:
|
||||||
|
result = mats[n-1] * mats[n-2] * ... * mats[0] */
|
||||||
|
for (size_t i = n; i-- > 0; ) {
|
||||||
|
result = Mat4_mul(mats[i], result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAT4_MUL_VAR(...) Mat4_mul_n((sizeof((Mat4[]){__VA_ARGS__})/sizeof(Mat4)), (Mat4[]){__VA_ARGS__})
|
||||||
|
|
||||||
|
/* Translate by (tx,ty,tz) */
|
||||||
|
static inline Mat4 Mat4_translate(float tx, float ty, float tz) {
|
||||||
|
Mat4 r = Mat4_identity();
|
||||||
|
r.m[0*4 + 3] = tx;
|
||||||
|
r.m[1*4 + 3] = ty;
|
||||||
|
r.m[2*4 + 3] = tz;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scale by (sx,sy,sz) */
|
||||||
|
static inline Mat4 Mat4_scale(float sx, float sy, float sz) {
|
||||||
|
Mat4 r = Mat4_identity();
|
||||||
|
r.m[0*4 + 0] = sx;
|
||||||
|
r.m[1*4 + 1] = sy;
|
||||||
|
r.m[2*4 + 2] = sz;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shear: specify XY, XZ, YX, YZ, ZX, ZY components (shear of axis_row by axis_col)
|
||||||
|
Example: shear_xy is X += shear_xy * Y */
|
||||||
|
static inline Mat4 Mat4_shear(float shear_xy, float shear_xz,
|
||||||
|
float shear_yx, float shear_yz,
|
||||||
|
float shear_zx, float shear_zy) {
|
||||||
|
Mat4 r = Mat4_identity();
|
||||||
|
r.m[0*4 + 1] = shear_xy;
|
||||||
|
r.m[0*4 + 2] = shear_xz;
|
||||||
|
r.m[1*4 + 0] = shear_yx;
|
||||||
|
r.m[1*4 + 2] = shear_yz;
|
||||||
|
r.m[2*4 + 0] = shear_zx;
|
||||||
|
r.m[2*4 + 1] = shear_zy;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rotation around X, Y, Z (angles in radians) */
|
||||||
|
static inline Mat4 Mat4_rotate_x(float a) {
|
||||||
|
float c = cosf(a), s = sinf(a);
|
||||||
|
Mat4 r = Mat4_identity();
|
||||||
|
r.m[1*4 + 1] = c; r.m[1*4 + 2] = -s;
|
||||||
|
r.m[2*4 + 1] = s; r.m[2*4 + 2] = c;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
static inline Mat4 Mat4_rotate_y(float a) {
|
||||||
|
float c = cosf(a), s = sinf(a);
|
||||||
|
Mat4 r = Mat4_identity();
|
||||||
|
r.m[0*4 + 0] = c; r.m[0*4 + 2] = s;
|
||||||
|
r.m[2*4 + 0] = -s; r.m[2*4 + 2] = c;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
static inline Mat4 Mat4_rotate_z(float a) {
|
||||||
|
float c = cosf(a), s = sinf(a);
|
||||||
|
Mat4 r = Mat4_identity();
|
||||||
|
r.m[0*4 + 0] = c; r.m[0*4 + 1] = -s;
|
||||||
|
r.m[1*4 + 0] = s; r.m[1*4 + 1] = c;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perspective projection
|
||||||
|
fovy: vertical field of view in radians
|
||||||
|
aspect: width/height
|
||||||
|
znear, zfar: positive distances
|
||||||
|
Produces standard right-handed projection mapping view-space z to [-1,1] (OpenGL style).
|
||||||
|
*/
|
||||||
|
static inline Mat4 Mat4_perspective(float fovy, float aspect, float znear, float zfar) {
|
||||||
|
float f = 1.0f / tanf(fovy * 0.5f);
|
||||||
|
Mat4 p = { .m = {0} };
|
||||||
|
p.m[0*4 + 0] = f / aspect;
|
||||||
|
p.m[1*4 + 1] = f;
|
||||||
|
p.m[2*4 + 2] = (zfar + znear) / (znear - zfar);
|
||||||
|
p.m[2*4 + 3] = (2.0f * zfar * znear) / (znear - zfar);
|
||||||
|
p.m[3*4 + 2] = -1.0f;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build full transform: scale -> rotateZ -> rotateY -> rotateX -> shear -> translate -> perspective
|
||||||
|
(Order is applied right-to-left when multiplying: final = P * T * Shear * R_x * R_y * R_z * S)
|
||||||
|
*/
|
||||||
|
static inline Mat4 Mat4_full_transform(float sx, float sy, float sz,
|
||||||
|
float rot_x, float rot_y, float rot_z,
|
||||||
|
float shear_xy, float shear_xz,
|
||||||
|
float shear_yx, float shear_yz,
|
||||||
|
float shear_zx, float shear_zy,
|
||||||
|
float tx, float ty, float tz,
|
||||||
|
float fovy, float aspect, float znear, float zfar) {
|
||||||
|
Mat4 S = Mat4_scale(sx, sy, sz);
|
||||||
|
Mat4 R = Mat4_mul(Mat4_rotate_x(rot_x),
|
||||||
|
Mat4_mul(Mat4_rotate_y(rot_y), Mat4_rotate_z(rot_z)));
|
||||||
|
Mat4 Sh = Mat4_shear(shear_xy, shear_xz, shear_yx, shear_yz, shear_zx, shear_zy);
|
||||||
|
Mat4 T = Mat4_translate(tx, ty, tz);
|
||||||
|
Mat4 M = Mat4_mul(T, Mat4_mul(Sh, Mat4_mul(R, S))); /* M = T * Shear * R * S */
|
||||||
|
Mat4 P = Mat4_perspective(fovy, aspect, znear, zfar);
|
||||||
|
Mat4 final = Mat4_mul(P, M); /* final = P * M */
|
||||||
|
return final;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
float sx = 1.5f, sy = 1.5f, sz = 1.5f;
|
||||||
|
float rx = 0.0f, ry = (float)M_PI / 4.0f, rz = 0.0f;
|
||||||
|
float shear_xy = 0.2f, shear_xz = 0.0f, shear_yx = 0.0f, shear_yz = 0.0f, shear_zx = 0.0f, shear_zy = 0.0f;
|
||||||
|
float tx = 2.0f, ty = 3.0f, tz = 4.0f;
|
||||||
|
float fovy = 60.0f * ((float)M_PI / 180.0f);
|
||||||
|
float aspect = 16.0f / 9.0f;
|
||||||
|
float znear = 0.1f, zfar = 100.0f;
|
||||||
|
|
||||||
|
Mat4 M = Mat4_full_transform(
|
||||||
|
1, 1, 1,
|
||||||
|
0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0,
|
||||||
|
fovy, aspect, znear, zfar
|
||||||
|
);
|
||||||
|
|
||||||
|
/* example point in object space (x,y,z,1) */
|
||||||
|
Vec4 points[8] = {
|
||||||
|
Vec4_make(1, 1, 1, 1),
|
||||||
|
Vec4_make(1, 1, -1, 1),
|
||||||
|
Vec4_make(1, -1, 1, 1),
|
||||||
|
Vec4_make(1, -1, -1, 1),
|
||||||
|
Vec4_make(-1, 1, 1, 1),
|
||||||
|
Vec4_make(-1, 1, -1, 1),
|
||||||
|
Vec4_make(-1, -1, 1, 1),
|
||||||
|
Vec4_make(-1, -1, -1, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int e[2];
|
||||||
|
} Edge;
|
||||||
|
|
||||||
|
Edge edges[] = {
|
||||||
|
(Edge){.e = {0, 1}},
|
||||||
|
(Edge){.e = {1, 3}},
|
||||||
|
(Edge){.e = {3, 2}},
|
||||||
|
(Edge){.e = {0, 2}},
|
||||||
|
|
||||||
|
(Edge){.e = {4, 5}},
|
||||||
|
(Edge){.e = {5, 7}},
|
||||||
|
(Edge){.e = {7, 6}},
|
||||||
|
(Edge){.e = {4, 6}},
|
||||||
|
|
||||||
|
(Edge){.e = {0, 4}},
|
||||||
|
(Edge){.e = {1, 5}},
|
||||||
|
(Edge){.e = {2, 6}},
|
||||||
|
(Edge){.e = {3, 7}},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SDL_Init(SDL_INIT_VIDEO);
|
||||||
|
|
||||||
|
SDL_Renderer *renderer;
|
||||||
|
SDL_Window *window;
|
||||||
|
SDL_CreateWindowAndRenderer("name", 512, 512, SDL_WINDOW_TRANSPARENT, &window, &renderer);
|
||||||
|
|
||||||
|
float roty = 0;
|
||||||
|
|
||||||
|
bool running = true;
|
||||||
|
while(running){
|
||||||
|
SDL_Event e;
|
||||||
|
while(SDL_PollEvent(&e)){
|
||||||
|
switch(e.type){
|
||||||
|
case SDL_EVENT_QUIT: {
|
||||||
|
running = false;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer, 0x11, 0x11, 0x11, 0xFF);
|
||||||
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
|
Vec4 projected[8] = {0};
|
||||||
|
|
||||||
|
for(int i = 0; i < sizeof(points) / sizeof(*points); i++){
|
||||||
|
Mat4 rx = Mat4_rotate_x(0.3);
|
||||||
|
Mat4 ry = Mat4_rotate_y(roty);
|
||||||
|
Mat4 campos = Mat4_translate(0, 0, 10);
|
||||||
|
|
||||||
|
Mat4 translate1 = Mat4_translate(0, 0, -1);
|
||||||
|
Mat4 rz = Mat4_rotate_x(roty);
|
||||||
|
Mat4 translate2 = Mat4_translate(0, 0, 1);
|
||||||
|
|
||||||
|
|
||||||
|
Mat4 pers = Mat4_make(
|
||||||
|
1,0,0,0,
|
||||||
|
0,1,0,0,
|
||||||
|
0,0,1,0,
|
||||||
|
0,0,0.2,0
|
||||||
|
);
|
||||||
|
|
||||||
|
// Mat4 transform = Mat4_mul(ry, rx);
|
||||||
|
Mat4 transform = MAT4_MUL_VAR(pers, campos, translate2, rz, translate1, rx, ry);
|
||||||
|
projected[i] = Mat4_mulVec4(transform, points[i]);
|
||||||
|
projected[i].v[0] /= projected[i].v[3];
|
||||||
|
projected[i].v[1] /= projected[i].v[3];
|
||||||
|
projected[i].v[2] /= projected[i].v[3];
|
||||||
|
projected[i].v[3] = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer, 0x0, 0xFF, 0x0, 0xFF);
|
||||||
|
for(int i = 0; i < sizeof(edges) / sizeof(*edges); i++){
|
||||||
|
float x1 = projected[edges[i].e[0]].v[0] * 128 + 256;
|
||||||
|
float y1 = projected[edges[i].e[0]].v[1] * 128 + 256;
|
||||||
|
float x2 = projected[edges[i].e[1]].v[0] * 128 + 256;
|
||||||
|
float y2 = projected[edges[i].e[1]].v[1] * 128 + 256;
|
||||||
|
SDL_RenderLine(renderer, x1, y1, x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float size = 20;
|
||||||
|
SDL_SetRenderDrawColor(renderer, 0xFF, 0x0, 0x0, 0xFF);
|
||||||
|
for(int i = 0; i < sizeof(points) / sizeof(*points); i++){
|
||||||
|
SDL_FRect rect = {
|
||||||
|
.x = projected[i].v[0] * 128 + 256 - size/2,
|
||||||
|
.y = projected[i].v[1] * 128 + 256 - size/2,
|
||||||
|
.w = size,
|
||||||
|
.h = size,
|
||||||
|
};
|
||||||
|
SDL_RenderFillRect(renderer, &rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
roty += 0.01;
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
SDL_Delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user