#include "camera.h" #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif Camera camera_perspective(float fov_y, float aspect, float near_z, float far_z) { Camera cam = {0}; cam.type = CAMERA_PERSPECTIVE; cam.position = (Vec3){0, 0, -5}; cam.target = (Vec3){0, 0, 0}; cam.up = (Vec3){0, 1, 0}; cam.fov_y = fov_y; cam.aspect = aspect; cam.near_z = near_z; cam.far_z = far_z; cam.dirty = 1; return cam; } Camera camera_orthographic(float width, float height, float near_z, float far_z) { Camera cam = {0}; cam.type = CAMERA_ORTHOGRAPHIC; cam.position = (Vec3){0, 0, -5}; cam.target = (Vec3){0, 0, 0}; cam.up = (Vec3){0, 1, 0}; cam.ortho_width = width; cam.ortho_height = height; cam.near_z = near_z; cam.far_z = far_z; cam.dirty = 1; return cam; } void camera_update(Camera* camera) { if (!camera->dirty) return; mat4_lookat(&camera->position, &camera->target, &camera->up, &camera->view); if (camera->type == CAMERA_PERSPECTIVE) { mat4_perspective(camera->fov_y, camera->aspect, camera->near_z, camera->far_z, &camera->projection); } else { mat4_orthographic(camera->ortho_width, camera->ortho_height, camera->near_z, camera->far_z, &camera->projection); } camera->dirty = 0; } const Mat4* camera_get_view(Camera* camera) { camera_update(camera); return &camera->view; } const Mat4* camera_get_projection(Camera* camera) { camera_update(camera); return &camera->projection; } void camera_move_forward(Camera* camera, float distance) { Vec3 dir; vec3_sub(&camera->target, &camera->position, &dir); vec3_normalize(&dir, &dir); Vec3 move; vec3_scale(&dir, distance, &move); vec3_add(&camera->position, &move, &camera->position); vec3_add(&camera->target, &move, &camera->target); camera->dirty = 1; } void camera_move_right(Camera* camera, float distance) { Vec3 forward, right; vec3_sub(&camera->target, &camera->position, &forward); vec3_normalize(&forward, &forward); vec3_cross(&forward, &camera->up, &right); vec3_normalize(&right, &right); Vec3 move; vec3_scale(&right, distance, &move); vec3_add(&camera->position, &move, &camera->position); vec3_add(&camera->target, &move, &camera->target); camera->dirty = 1; } void camera_move_up(Camera* camera, float distance) { Vec3 move; vec3_scale(&camera->up, distance, &move); vec3_add(&camera->position, &move, &camera->position); vec3_add(&camera->target, &move, &camera->target); camera->dirty = 1; } void camera_rotate_yaw(Camera* camera, float angle) { Vec3 forward; vec3_sub(&camera->target, &camera->position, &forward); float cs = cosf(angle), sn = sinf(angle); Vec3 right; vec3_cross(&forward, &camera->up, &right); vec3_normalize(&right, &right); Vec3 new_forward = { forward.x * cs + right.x * sn, forward.y * cs + right.y * sn, forward.z * cs + right.z * sn, }; vec3_add(&camera->position, &new_forward, &camera->target); camera->dirty = 1; } void camera_rotate_pitch(Camera* camera, float angle) { Vec3 forward; vec3_sub(&camera->target, &camera->position, &forward); Vec3 right; vec3_cross(&forward, &camera->up, &right); vec3_normalize(&right, &right); float cs = cosf(angle), sn = sinf(angle); Vec3 new_forward = { forward.x * cs + camera->up.x * sn, forward.y * cs + camera->up.y * sn, forward.z * cs + camera->up.z * sn, }; Vec3 new_up; vec3_cross(&right, &new_forward, &new_up); camera->up = new_up; vec3_add(&camera->position, &new_forward, &camera->target); camera->dirty = 1; } void camera_look_at(Camera* camera, Vec3 target) { camera->target = target; camera->dirty = 1; }