strichmaennchen git · main
git clone https://git.christianimmanuel.de/games/strichmaennchen.gitwget https://git.christianimmanuel.de/games/strichmaennchen/archive/strichmaennchen.tar.gzlinalg.c raw
#include "linalg.h"
#include <math.h>
#include <stdio.h>
float cosf(float x);
float tanf(float x);
float sinf(float x);
float sqrtf(float x);
Vec4 vec4(float x, float y, float z, float w) {
Vec4 v = {x, y, z, w};
return v;
}
Vec4 vec4_sub(Vec4 a, Vec4 b) {
Vec4 r = {a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w};
return r;
}
Vec4 mat4_mul_vec4(Mat4 m, Vec4 v) {
Vec4 r;
r.x = m.m[0]*v.x + m.m[1]*v.y + m.m[2]*v.z + m.m[3]*v.w;
r.y = m.m[4]*v.x + m.m[5]*v.y + m.m[6]*v.z + m.m[7]*v.w;
r.z = m.m[8]*v.x + m.m[9]*v.y + m.m[10]*v.z + m.m[11]*v.w;
r.w = m.m[12]*v.x + m.m[13]*v.y + m.m[14]*v.z + m.m[15]*v.w;
return r;
}
Vec3 vec3(float x, float y, float z) {
Vec3 v = {x, y, z};
return v;
}
Vec3 vec3_negate(Vec3 v) {
return (Vec3){ -v.x, -v.y, -v.z };
}
float vec3_dot(Vec3 a, Vec3 b) {
return a.x*b.x + a.y*b.y + a.z*b.z;
}
Mat4 mat4_identity() {
Mat4 m = {{0}};
m.m[0]=1; m.m[5]=1; m.m[10]=1; m.m[15]=1;
return m;
}
Mat4 mat4_translate(Vec3 v) {
Mat4 m = mat4_identity();
m.m[12] = v.x;
m.m[13] = v.y;
m.m[14] = v.z;
return m;
}
float vec3_length(Vec3 v) {
return sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
}
Vec3 vec3_normalize(Vec3 v) {
float len = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
return (Vec3){ v.x/len, v.y/len, v.z/len };
}
Vec3 vec3_scale(Vec3 v, float s) {
return (Vec3){v.x * s, v.y * s, v.z * s};
}
Vec3 vec3_div_scalar(Vec4 v) {
float inv_w = 1.0f / v.w;
Vec3 r = { v.x * inv_w, v.y * inv_w, v.z * inv_w };
return r;
}
Vec3 vec3_div_scalar_f(Vec3 v, float s) {
return (Vec3){v.x / s, v.y / s, v.z / s};
}
Vec3 vec3_cross(Vec3 a, Vec3 b) {
return (Vec3){
a.y*b.z - a.z*b.y,
a.z*b.x - a.x*b.z,
a.x*b.y - a.y*b.x
};
}
Vec3 vec3_rotate(Vec3 v, Vec3 rot) {
// Apply ZYX rotation (roll, pitch, yaw)
float cx = cosf(rot.x), sx = sinf(rot.x);
float cy = cosf(rot.y), sy = sinf(rot.y);
float cz = cosf(rot.z), sz = sinf(rot.z);
// Rotation around X
Vec3 rx = {v.x, v.y*cx - v.z*sx, v.y*sx + v.z*cx};
// Rotation around Y
Vec3 ry = {rx.x*cy + rx.z*sy, rx.y, -rx.x*sy + rx.z*cy};
// Rotation around Z
Vec3 rz = {ry.x*cz - ry.y*sz, ry.x*sz + ry.y*cz, ry.z};
return rz;
}
Vec3 vec3_add(Vec3 a, Vec3 b) {
return (Vec3){ a.x + b.x, a.y + b.y, a.z + b.z };
}
Vec3 vec3_sub(Vec3 a, Vec3 b) {
return (Vec3){a.x - b.x, a.y - b.y, a.z - b.z};
}
Vec3 mat4_mul_vec3_dir(Mat4 m, Vec3 v) {
Vec3 r;
r.x = m.m[0] * v.x + m.m[4] * v.y + m.m[8] * v.z;
r.y = m.m[1] * v.x + m.m[5] * v.y + m.m[9] * v.z;
r.z = m.m[2] * v.x + m.m[6] * v.y + m.m[10] * v.z;
return r;
}
// Placeholder for future perspective/lookAt
Mat4 mat4_perspective(float fov_deg, float aspect, float near, float far) {
float f = 1.0f / tanf(fov_deg * 0.5f * (3.14159265f / 180.0f));
Mat4 m = {{0}};
m.m[0] = f / aspect; // scale X by aspect
m.m[5] = f; // scale Y
m.m[10] = -(far + near) / (far - near);
m.m[11] = -1.0f;
m.m[14] = -(2.0f * far * near) / (far - near);
m.m[15] = 0.0f;
return m;
}
Mat4 mat4_inverse(Mat4 m) {
Mat4 inv;
float *a = m.m, *o = inv.m;
o[0] = a[5]*a[10]*a[15] - a[5]*a[11]*a[14] - a[9]*a[6]*a[15]
+ a[9]*a[7]*a[14] + a[13]*a[6]*a[11] - a[13]*a[7]*a[10];
o[4] = -a[4]*a[10]*a[15] + a[4]*a[11]*a[14] + a[8]*a[6]*a[15]
- a[8]*a[7]*a[14] - a[12]*a[6]*a[11] + a[12]*a[7]*a[10];
o[8] = a[4]*a[9]*a[15] - a[4]*a[11]*a[13] - a[8]*a[5]*a[15]
+ a[8]*a[7]*a[13] + a[12]*a[5]*a[11] - a[12]*a[7]*a[9];
o[12] = -a[4]*a[9]*a[14] + a[4]*a[10]*a[13] + a[8]*a[5]*a[14]
- a[8]*a[6]*a[13] - a[12]*a[5]*a[10] + a[12]*a[6]*a[9];
o[1] = -a[1]*a[10]*a[15] + a[1]*a[11]*a[14] + a[9]*a[2]*a[15]
- a[9]*a[3]*a[14] - a[13]*a[2]*a[11] + a[13]*a[3]*a[10];
o[5] = a[0]*a[10]*a[15] - a[0]*a[11]*a[14] - a[8]*a[2]*a[15]
+ a[8]*a[3]*a[14] + a[12]*a[2]*a[11] - a[12]*a[3]*a[10];
o[9] = -a[0]*a[9]*a[15] + a[0]*a[11]*a[13] + a[8]*a[1]*a[15]
- a[8]*a[3]*a[13] - a[12]*a[1]*a[11] + a[12]*a[3]*a[9];
o[13] = a[0]*a[9]*a[14] - a[0]*a[10]*a[13] - a[8]*a[1]*a[14]
+ a[8]*a[2]*a[13] + a[12]*a[1]*a[10] - a[12]*a[2]*a[9];
o[2] = a[1]*a[6]*a[15] - a[1]*a[7]*a[14] - a[5]*a[2]*a[15]
+ a[5]*a[3]*a[14] + a[13]*a[2]*a[7] - a[13]*a[3]*a[6];
o[6] = -a[0]*a[6]*a[15] + a[0]*a[7]*a[14] + a[4]*a[2]*a[15]
- a[4]*a[3]*a[14] - a[12]*a[2]*a[7] + a[12]*a[3]*a[6];
o[10] = a[0]*a[5]*a[15] - a[0]*a[7]*a[13] - a[4]*a[1]*a[15]
+ a[4]*a[3]*a[13] + a[12]*a[1]*a[7] - a[12]*a[3]*a[5];
o[14] = -a[0]*a[5]*a[14] + a[0]*a[6]*a[13] + a[4]*a[1]*a[14]
- a[4]*a[2]*a[13] - a[12]*a[1]*a[6] + a[12]*a[2]*a[5];
o[3] = -a[1]*a[6]*a[11] + a[1]*a[7]*a[10] + a[5]*a[2]*a[11]
- a[5]*a[3]*a[10] - a[9]*a[2]*a[7] + a[9]*a[3]*a[6];
o[7] = a[0]*a[6]*a[11] - a[0]*a[7]*a[10] - a[4]*a[2]*a[11]
+ a[4]*a[3]*a[10] + a[8]*a[2]*a[7] - a[8]*a[3]*a[6];
o[11] = -a[0]*a[5]*a[11] + a[0]*a[7]*a[9] + a[4]*a[1]*a[11]
- a[4]*a[3]*a[9] - a[8]*a[1]*a[7] + a[8]*a[3]*a[5];
o[15] = a[0]*a[5]*a[10] - a[0]*a[6]*a[9] - a[4]*a[1]*a[10]
+ a[4]*a[2]*a[9] + a[8]*a[1]*a[6] - a[8]*a[2]*a[5];
float det = a[0]*o[0] + a[1]*o[4] + a[2]*o[8] + a[3]*o[12];
if (det == 0.0f) {
// return identity if not invertible
Mat4 id = { {1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1} };
return id;
}
det = 1.0f / det;
for (int i = 0; i < 16; i++) o[i] *= det;
return inv;
}
Mat4 mat4_orthographic(float left, float right, float bottom, float top, float near, float far) {
Mat4 result = {0};
result.m[0] = 2.0f / (right - left);
result.m[5] = 2.0f / (top - bottom);
result.m[10] = -2.0f / (far - near);
result.m[12] = -(right + left) / (right - left);
result.m[13] = -(top + bottom) / (top - bottom);
result.m[14] = -(far + near) / (far - near);
result.m[15] = 1.0f;
return result;
}
Mat4 mat4_lookAt(Vec3 eye, Vec3 center, Vec3 up) {
Vec3 f = vec3_normalize(vec3_sub(center, eye));
Vec3 s = vec3_normalize(vec3_cross(f, up));
Vec3 u = vec3_cross(s, f);
Mat4 m = mat4_identity();
// rotation part
m.m[0] = s.x; m.m[4] = s.y; m.m[8] = s.z;
m.m[1] = u.x; m.m[5] = u.y; m.m[9] = u.z;
m.m[2] = -f.x; m.m[6] = -f.y; m.m[10] = -f.z;
// translation part
m.m[12] = -vec3_dot(s, eye);
m.m[13] = -vec3_dot(u, eye);
m.m[14] = vec3_dot(f, eye);
return m;
}
Mat4 mat4_mul(Mat4 a, Mat4 b) {
Mat4 r = {{0}};
for (int row=0; row<4; ++row)
for (int col=0; col<4; ++col)
for (int k=0; k<4; ++k)
r.m[row + col*4] += a.m[row + k*4] * b.m[k + col*4];
return r;
}
Mat4 mat4_rotate_y(float angle_rad) {
Mat4 m = mat4_identity();
float c = cosf(angle_rad);
float s = sinf(angle_rad);
m.m[0] = c; m.m[2] = s;
m.m[5] = 1.0f;
m.m[8] = -s; m.m[10] = c;
m.m[15] = 1.0f;
return m;
}
Mat4 mat4_rotate_x(float angle_rad) {
Mat4 m = mat4_identity();
float c = cosf(angle_rad);
float s = sinf(angle_rad);
m.m[0] = 1.0f;
m.m[5] = c; m.m[6] = -s;
m.m[9] = s; m.m[10] = c;
m.m[15] = 1.0f;
return m;
}
Mat4 mat4_rotate_z(float angle_rad) {
Mat4 m = mat4_identity();
float c = cosf(angle_rad);
float s = sinf(angle_rad);
m.m[0] = c; m.m[1] = -s;
m.m[4] = s; m.m[5] = c;
m.m[10] = 1.0f;
m.m[15] = 1.0f;
return m;
}