diff options
| author | hachem <im@hachem.wtf> | 2025-08-14 18:21:00 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2025-08-14 18:21:00 +0200 |
| commit | 3d8d3259e1cf5a7d88e5d1e530cc8c9bf9140734 (patch) | |
| tree | 450b674caaf60327104aa76375c045f1f8f77076 /src/core/camera.cpp | |
| parent | 79045760ce6100b4c87846d793f9dceeba4c9c36 (diff) | |
feat: I am going to throw my computer out a window
Diffstat (limited to 'src/core/camera.cpp')
| -rw-r--r-- | src/core/camera.cpp | 180 |
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; + } + } } |
