aboutsummaryrefslogtreecommitdiff
path: root/src/Core
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2025-08-14 18:21:00 +0200
committerhachem <im@hachem.wtf>2025-08-14 18:21:00 +0200
commitbc2d88c799cb3913a5defe4ea9ddea9c56814349 (patch)
treeea60d47c5924ba56f6d84de9d7baa38f1710f13a /src/Core
parent5265d5f8cacdb8af523e2b2fbfa45f0ef44b9995 (diff)
[help]: I am going to throw my computer out a window
Diffstat (limited to 'src/Core')
-rw-r--r--src/Core/Camera.cpp181
-rw-r--r--src/Core/Camera.h75
2 files changed, 218 insertions, 38 deletions
diff --git a/src/Core/Camera.cpp b/src/Core/Camera.cpp
index 4dff2d7..6f86124 100644
--- a/src/Core/Camera.cpp
+++ b/src/Core/Camera.cpp
@@ -28,22 +28,32 @@ namespace Donut
void Camera::RecalculateViewMatrix()
{
- float pitch = glm::radians(m_Rotation.x);
- float yaw = glm::radians(m_Rotation.y);
- float roll = glm::radians(m_Rotation.z);
+ if (m_CameraMode == 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 worldUp(0.0f, 1.0f, 0.0f);
- glm::vec3 front = glm::normalize(direction);
- glm::vec3 right = glm::normalize(glm::cross(front, worldUp));
- glm::vec3 up = glm::normalize(glm::cross(right, front));
+ glm::vec3 worldUp(0.0f, 1.0f, 0.0f);
+ glm::vec3 front = glm::normalize(direction);
+ glm::vec3 right = glm::normalize(glm::cross(front, worldUp));
+ glm::vec3 up = glm::normalize(glm::cross(right, front));
- m_ViewMatrix = glm::lookAt(m_Position, m_Position + front, up);
- m_ViewProjectionMatrix = m_ProjectionMatrix * m_ViewMatrix;
+ m_ViewMatrix = glm::lookAt(m_Position, m_Position + front, up);
+ m_ViewProjectionMatrix = m_ProjectionMatrix * m_ViewMatrix;
+ }
+ else if (m_CameraMode == CameraMode::Orbital)
+ {
+ glm::vec3 position = GetOrbitalPosition();
+ glm::vec3 worldUp(0.0f, 1.0f, 0.0f);
+ m_ViewMatrix = glm::lookAt(position, m_Target, worldUp);
+ m_ViewProjectionMatrix = m_ProjectionMatrix * m_ViewMatrix;
+ }
}
glm::vec3 Camera::GetForwardDirection() const
@@ -72,58 +82,153 @@ namespace Donut
void Camera::OnMouseMove(float xOffset, float yOffset, bool constrainPitch)
{
- xOffset *= m_MouseSensitivity;
- yOffset *= m_MouseSensitivity;
+ if (m_CameraMode == CameraMode::FPS)
+ {
+ xOffset *= m_MouseSensitivity;
+ yOffset *= m_MouseSensitivity;
- m_Rotation.y += xOffset;
- m_Rotation.x += yOffset;
+ m_Rotation.y += xOffset;
+ m_Rotation.x += yOffset;
- if (constrainPitch)
- {
- if (m_Rotation.x > 89.0f)
- m_Rotation.x = 89.0f;
- if (m_Rotation.x < -89.0f)
- m_Rotation.x = -89.0f;
- }
+ if (constrainPitch)
+ {
+ if (m_Rotation.x > 89.0f)
+ m_Rotation.x = 89.0f;
+ if (m_Rotation.x < -89.0f)
+ m_Rotation.x = -89.0f;
+ }
- RecalculateViewMatrix();
+ RecalculateViewMatrix();
+ }
}
void Camera::MoveForward(float deltaTime)
{
- m_Position += GetForwardDirection() * m_MovementSpeed * deltaTime;
- RecalculateViewMatrix();
+ if (m_CameraMode == CameraMode::FPS)
+ {
+ m_Position += GetForwardDirection() * m_MovementSpeed * deltaTime;
+ RecalculateViewMatrix();
+ }
}
void Camera::MoveBackward(float deltaTime)
{
- m_Position -= GetForwardDirection() * m_MovementSpeed * deltaTime;
- RecalculateViewMatrix();
+ if (m_CameraMode == CameraMode::FPS)
+ {
+ m_Position -= GetForwardDirection() * m_MovementSpeed * deltaTime;
+ RecalculateViewMatrix();
+ }
}
void Camera::MoveRight(float deltaTime)
{
- m_Position += GetRightDirection() * m_MovementSpeed * deltaTime;
- RecalculateViewMatrix();
+ if (m_CameraMode == CameraMode::FPS)
+ {
+ m_Position += GetRightDirection() * m_MovementSpeed * deltaTime;
+ RecalculateViewMatrix();
+ }
}
void Camera::MoveLeft(float deltaTime)
{
- m_Position -= GetRightDirection() * m_MovementSpeed * deltaTime;
- RecalculateViewMatrix();
+ if (m_CameraMode == CameraMode::FPS)
+ {
+ m_Position -= GetRightDirection() * m_MovementSpeed * deltaTime;
+ RecalculateViewMatrix();
+ }
}
void Camera::MoveUp(float deltaTime)
{
- glm::vec3 worldUp(0.0f, 1.0f, 0.0f);
- m_Position += worldUp * m_MovementSpeed * deltaTime;
- RecalculateViewMatrix();
+ if (m_CameraMode == CameraMode::FPS)
+ {
+ glm::vec3 worldUp(0.0f, 1.0f, 0.0f);
+ m_Position += worldUp * m_MovementSpeed * deltaTime;
+ RecalculateViewMatrix();
+ }
}
void Camera::MoveDown(float deltaTime)
{
- glm::vec3 worldUp(0.0f, 1.0f, 0.0f);
- m_Position -= worldUp * m_MovementSpeed * deltaTime;
+ if (m_CameraMode == CameraMode::FPS)
+ {
+ glm::vec3 worldUp(0.0f, 1.0f, 0.0f);
+ m_Position -= worldUp * m_MovementSpeed * deltaTime;
+ RecalculateViewMatrix();
+ }
+ }
+
+ // Orbital Camera Methods
+ void Camera::SetOrbitalMode(bool enabled)
+ {
+ m_CameraMode = enabled ? CameraMode::Orbital : CameraMode::FPS;
+ RecalculateViewMatrix();
+ }
+
+ glm::vec3 Camera::GetOrbitalPosition() const
+ {
+ float clampedElevation = glm::clamp(m_Elevation, 0.01f, float(M_PI) - 0.01f);
+ return glm::vec3(
+ m_Radius * sin(clampedElevation) * cos(m_Azimuth),
+ m_Radius * cos(clampedElevation),
+ m_Radius * sin(clampedElevation) * sin(m_Azimuth)
+ );
+ }
+
+ void Camera::ProcessOrbitalMouseMove(double x, double y)
+ {
+ if (m_Dragging && !m_Panning)
+ {
+ float dx = float(x - m_OrbitalLastX);
+ float dy = float(y - m_OrbitalLastY);
+
+ m_Azimuth += dx * m_OrbitSpeed;
+ m_Elevation -= dy * m_OrbitSpeed;
+ m_Elevation = glm::clamp(m_Elevation, 0.01f, float(M_PI) - 0.01f);
+ }
+
+ m_OrbitalLastX = x;
+ m_OrbitalLastY = y;
+ UpdateOrbitalState();
RecalculateViewMatrix();
}
+
+ void Camera::ProcessOrbitalMouseButton(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;
+ }
+ }
+ UpdateOrbitalState();
+ }
+
+ void Camera::ProcessOrbitalScroll(double xoffset, double yoffset)
+ {
+ m_Radius -= yoffset * m_ZoomSpeed;
+ m_Radius = glm::clamp(m_Radius, m_MinRadius, m_MaxRadius);
+ UpdateOrbitalState();
+ RecalculateViewMatrix();
+ }
+
+ void Camera::UpdateOrbitalState()
+ {
+ m_Target = glm::vec3(0.0f, 0.0f, 0.0f);
+ if (m_Dragging || m_Panning)
+ {
+ m_Moving = true;
+ }
+ else
+ {
+ m_Moving = false;
+ }
+ }
}
diff --git a/src/Core/Camera.h b/src/Core/Camera.h
index e3569b8..7fe3bd9 100644
--- a/src/Core/Camera.h
+++ b/src/Core/Camera.h
@@ -2,9 +2,21 @@
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
+#include <GLFW/glfw3.h>
+
+#define _USE_MATH_DEFINES
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
namespace Donut
{
+ enum class CameraMode
+ {
+ FPS,
+ Orbital
+ };
+
class Camera
{
public:
@@ -12,6 +24,7 @@ namespace Donut
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(); }
@@ -42,10 +55,57 @@ namespace Donut
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;
@@ -63,5 +123,20 @@ namespace Donut
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<float>(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;
};
}