#include "Camera.hpp" #include #include #include namespace engine { Camera::Camera() { reset(); } void Camera::onMouseDrag(float deltaX, float deltaY) { const float rotateSpeed = 0.005f; targetYaw_ -= deltaX * rotateSpeed; targetPitch_ += deltaY * rotateSpeed; targetPitch_ = std::clamp(targetPitch_, kMinPitch, kMaxPitch); } void Camera::onMousePan(float deltaX, float deltaY) { // Pan moves the orbit focus along the camera's local right/up axes, // scaled by distance so panning feels consistent whether zoomed in // close to a planet or viewing the whole system. glm::vec3 forward = glm::normalize(currentFocus_ - currentPosition_); glm::vec3 right = glm::normalize(glm::cross(forward, glm::vec3(0.0f, 1.0f, 0.0f))); glm::vec3 up = glm::normalize(glm::cross(right, forward)); float panSpeed = 0.0015f * currentDistance_; targetFocus_ += (-right * deltaX + up * deltaY) * panSpeed; } void Camera::onScroll(float deltaY) { float zoomFactor = std::pow(0.9f, deltaY); targetDistance_ = std::clamp(targetDistance_ * zoomFactor, kMinDistance, kMaxDistance); } void Camera::reset() { targetYaw_ = -0.6f; targetPitch_ = 0.45f; targetDistance_ = 18.0f; targetFocus_ = glm::vec3(0.0f); } void Camera::focusOn(const glm::vec3& worldPoint, float suggestedDistance) { targetFocus_ = worldPoint; targetDistance_ = std::clamp(suggestedDistance, kMinDistance, kMaxDistance); } void Camera::update(float deltaTime) { // Exponential ("critically damped") smoothing: each frame closes a // fixed fraction of the remaining gap to the target, giving smooth // deceleration without overshoot regardless of frame rate. float t = 1.0f - std::exp(-kSmoothingSpeed * deltaTime); currentYaw_ += (targetYaw_ - currentYaw_) * t; currentPitch_ += (targetPitch_ - currentPitch_) * t; currentDistance_ += (targetDistance_ - currentDistance_) * t; currentFocus_ += (targetFocus_ - currentFocus_) * t; glm::vec3 offset; offset.x = currentDistance_ * std::cos(currentPitch_) * std::sin(currentYaw_); offset.y = currentDistance_ * std::sin(currentPitch_); offset.z = currentDistance_ * std::cos(currentPitch_) * std::cos(currentYaw_); currentPosition_ = currentFocus_ + offset; } glm::mat4 Camera::viewMatrix() const { return glm::lookAt(currentPosition_, currentFocus_, glm::vec3(0.0f, 1.0f, 0.0f)); } } // namespace engine