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

101 lines
2.3 KiB
C

const vec3 WORLD_UP = {0.0f, 0.0f, 1.0f};
typedef struct camera {
vec3 position;
vec3 front;
vec3 right;
float yaw;
float pitch;
mat4 view_mat;
} camera_t;
void
camera_update_view(camera_t* camera)
{
// Create orthonormal basis for camera orientation
vec3 target = vec3_add(camera->position, camera->front);
vec3 front = vec3_normalize(vec3_sub(target, camera->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(camera->position, side),
up.x, up.y, up.z, -vec3_dot(camera->position, up),
front.x, front.y, front.z, -vec3_dot(camera->position, front),
0.0f, 0.0f, 0.0f, 1.0f
};
camera->view_mat = view_mat;
}
camera_t
camera_create(vec3 position)
{
camera_t result = {
.position = position,
.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)
{
// Preserve Z
float position_z = camera->position.z;
// Forward/Backward
camera->position = vec3_add(camera->position, vec3_mult(camera->front, velocity.y));
// Left/Right
camera->right = vec3_cross(camera->front, WORLD_UP);
camera->position = vec3_add(camera->position, vec3_mult(vec3_normalize(camera->right), velocity.x));
// Restore Z
camera->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);
}