hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/src/core/camera.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/camera.cpp')
-rw-r--r--src/core/camera.cpp180
1 files changed, 142 insertions, 38 deletions
diff --git a/src/core/camera.cpp b/src/core/camera.cpp
index f580191..43cb1ee 100644
--- a/src/core/camera.cpp
+++ b/src/core/camera.cpp
@@ -28,22 +28,32 @@ namespace Donut
void Camera::recalculate_view_matrix()
{
- float pitch = glm::radians(m_rotation.x);
- float yaw = glm::radians(m_rotation.y);
- float roll = glm::radians(m_rotation.z);
+ if (m_camera_mode == CameraMode::FPS)
+ {
+ float pitch = glm::radians(m_rotation.x);
+ float yaw = glm::radians(m_rotation.y);
+ float roll = glm::radians(m_rotation.z);
- glm::vec3 direction;
- direction.x = cos(yaw) * cos(pitch);
- direction.y = sin(pitch);
- direction.z = sin(yaw) * cos(pitch);
+ glm::vec3 direction;
+ direction.x = cos(yaw) * cos(pitch);
+ direction.y = sin(pitch);
+ direction.z = sin(yaw) * cos(pitch);
- glm::vec3 world_up(0.0f, 1.0f, 0.0f);
- glm::vec3 front = glm::normalize(direction);
- glm::vec3 right = glm::normalize(glm::cross(front, world_up));
- glm::vec3 up = glm::normalize(glm::cross(right, front));
+ glm::vec3 world_up(0.0f, 1.0f, 0.0f);
+ glm::vec3 front = glm::normalize(direction);
+ glm::vec3 right = glm::normalize(glm::cross(front, world_up));
+ glm::vec3 up = glm::normalize(glm::cross(right, front));
- m_view_matrix = glm::lookAt(m_position, m_position + front, up);
- m_view_projection_matrix = m_projection_matrix * m_view_matrix;
+ m_view_matrix = glm::lookAt(m_position, m_position + front, up);
+ m_view_projection_matrix = m_projection_matrix * m_view_matrix;
+ }
+ else if (m_camera_mode == CameraMode::Orbital)
+ {
+ glm::vec3 position = get_orbital_position();
+ glm::vec3 world_up(0.0f, 1.0f, 0.0f);
+ m_view_matrix = glm::lookAt(position, m_target, world_up);
+ m_view_projection_matrix = m_projection_matrix * m_view_matrix;
+ }
}
glm::vec3 Camera::get_forward_direction() const
@@ -72,58 +82,152 @@ namespace Donut
void Camera::on_mouse_move(float x_offset, float y_offset, bool constrain_pitch)
{
- x_offset *= m_mouse_sensitivity;
- y_offset *= m_mouse_sensitivity;
+ if (m_camera_mode == CameraMode::FPS)
+ {
+ x_offset *= m_mouse_sensitivity;
+ y_offset *= m_mouse_sensitivity;
- m_rotation.y += x_offset;
- m_rotation.x += y_offset;
+ m_rotation.y += x_offset;
+ m_rotation.x += y_offset;
- if (constrain_pitch)
- {
- if (m_rotation.x > 89.0f)
- m_rotation.x = 89.0f;
- if (m_rotation.x < -89.0f)
- m_rotation.x = -89.0f;
- }
+ if (constrain_pitch)
+ {
+ if (m_rotation.x > 89.0f)
+ m_rotation.x = 89.0f;
+ if (m_rotation.x < -89.0f)
+ m_rotation.x = -89.0f;
+ }
- recalculate_view_matrix();
+ recalculate_view_matrix();
+ }
}
void Camera::move_forward(float delta_time)
{
- m_position += get_forward_direction() * m_movement_speed * delta_time;
- recalculate_view_matrix();
+ if (m_camera_mode == CameraMode::FPS)
+ {
+ m_position += get_forward_direction() * m_movement_speed * delta_time;
+ recalculate_view_matrix();
+ }
}
void Camera::move_backward(float delta_time)
{
- m_position -= get_forward_direction() * m_movement_speed * delta_time;
- recalculate_view_matrix();
+ if (m_camera_mode == CameraMode::FPS)
+ {
+ m_position -= get_forward_direction() * m_movement_speed * delta_time;
+ recalculate_view_matrix();
+ }
}
void Camera::move_right(float delta_time)
{
- m_position += get_right_direction() * m_movement_speed * delta_time;
- recalculate_view_matrix();
+ if (m_camera_mode == CameraMode::FPS)
+ {
+ m_position += get_right_direction() * m_movement_speed * delta_time;
+ recalculate_view_matrix();
+ }
}
void Camera::move_left(float delta_time)
{
- m_position -= get_right_direction() * m_movement_speed * delta_time;
- recalculate_view_matrix();
+ if (m_camera_mode == CameraMode::FPS)
+ {
+ m_position -= get_right_direction() * m_movement_speed * delta_time;
+ recalculate_view_matrix();
+ }
}
void Camera::move_up(float delta_time)
{
- glm::vec3 world_up(0.0f, 1.0f, 0.0f);
- m_position += world_up * m_movement_speed * delta_time;
- recalculate_view_matrix();
+ if (m_camera_mode == CameraMode::FPS)
+ {
+ glm::vec3 world_up(0.0f, 1.0f, 0.0f);
+ m_position += world_up * m_movement_speed * delta_time;
+ recalculate_view_matrix();
+ }
}
void Camera::move_down(float delta_time)
{
- glm::vec3 world_up(0.0f, 1.0f, 0.0f);
- m_position -= world_up * m_movement_speed * delta_time;
+ if (m_camera_mode == CameraMode::FPS)
+ {
+ glm::vec3 world_up(0.0f, 1.0f, 0.0f);
+ m_position -= world_up * m_movement_speed * delta_time;
+ recalculate_view_matrix();
+ }
+ }
+
+ void Camera::set_orbital_mode(bool enabled)
+ {
+ m_camera_mode = enabled ? CameraMode::Orbital : CameraMode::FPS;
+ recalculate_view_matrix();
+ }
+
+ glm::vec3 Camera::get_orbital_position() const
+ {
+ float clamped_elevation = glm::clamp(m_elevation, 0.01f, float(M_PI) - 0.01f);
+ return glm::vec3(
+ m_radius * sin(clamped_elevation) * cos(m_azimuth),
+ m_radius * cos(clamped_elevation),
+ m_radius * sin(clamped_elevation) * sin(m_azimuth)
+ );
+ }
+
+ void Camera::process_orbital_mouse_move(double x, double y)
+ {
+ if (m_dragging && !m_panning)
+ {
+ float dx = float(x - m_orbital_last_x);
+ float dy = float(y - m_orbital_last_y);
+
+ m_azimuth += dx * m_orbit_speed;
+ m_elevation -= dy * m_orbit_speed;
+ m_elevation = glm::clamp(m_elevation, 0.01f, float(M_PI) - 0.01f);
+ }
+
+ m_orbital_last_x = x;
+ m_orbital_last_y = y;
+ update_orbital_state();
recalculate_view_matrix();
}
+
+ void Camera::process_orbital_mouse_button(int button, int action, int mods)
+ {
+ if (button == GLFW_MOUSE_BUTTON_LEFT)
+ {
+ if (action == GLFW_PRESS)
+ {
+ m_dragging = true;
+ m_panning = false;
+ }
+ else if (action == GLFW_RELEASE)
+ {
+ m_dragging = false;
+ m_panning = false;
+ }
+ }
+ update_orbital_state();
+ }
+
+ void Camera::process_orbital_scroll(double x_offset, double y_offset)
+ {
+ m_radius -= y_offset * m_zoom_speed;
+ m_radius = glm::clamp(m_radius, m_min_radius, m_max_radius);
+ update_orbital_state();
+ recalculate_view_matrix();
+ }
+
+ void Camera::update_orbital_state()
+ {
+ m_target = glm::vec3(0.0f, 0.0f, 0.0f);
+ if (m_dragging || m_panning)
+ {
+ m_moving = true;
+ }
+ else
+ {
+ m_moving = false;
+ }
+ }
}