aboutsummaryrefslogtreecommitdiff
path: root/src/Core
diff options
context:
space:
mode:
Diffstat (limited to 'src/Core')
-rw-r--r--src/Core/Application.cpp149
-rw-r--r--src/Core/Application.h12
-rw-r--r--src/Core/Camera.cpp132
-rw-r--r--src/Core/Camera.h69
-rw-r--r--src/Core/Window.cpp19
-rw-r--r--src/Core/Window.h17
6 files changed, 378 insertions, 20 deletions
diff --git a/src/Core/Application.cpp b/src/Core/Application.cpp
index 98d1de7..1af049a 100644
--- a/src/Core/Application.cpp
+++ b/src/Core/Application.cpp
@@ -9,6 +9,7 @@
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
+#include <GLFW/glfw3.h>
namespace Donut
{
@@ -70,14 +71,78 @@ namespace Donut
else
m_Minimized = false;
+ if (m_Camera)
+ m_Camera->SetProjection(45.0f, (float)e.GetWidth() / (float)e.GetHeight(), 0.1f, 100.0f);
+
+ event.Handled = true;
+ return true;
+ });
+
+ dispatcher.Dispatch<WindowFocusEvent>([this, &event](WindowFocusEvent& e)
+ {
+ m_FirstMouse = true;
+ m_MouseDragging = false;
+ event.Handled = true;
+ return true;
+ });
+
+ dispatcher.Dispatch<WindowLostFocusEvent>([this, &event](WindowLostFocusEvent& e)
+ {
+ m_MouseDragging = false;
event.Handled = true;
return true;
});
dispatcher.Dispatch<KeyPressedEvent>([this, &event](KeyPressedEvent& e)
{
- if (e.GetKeyCode() == 256)
- Close();
+ m_Keys[e.GetKeyCode()] = true;
+ return true;
+ });
+
+ dispatcher.Dispatch<KeyReleasedEvent>([this, &event](KeyReleasedEvent& e)
+ {
+ m_Keys[e.GetKeyCode()] = false;
+ return true;
+ });
+
+ dispatcher.Dispatch<MouseMovedEvent>([this, &event](MouseMovedEvent& e)
+ {
+ if (!m_MouseDragging)
+ return true;
+
+ if (m_FirstMouse)
+ {
+ m_LastX = e.GetX();
+ m_LastY = e.GetY();
+ m_FirstMouse = false;
+ }
+
+ float xOffset = m_LastX - e.GetX();
+ float yOffset = e.GetY() - m_LastY;
+
+ m_LastX = e.GetX();
+ m_LastY = e.GetY();
+
+ if (m_Camera)
+ m_Camera->OnMouseMove(xOffset, yOffset);
+
+ return true;
+ });
+
+ dispatcher.Dispatch<MouseButtonPressedEvent>([this, &event](MouseButtonPressedEvent& e)
+ {
+ if (e.GetMouseButton() == GLFW_MOUSE_BUTTON_LEFT)
+ {
+ m_MouseDragging = true;
+ m_FirstMouse = true;
+ }
+ return true;
+ });
+
+ dispatcher.Dispatch<MouseButtonReleasedEvent>([this, &event](MouseButtonReleasedEvent& e)
+ {
+ if (e.GetMouseButton() == GLFW_MOUSE_BUTTON_LEFT)
+ m_MouseDragging = false;
return true;
});
}
@@ -86,14 +151,32 @@ namespace Donut
{
Renderer::Init();
- float vertices[3 * 7] =
+ m_Camera = std::make_unique<Camera>(45.0f, 1280.0f / 720.0f, 0.1f, 100.0f);
+ m_Camera->SetPosition({ 0.0f, 0.0f, 3.0f });
+ m_Camera->SetMouseSensitivity(0.1f);
+ m_Camera->SetMovementSpeed(5.0f);
+
+ float vertices[] =
{
- -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
- 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
- 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f
+ -0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f,
+ 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f,
+ 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f,
+ -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f,
+ -0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f,
+ 0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 1.0f,
+ 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 1.0f,
+ -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f
};
- uint32_t indices[3] = { 0, 1, 2 };
+ uint32_t indices[] =
+ {
+ 0, 1, 2, 2, 3, 0,
+ 1, 5, 6, 6, 2, 1,
+ 5, 4, 7, 7, 6, 5,
+ 4, 0, 3, 3, 7, 4,
+ 3, 2, 6, 6, 7, 3,
+ 4, 5, 1, 1, 0, 4
+ };
m_VertexArray = std::shared_ptr<VertexArray>(VertexArray::Create());
m_VertexBuffer = std::shared_ptr<VertexBuffer>(VertexBuffer::Create(vertices, sizeof(vertices)));
@@ -105,7 +188,7 @@ namespace Donut
m_VertexArray->AddVertexBuffer(m_VertexBuffer);
- m_IndexBuffer = std::shared_ptr<IndexBuffer>(IndexBuffer::Create(indices, 3));
+ m_IndexBuffer = std::shared_ptr<IndexBuffer>(IndexBuffer::Create(indices, 36));
m_VertexArray->SetIndexBuffer(m_IndexBuffer);
m_Shader = std::shared_ptr<Shader>(Shader::Create("assets/Basic.glsl"));
@@ -118,19 +201,55 @@ namespace Donut
void Application::OnUpdate()
{
+ float currentFrame = (float)glfwGetTime();
+ m_DeltaTime = currentFrame - m_LastFrame;
+ m_LastFrame = currentFrame;
+
+ if (m_Camera)
+ {
+ if (m_Keys[GLFW_KEY_W])
+ m_Camera->MoveForward(m_DeltaTime);
+ if (m_Keys[GLFW_KEY_S])
+ m_Camera->MoveBackward(m_DeltaTime);
+ if (m_Keys[GLFW_KEY_A])
+ m_Camera->MoveLeft(m_DeltaTime);
+ if (m_Keys[GLFW_KEY_D])
+ m_Camera->MoveRight(m_DeltaTime);
+ if (m_Keys[GLFW_KEY_SPACE])
+ m_Camera->MoveUp(m_DeltaTime);
+ if (m_Keys[GLFW_KEY_LEFT_SHIFT])
+ m_Camera->MoveDown(m_DeltaTime);
+ }
}
void Application::OnRender()
{
- Renderer::SetClearColor({ 0.1f, 0.1f, 0.1f, 1.0f });
+ Renderer::SetClearColor({ 0.0f, 0.0f, 0.0f, 1.0f });
Renderer::Clear();
- Renderer::BeginScene();
-
- glm::mat4 viewProjection = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
+ glm::mat4 viewProjection = m_Camera ? m_Camera->GetViewProjectionMatrix() : glm::mat4(1.0f);
- Renderer::Submit(m_Shader, m_VertexArray, glm::mat4(1.0f));
-
- Renderer::EndScene();
+ glm::vec3 centerPos(0.0f, 0.0f, 0.0f);
+ glm::vec3 rightPos(2.0f, 0.0f, 0.0f);
+ glm::vec3 leftPos(-2.0f, 0.0f, 0.0f);
+ glm::vec3 upPos(0.0f, 2.0f, 0.0f);
+ glm::vec3 downPos(0.0f, -2.0f, 0.0f);
+ glm::vec3 forwardPos(0.0f, 0.0f, 2.0f);
+ glm::vec3 backPos(0.0f, 0.0f, -2.0f);
+
+ glm::mat4 transform = glm::translate(glm::mat4(1.0f), centerPos);
+ Renderer::Submit(m_Shader, m_VertexArray, transform, viewProjection);
+ transform = glm::translate(glm::mat4(1.0f), rightPos);
+ Renderer::Submit(m_Shader, m_VertexArray, transform, viewProjection);
+ transform = glm::translate(glm::mat4(1.0f), leftPos);
+ Renderer::Submit(m_Shader, m_VertexArray, transform, viewProjection);
+ transform = glm::translate(glm::mat4(1.0f), upPos);
+ Renderer::Submit(m_Shader, m_VertexArray, transform, viewProjection);
+ transform = glm::translate(glm::mat4(1.0f), downPos);
+ Renderer::Submit(m_Shader, m_VertexArray, transform, viewProjection);
+ transform = glm::translate(glm::mat4(1.0f), forwardPos);
+ Renderer::Submit(m_Shader, m_VertexArray, transform, viewProjection);
+ transform = glm::translate(glm::mat4(1.0f), backPos);
+ Renderer::Submit(m_Shader, m_VertexArray, transform, viewProjection);
}
}
diff --git a/src/Core/Application.h b/src/Core/Application.h
index b8c9d49..9e5d31d 100644
--- a/src/Core/Application.h
+++ b/src/Core/Application.h
@@ -2,6 +2,7 @@
#include "Window.h"
#include "Event.h"
+#include "Camera.h"
#include <memory>
#include <functional>
@@ -42,6 +43,17 @@ namespace Donut
std::shared_ptr<VertexBuffer> m_VertexBuffer;
std::shared_ptr<IndexBuffer> m_IndexBuffer;
std::shared_ptr<Shader> m_Shader;
+
+ std::unique_ptr<Camera> m_Camera;
+
+ // Input state
+ bool m_Keys[1024] = { false };
+ bool m_FirstMouse = true;
+ float m_LastX = 0.0f;
+ float m_LastY = 0.0f;
+ float m_DeltaTime = 0.0f;
+ float m_LastFrame = 0.0f;
+ bool m_MouseDragging = false;
static Application* s_Instance;
};
diff --git a/src/Core/Camera.cpp b/src/Core/Camera.cpp
new file mode 100644
index 0000000..ea363b0
--- /dev/null
+++ b/src/Core/Camera.cpp
@@ -0,0 +1,132 @@
+#include "Camera.h"
+#include <glm/gtc/quaternion.hpp>
+
+namespace Donut
+{
+ Camera::Camera(float fov, float aspectRatio, float nearPlane, float farPlane)
+ : m_FOV(fov), m_AspectRatio(aspectRatio), m_NearPlane(nearPlane), m_FarPlane(farPlane)
+ {
+ RecalculateProjectionMatrix();
+ RecalculateViewMatrix();
+ }
+
+ void Camera::SetProjection(float fov, float aspectRatio, float nearPlane, float farPlane)
+ {
+ m_FOV = fov;
+ m_AspectRatio = aspectRatio;
+ m_NearPlane = nearPlane;
+ m_FarPlane = farPlane;
+ RecalculateProjectionMatrix();
+ }
+
+ void Camera::RecalculateProjectionMatrix()
+ {
+ m_ProjectionMatrix = glm::perspective(glm::radians(m_FOV), m_AspectRatio, m_NearPlane, m_FarPlane);
+ m_ViewProjectionMatrix = m_ProjectionMatrix * m_ViewMatrix;
+ }
+
+ void Camera::RecalculateViewMatrix()
+ {
+ 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 front = glm::normalize(direction);
+ glm::vec3 worldUp(0.0f, 1.0f, 0.0f);
+ 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;
+ }
+
+ glm::vec3 Camera::GetForwardDirection() const
+ {
+ float pitch = glm::radians(m_Rotation.x);
+ float yaw = glm::radians(m_Rotation.y);
+
+ glm::vec3 direction;
+ direction.x = cos(yaw) * cos(pitch);
+ direction.y = sin(pitch);
+ direction.z = sin(yaw) * cos(pitch);
+
+ return glm::normalize(direction);
+ }
+
+ glm::vec3 Camera::GetRightDirection() const
+ {
+ glm::vec3 worldUp(0.0f, 1.0f, 0.0f);
+ return glm::normalize(glm::cross(GetForwardDirection(), worldUp));
+ }
+
+ glm::vec3 Camera::GetUpDirection() const
+ {
+ return glm::normalize(glm::cross(GetRightDirection(), GetForwardDirection()));
+ }
+
+ void Camera::OnUpdate(float deltaTime)
+ {
+ }
+
+ void Camera::OnMouseMove(float xOffset, float yOffset, bool constrainPitch)
+ {
+ xOffset *= m_MouseSensitivity;
+ yOffset *= m_MouseSensitivity;
+
+ 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;
+ }
+
+ RecalculateViewMatrix();
+ }
+
+ void Camera::MoveForward(float deltaTime)
+ {
+ m_Position += GetForwardDirection() * m_MovementSpeed * deltaTime;
+ RecalculateViewMatrix();
+ }
+
+ void Camera::MoveBackward(float deltaTime)
+ {
+ m_Position -= GetForwardDirection() * m_MovementSpeed * deltaTime;
+ RecalculateViewMatrix();
+ }
+
+ void Camera::MoveRight(float deltaTime)
+ {
+ m_Position += GetRightDirection() * m_MovementSpeed * deltaTime;
+ RecalculateViewMatrix();
+ }
+
+ void Camera::MoveLeft(float deltaTime)
+ {
+ 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();
+ }
+
+ void Camera::MoveDown(float deltaTime)
+ {
+ glm::vec3 worldUp(0.0f, 1.0f, 0.0f);
+ m_Position -= worldUp * m_MovementSpeed * deltaTime;
+ RecalculateViewMatrix();
+ }
+}
diff --git a/src/Core/Camera.h b/src/Core/Camera.h
new file mode 100644
index 0000000..b2037b7
--- /dev/null
+++ b/src/Core/Camera.h
@@ -0,0 +1,69 @@
+#pragma once
+
+#include <glm/glm.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+
+namespace Donut
+{
+ class Camera
+ {
+ public:
+ Camera(float fov = 45.0f, float aspectRatio = 16.0f / 9.0f,
+ float nearPlane = 0.1f, float farPlane = 100.0f);
+ ~Camera() = default;
+
+ 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 OnUpdate(float deltaTime);
+ 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; }
+
+ private:
+ void RecalculateViewMatrix();
+ void RecalculateProjectionMatrix();
+ private:
+ 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;
+ };
+}
diff --git a/src/Core/Window.cpp b/src/Core/Window.cpp
index 440aeb1..ff451fd 100644
--- a/src/Core/Window.cpp
+++ b/src/Core/Window.cpp
@@ -44,7 +44,6 @@ namespace Donut
glfwMakeContextCurrent(m_Window);
- // Initialize GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD!" << std::endl;
@@ -91,6 +90,24 @@ namespace Donut
return glfwWindowShouldClose(m_Window) || m_IsClosed;
}
+ void Window::SetCursorLocked(bool locked)
+ {
+ m_CursorLocked = locked;
+ if (locked)
+ glfwSetInputMode(m_Window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+ else
+ glfwSetInputMode(m_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
+ }
+
+ void Window::SetCursorVisible(bool visible)
+ {
+ m_CursorVisible = visible;
+ if (visible)
+ glfwSetInputMode(m_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
+ else
+ glfwSetInputMode(m_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
+ }
+
void Window::GLFWErrorCallback(int error, const char* description)
{
std::cout << "GLFW Error (" << error << "): " << description << std::endl;
diff --git a/src/Core/Window.h b/src/Core/Window.h
index f954ed6..c1cda2d 100644
--- a/src/Core/Window.h
+++ b/src/Core/Window.h
@@ -15,16 +15,24 @@ namespace Donut
~Window();
bool ShouldClose() const;
- void OnUpdate() const;
+ void OnUpdate() const;
+
+ void SetEventCallback(const EventCallbackFn& callback)
+ {
+ m_EventHandler.SetEventCallback(callback);
+ }
- void SetEventCallback(const EventCallbackFn& callback) { m_EventHandler.SetEventCallback(callback); }
EventHandler& GetEventHandler() { return m_EventHandler; }
- unsigned int GetWidth() const { return m_Width; }
+ unsigned int GetWidth() const { return m_Width; }
unsigned int GetHeight() const { return m_Height; }
void* GetNativeWindow() const { return m_Window; }
+ void SetCursorLocked(bool locked);
+ void SetCursorVisible(bool visible);
+ bool IsCursorLocked() const { return m_CursorLocked; }
+ bool IsCursorVisible() const { return m_CursorVisible; }
private:
void Init();
void Shutdown();
@@ -39,7 +47,6 @@ namespace Donut
static void GLFWMouseButtonCallback(GLFWwindow* window, int button, int action, int mods);
static void GLFWMouseScrollCallback(GLFWwindow* window, double xOffset, double yOffset);
static void GLFWCursorPosCallback(GLFWwindow* window, double xPos, double yPos);
-
private:
GLFWwindow* m_Window;
EventHandler m_EventHandler;
@@ -48,5 +55,7 @@ namespace Donut
unsigned int m_Width;
unsigned int m_Height;
bool m_IsClosed;
+ bool m_CursorLocked = false;
+ bool m_CursorVisible = true;
};
} \ No newline at end of file