#include "Scene.hpp" namespace Scene { glm::vec3 OrbitCamera::eye() const { const float ce = std::cos(elevation), se = std::sin(elevation); const float ca = std::cos(azimuth), sa = std::sin(azimuth); return target + radius * glm::vec3(ce * ca, ce * sa, se); } glm::mat4 OrbitCamera::view() const { return glm::lookAt(eye(), target, glm::vec3(0, 0, 1)); // Z-up } glm::mat4 OrbitCamera::proj() const { return glm::perspective(glm::radians(fov_deg), aspect, nearZ, farZ); } // controls (delta-based, feed from input) void OrbitCamera::dolly(float dr) { radius = std::max(0.05f, radius * std::exp(-dr)); } void OrbitCamera::rotate(float dAzim, float dElev) { azimuth += dAzim; elevation = std::clamp(elevation + dElev, -1.55f, +1.55f); } void OrbitCamera::pan_world(const glm::vec2& d) { const float ce = std::cos(elevation), se = std::sin(elevation); const float ca = std::cos(azimuth), sa = std::sin(azimuth); glm::vec3 right = glm::normalize(glm::vec3(-sa, ca, 0.0f)); glm::vec3 up = glm::normalize(glm::vec3(-ca * se, -sa * se, ce)); target += (-d.x * right + d.y * up); } // keep aspect updated on resize void OrbitCamera::set_aspect_from_pixels(int W, int H) { aspect = (H > 0) ? float(W) / float(H) : 1.0f; } } // namespace Scene