94 lines
2.3 KiB
C
94 lines
2.3 KiB
C
camera_t
|
|
camera_create(handle_t transform)
|
|
{
|
|
camera_t result = {
|
|
.transform = transform,
|
|
.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)
|
|
{
|
|
transform_t* transform = get_transform(camera->transform);
|
|
|
|
// Preserve Z
|
|
float position_z = transform->position.z;
|
|
|
|
// Forward/Backward
|
|
transform->position = vec3_add(transform->position, vec3_mult(camera->front, velocity.y));
|
|
|
|
// Left/Right
|
|
camera->right = vec3_cross(camera->front, WORLD_UP);
|
|
transform->position = vec3_add(transform->position, vec3_mult(vec3_normalize(camera->right), velocity.x));
|
|
|
|
// Restore Z
|
|
transform->position.z = position_z;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|