From 6703e40ac8b1a80fd3c0bc6c914f4193be0a39dc Mon Sep 17 00:00:00 2001 From: hypercube Date: Fri, 3 Apr 2026 10:21:04 +0000 Subject: [PATCH] Upload files to "/" --- main.c | 343 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 main.c diff --git a/main.c b/main.c new file mode 100644 index 0000000..d4abe15 --- /dev/null +++ b/main.c @@ -0,0 +1,343 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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; +}