#pragma once #include #include #include #define _USE_MATH_DEFINES #ifndef M_PI #define M_PI 3.14159265358979323846 #endif namespace Donut { enum class CameraMode { FPS, Orbital }; class Camera { public: Camera(float fov = 45.0f, float aspectRatio = 16.0f / 9.0f, float nearPlane = 0.1f, float farPlane = 100.0f); ~Camera() = default; // FPS Camera Methods void SetPosition(const glm::vec3& position) { m_Position = position; RecalculateViewMatrix(); } void SetRotation(const glm::vec3& rotation) { m_Rotation = rotation; RecalculateViewMatrix(); } const glm::vec3& GetPosition() const { return m_Position; } const glm::vec3& GetRotation() const { return m_Rotation; } glm::vec3 GetForwardDirection() const; glm::vec3 GetRightDirection() const; glm::vec3 GetUpDirection() const; const glm::mat4& GetProjectionMatrix() const { return m_ProjectionMatrix; } const glm::mat4& GetViewMatrix() const { return m_ViewMatrix; } const glm::mat4& GetViewProjectionMatrix() const { return m_ViewProjectionMatrix; } void SetProjection(float fov, float aspectRatio, float nearPlane, float farPlane); void OnMouseMove(float xOffset, float yOffset, bool constrainPitch = true); void MoveForward(float deltaTime); void MoveBackward(float deltaTime); void MoveRight(float deltaTime); void MoveLeft(float deltaTime); void MoveUp(float deltaTime); void MoveDown(float deltaTime); void SetMouseSensitivity(float sensitivity) { m_MouseSensitivity = sensitivity; } float GetMouseSensitivity() const { return m_MouseSensitivity; } void SetMovementSpeed(float speed) { m_MovementSpeed = speed; } float GetMovementSpeed() const { return m_MovementSpeed; } // Orbital Camera Methods void SetOrbitalMode(bool enabled); bool IsOrbitalMode() const { return m_CameraMode == CameraMode::Orbital; } void SetTarget(const glm::vec3& target) { m_Target = target; } const glm::vec3& GetTarget() const { return m_Target; } void SetRadius(double radius) { m_Radius = radius; } double GetRadius() const { return m_Radius; } void SetMinRadius(double minRadius) { m_MinRadius = minRadius; } double GetMinRadius() const { return m_MinRadius; } void SetMaxRadius(double maxRadius) { m_MaxRadius = maxRadius; } double GetMaxRadius() const { return m_MaxRadius; } void SetAzimuth(float azimuth) { m_Azimuth = azimuth; } float GetAzimuth() const { return m_Azimuth; } void SetElevation(float elevation) { m_Elevation = elevation; } float GetElevation() const { return m_Elevation; } void SetOrbitSpeed(float orbitSpeed) { m_OrbitSpeed = orbitSpeed; } float GetOrbitSpeed() const { return m_OrbitSpeed; } void SetZoomSpeed(double zoomSpeed) { m_ZoomSpeed = zoomSpeed; } double GetZoomSpeed() const { return m_ZoomSpeed; } // Orbital camera position calculation glm::vec3 GetOrbitalPosition() const; // Input handling for orbital camera void ProcessOrbitalMouseMove(double x, double y); void ProcessOrbitalMouseButton(int button, int action, int mods); void ProcessOrbitalScroll(double xoffset, double yoffset); // State management bool IsDragging() const { return m_Dragging; } bool IsPanning() const { return m_Panning; } bool IsMoving() const { return m_Moving; } private: void RecalculateViewMatrix(); void RecalculateProjectionMatrix(); void UpdateOrbitalState(); private: // Camera mode CameraMode m_CameraMode = CameraMode::FPS; // FPS Camera members glm::mat4 m_ProjectionMatrix; glm::mat4 m_ViewMatrix; glm::mat4 m_ViewProjectionMatrix; glm::vec3 m_Position = { 0.0f, 0.0f, 3.0f }; glm::vec3 m_Rotation = { 0.0f, 0.0f, 0.0f }; float m_FOV = 45.0f; float m_AspectRatio = 16.0f / 9.0f; float m_NearPlane = 0.1f; float m_FarPlane = 100.0f; float m_MouseSensitivity = 0.1f; float m_MovementSpeed = 5.0f; bool m_FirstMouse = true; float m_LastX = 0.0f; float m_LastY = 0.0f; // Orbital Camera members glm::vec3 m_Target = glm::vec3(0.0f, 0.0f, 0.0f); double m_Radius = 6.34194e10; double m_MinRadius = 1e10; double m_MaxRadius = 1e12; float m_Azimuth = 0.0f; float m_Elevation = static_cast(M_PI) / 2.0f; float m_OrbitSpeed = 0.01f; double m_ZoomSpeed = 25e9f; bool m_Dragging = false; bool m_Panning = false; bool m_Moving = false; double m_OrbitalLastX = 0.0; double m_OrbitalLastY = 0.0; }; }