1
0
Fork 0
2022-untitled-game/code/game/engine/camera.c

94 lines
2.3 KiB
C
Raw Normal View History

2022-08-01 23:11:10 +00:00
camera_t
2022-08-02 16:35:50 +00:00
camera_create(handle_t transform)
2022-08-01 23:11:10 +00:00
{
camera_t result = {
2022-08-02 16:35:50 +00:00
.transform = transform,
2022-08-01 23:11:10 +00:00
.front = {0.0f, 1.0f, 0.0f},
.right = {1.0f, 0.0f, 0.0f},
.yaw = 90.0f};
camera_update_view(&result);
return result;
}
void
camera_move(camera_t* camera, vec3 velocity)
{
2022-08-02 16:35:50 +00:00
transform_t* transform = get_transform(camera->transform);
2022-08-01 23:11:10 +00:00
// Preserve Z
2022-08-02 16:35:50 +00:00
float position_z = transform->position.z;
2022-08-01 23:11:10 +00:00
// Forward/Backward
2022-08-02 16:35:50 +00:00
transform->position = vec3_add(transform->position, vec3_mult(camera->front, velocity.y));
2022-08-01 23:11:10 +00:00
// Left/Right
camera->right = vec3_cross(camera->front, WORLD_UP);
2022-08-02 16:35:50 +00:00
transform->position = vec3_add(transform->position, vec3_mult(vec3_normalize(camera->right), velocity.x));
2022-08-01 23:11:10 +00:00
// Restore Z
2022-08-02 16:35:50 +00:00
transform->position.z = position_z;
2022-08-01 23:11:10 +00:00
}
void
camera_rotate(camera_t* camera, float offset_x, float offset_y)
{
camera->yaw += offset_x;
camera->pitch += offset_y;
// Limit the camera's up/down motion
if (camera->pitch > 60.0f)
{
camera->pitch = 60.0f;
}
else if (camera->pitch < -60.0f)
{
camera->pitch = -60.0f;
}
// Ensure camera yaw circles around 360 degrees rather than increases indefinitely
if (camera->yaw > 360.0f)
{
camera->yaw -= 360.0f;
}
else if (camera->yaw < -360.0f)
{
camera->yaw += 360.0f;
}
float yaw_rad = DEG_TO_RAD(camera->yaw);
float pitch_rad = DEG_TO_RAD(camera->pitch);
camera->front.x = cosf(yaw_rad) * cosf(pitch_rad);
camera->front.y = sinf(yaw_rad) * cosf(pitch_rad);
camera->front.z = sinf(pitch_rad);
camera->front = vec3_normalize(camera->front);
}
2022-08-02 16:35:50 +00:00
void
camera_update_view(camera_t* camera)
{
transform_t* transform = get_transform(camera->transform);
// Create orthonormal basis for camera orientation
vec3 target = vec3_add(transform->position, camera->front);
vec3 front = vec3_normalize(vec3_sub(target, transform->position));
vec3 side = vec3_normalize(vec3_cross(front, WORLD_UP));
vec3 up = vec3_cross(side, front);
// Create an inverse rotation matrix
// Orthogonal inverse is a simple transpose where the columns become the rows
// +X: Right
// +Y: Forward
// +Z: Up
mat4 view_mat = {
side.x, side.y, side.z, -vec3_dot(transform->position, side),
up.x, up.y, up.z, -vec3_dot(transform->position, up),
front.x, front.y, front.z, -vec3_dot(transform->position, front),
0.0f, 0.0f, 0.0f, 1.0f
};
camera->view_mat = view_mat;
}