99 lines
3.0 KiB
C
99 lines
3.0 KiB
C
#include "camera_controller.h"
|
|
#include <math.h>
|
|
|
|
#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;
|
|
}
|
|
}
|