Files
gpu-renderer/linear_alg.c
T

134 lines
2.5 KiB
C

#include "linear_alg.h"
#include <math.h>
vec3_t vec3_sub(vec3_t v, vec3_t u)
{
return (vec3_t) { v.x - u.x, v.y - u.y, v.z - u.z };
}
float vec3_len(vec3_t v)
{
return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
}
vec3_t vec3_norm(vec3_t v)
{
const float l = vec3_len(v);
return (vec3_t) { v.x / l, v.y / l, v.z / l };
}
float vec3_dot(vec3_t v, vec3_t u)
{
return v.x * u.x + v.y * u.y + v.z * u.z;
}
vec3_t vec3_cross(vec3_t v, vec3_t u)
{
return (vec3_t) {
v.y * u.z - v.z * u.y,
v.z * u.x - v.x * u.z,
v.x * u.y - v.y * u.x,
};
}
mat4_t mat4_mul(mat4_t m, mat4_t n)
{
#define ELEM(i, j) m.x.i *n.j.x + m.y.i *n.j.y + m.z.i *n.j.z + m.w.i *n.j.w
return (mat4_t) {
{ ELEM(x, x), ELEM(y, x), ELEM(z, x), ELEM(w, x) },
{ ELEM(x, y), ELEM(y, y), ELEM(z, y), ELEM(w, y) },
{ ELEM(x, z), ELEM(y, z), ELEM(z, z), ELEM(w, z) },
{ ELEM(x, w), ELEM(y, w), ELEM(z, w), ELEM(w, w) },
};
#undef ELEM
}
mat4_t mat4_lookat(vec3_t camera, vec3_t target, vec3_t up)
{
const vec3_t s = vec3_sub(target, camera);
const vec3_t s_hat = vec3_norm(s);
const vec3_t u_hat = vec3_norm(vec3_cross(up, s_hat));
const vec3_t v_hat = vec3_cross(s_hat, u_hat);
return (mat4_t) {
{ u_hat.x, v_hat.x, s_hat.x, 0 },
{ u_hat.y, v_hat.y, s_hat.y, 0 },
{ u_hat.z, v_hat.z, s_hat.z, 0 },
{
-vec3_dot(u_hat, camera),
-vec3_dot(v_hat, camera),
-vec3_dot(s_hat, camera),
1,
},
};
}
mat4_t mat4_perspective(float aspect, float fov, float near, float far)
{
const float r = 2 * near * tanf(fov / 2);
const float t = r * aspect;
return (mat4_t) {
{ near / t, 0, 0, 0 },
{ 0, -near / r, 0, 0 },
{ 0, 0, far / (far - near), 1 },
{ 0, 0, -far * near / (far - near), 0 },
};
}
mat4_t mat4_translate_vec3(vec3_t v)
{
return (mat4_t) {
{ 1, 0, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 0, 1, 0 },
{ v.x, v.y, v.z, 1 },
};
}
mat4_t mat4_scale_vec3(vec3_t v)
{
return (mat4_t) {
{ v.x, 0, 0, 0 },
{ 0, v.y, 0, 0 },
{ 0, 0, v.z, 0 },
{ 0, 0, 0, 1 },
};
}
mat4_t mat4_rotate_quaternion(vec4_t q)
{
const float xx = q.x * q.x;
const float xy = q.x * q.y;
const float xz = q.x * q.z;
const float xw = q.x * q.w;
const float yy = q.y * q.y;
const float yz = q.y * q.z;
const float yw = q.y * q.w;
const float zz = q.z * q.z;
const float zw = q.z * q.w;
return (mat4_t) {
{
1 - 2 * (yy + zz),
2 * (xy + zw),
2 * (xz - yw),
0,
},
{
2 * (xy - zw),
1 - 2 * (xx + zz),
2 * (yz + xw),
0,
},
{
2 * (xz + yw),
2 * (yz - xw),
1 - 2 * (xx + yy),
0,
},
{ 0, 0, 0, 1 },
};
}