#include "render/camera.h" #define PITCH_LIMIT 89.0f static void updateVectors(Camera *cam) { float yaw = deg2rad(cam->yaw), pitch = deg2rad(cam->pitch); cam->front = vec3_normalize(vec3(cosf(yaw) * cosf(pitch), sinf(pitch), sinf(yaw) * cosf(pitch))); cam->right = vec3_normalize(vec3_cross(cam->front, vec3(0, 1, 0))); cam->up = vec3_normalize(vec3_cross(cam->right, cam->front)); } void Camera_init(Camera *cam, Vec3 position, float yaw, float pitch, float fov) { *cam = (Camera){ .position = position, .yaw = yaw, .pitch = pitch, .fov = fov, .near_z = 0.1f, .far_z = 420.0f, /* across the whole site */ }; updateVectors(cam); Camera_updateMatrices(cam, 1.0f); } void Camera_rotate(Camera *cam, float yaw_delta, float pitch_delta) { cam->yaw += yaw_delta; cam->pitch += pitch_delta; if (cam->pitch > PITCH_LIMIT) cam->pitch = PITCH_LIMIT; if (cam->pitch < -PITCH_LIMIT) cam->pitch = -PITCH_LIMIT; updateVectors(cam); } void Camera_updateMatrices(Camera *cam, float aspect) { cam->projection = mat4_perspective(cam->fov, aspect, cam->near_z, cam->far_z); /* Sway and roll only change what we see, not where we walk */ float yaw = deg2rad(cam->yaw + cam->sway_yaw); float pitch = deg2rad(clampf(cam->pitch + cam->sway_pitch, -PITCH_LIMIT, PITCH_LIMIT)); Vec3 front = vec3(cosf(yaw) * cosf(pitch), sinf(pitch), sinf(yaw) * cosf(pitch)); Vec3 right = vec3_normalize(vec3_cross(front, vec3(0, 1, 0))); Vec3 up = vec3_cross(right, front); float roll = deg2rad(cam->roll); up = vec3_add(vec3_scale(up, cosf(roll)), vec3_scale(right, sinf(roll))); cam->view = mat4_look_at(cam->position, vec3_add(cam->position, front), up); }