Files
lity3d/Engine/Rendering/camera_controller.c
T

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;
}
}