核心热路径(数学/内存/字符串/性能分析)用MASM汇编(SSE/AVX2) 外围系统(窗口/渲染/ECS/音频/UI/脚本)用C语言 含自研编辑器、VisualScript积木编程、中文渲染(glyph_atlas)
136 lines
3.8 KiB
C
136 lines
3.8 KiB
C
#include "camera.h"
|
|
|
|
#include <math.h>
|
|
#include <string.h>
|
|
|
|
#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;
|
|
}
|