#include "camera_controller.h" #include #ifndef M_PI #define M_PI 3.14159265358979323846f #endif CameraController camera_controller_create(Camera* camera) { CameraController ctrl = {0}; ctrl.camera = camera; ctrl.mode = CAMERA_MODE_FLY; ctrl.move_speed = 10.0f; ctrl.mouse_sensitivity = 0.003f; ctrl.height_offset = 1.75f; ctrl.pitch_min = -1.45f; ctrl.pitch_max = 1.45f; ctrl.yaw = 0.0f; ctrl.pitch = 0.0f; ctrl.ground_height_fn = NULL; ctrl.ground_user = NULL; return ctrl; } void camera_controller_set_ground_callback(CameraController* ctrl, float (*get_height)(float x, float z, void* user), void* user) { ctrl->ground_height_fn = get_height; ctrl->ground_user = user; } void camera_controller_set_mode(CameraController* ctrl, CameraMode mode) { ctrl->mode = mode; } void camera_controller_look(CameraController* ctrl, float delta_x, float delta_y) { ctrl->yaw -= delta_x * ctrl->mouse_sensitivity; ctrl->pitch -= delta_y * ctrl->mouse_sensitivity; if (ctrl->pitch < ctrl->pitch_min) ctrl->pitch = ctrl->pitch_min; if (ctrl->pitch > ctrl->pitch_max) ctrl->pitch = ctrl->pitch_max; // 重建 target Vec3 forward; forward.x = cosf(ctrl->pitch) * sinf(ctrl->yaw); forward.y = sinf(ctrl->pitch); forward.z = cosf(ctrl->pitch) * cosf(ctrl->yaw); vec3_normalize(&forward, &forward); vec3_add(&ctrl->camera->position, &forward, &ctrl->camera->target); ctrl->camera->dirty = 1; } void camera_controller_move(CameraController* ctrl, Vec3 dir, float dt) { Camera* cam = ctrl->camera; Vec3 forward, right, up; vec3_sub(&cam->target, &cam->position, &forward); forward.y = 0.0f; vec3_normalize(&forward, &forward); vec3_cross(&cam->up, &forward, &right); vec3_normalize(&right, &right); up = cam->up; Vec3 move = {0}; Vec3 tmp; vec3_scale(&right, dir.x, &tmp); vec3_add(&move, &tmp, &move); vec3_scale(&up, dir.y, &tmp); vec3_add(&move, &tmp, &move); vec3_scale(&forward, dir.z, &tmp); vec3_add(&move, &tmp, &move); float len = vec3_length(&move); if (len > 0.0001f) { vec3_scale(&move, ctrl->move_speed * dt / len, &move); vec3_add(&cam->position, &move, &cam->position); vec3_add(&cam->target, &move, &cam->target); cam->dirty = 1; } } void camera_controller_update(CameraController* ctrl, float dt) { (void)dt; if (ctrl->mode != CAMERA_MODE_WALK) return; if (!ctrl->ground_height_fn) return; float ground = ctrl->ground_height_fn(ctrl->camera->position.x, ctrl->camera->position.z, ctrl->ground_user); float desired_y = ground + ctrl->height_offset; float delta = desired_y - ctrl->camera->position.y; if (fabsf(delta) > 0.01f) { Vec3 move = {0, delta, 0}; vec3_add(&ctrl->camera->position, &move, &ctrl->camera->position); vec3_add(&ctrl->camera->target, &move, &ctrl->camera->target); ctrl->camera->dirty = 1; } }