diff --git a/main.c b/main.c index 5a2ab0b..d7fbf21 100644 --- a/main.c +++ b/main.c @@ -106,10 +106,39 @@ key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) } } +static vec3_t sub(vec3_t v, vec3_t u) +{ + return (vec3_t) { v.x - u.x, v.y - u.y, v.z - u.z }; +} + +static float len(vec3_t v) +{ + return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); +} + +static vec3_t norm(vec3_t v) +{ + const float s = len(v); + return (vec3_t) { v.x / s, v.y / s, v.z / s }; +} + +static float dot(vec3_t v, vec3_t u) +{ + return v.x * u.x + v.y * u.y + v.z * u.z; +} + +static vec3_t 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, + }; +} + static mat4_t 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 +#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) }, @@ -119,6 +148,22 @@ static mat4_t mul(mat4_t m, mat4_t n) #undef MUL_ELEM } +static mat4_t lookat(vec3_t cam, vec3_t tgt, vec3_t up) +{ + const vec3_t s = sub(tgt, cam); + + const vec3_t s_hat = norm(s); + const vec3_t u_hat = norm(cross(up, s_hat)); + const vec3_t v_hat = 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 }, + { -dot(u_hat, cam), -dot(v_hat, cam), -dot(s_hat, cam), 1 }, + }; +} + static mat4_t persp(float aspect, float fov, float ncp, float fcp) { const float r = 2 * ncp * tanf(fov / 2); @@ -155,9 +200,11 @@ int main() gpu_ctx_t gpu; gpu_init(&gpu, &gpu_config); + const vec3_t cam = { 2, 2, -2 }; + const vec3_t tgt = { 0, 0, 0 }; mvp_t mvp = { .model = SCALE(2), - .view = TRANSLATE(0, 0, 4.0), + .view = lookat(cam, tgt, (vec3_t) { 0, 1, 0 }), .proj = persp((float)W / H, M_PI / 6, 0.1, 10.0), };