72 lines
2.4 KiB
C++
72 lines
2.4 KiB
C++
#include "Camera.hpp"
|
|
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
|
|
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
|