diff --git a/src/Engine/Engine.vcxproj b/src/Engine/Engine.vcxproj index c62a1fd..d6d4c6e 100644 --- a/src/Engine/Engine.vcxproj +++ b/src/Engine/Engine.vcxproj @@ -138,6 +138,7 @@ + @@ -151,6 +152,7 @@ + diff --git a/src/Engine/Engine.vcxproj.filters b/src/Engine/Engine.vcxproj.filters index aa346ca..4e69393 100644 --- a/src/Engine/Engine.vcxproj.filters +++ b/src/Engine/Engine.vcxproj.filters @@ -27,6 +27,9 @@ Source Files + + Source Files + @@ -56,6 +59,9 @@ Header Files + + Header Files + diff --git a/src/Engine/main.cpp b/src/Engine/main.cpp index 10be1eb..09ef7c6 100644 --- a/src/Engine/main.cpp +++ b/src/Engine/main.cpp @@ -10,9 +10,10 @@ #include "shaders/Shader.h" #include "textures/Texture2D.h" #include "util/stb_image.h" +#include "util/camera/camera.h" -// Continue: https://learnopengl.com/Getting-started/Camera -// Chapter: Camera class +// Continue: https://learnopengl.com/Lighting/Colors +// Chapter: Not yet started // // TODO: look at project->properties->VC++ Directories-> change everything to the Environment var // For the "real" Nebulix Engine setup everything so it can be compiled/used with VSCode/CLion and not just VS @@ -33,12 +34,9 @@ typedef glm::mat4 mat4; typedef glm::vec3 vec3; vec3 cameraPosition = vec3(0.0f, 0.0f, 3.0f); -vec3 cameraFront = vec3(0.0f, 0.0f, -1.0f); -vec3 cameraUp = vec3(0.0f, 1.0f, 0.0f); +Camera cam(cameraPosition); -float deltaTime = 0.0f; -float lastFrameTime = 0.0f; -float pitch = 0.0f, yaw = -90.0f, fov = 45.0f; +float deltaTime = 0.0f, lastFrameTime = 0.0f; float mouseLastX = WINDOW_WIDTH / 2, mouseLastY = WINDOW_HEIGHT / 2; bool firstMouseMove = true; @@ -50,24 +48,17 @@ void OnWindowResize(GLFWwindow* window, int width, int height) void ProcessInput(GLFWwindow* window) { - const float cameraSpeed = 3.0f * deltaTime; - if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); - if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) - cameraPosition += cameraSpeed * cameraFront; - if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) - cameraPosition -= cameraSpeed * cameraFront; - if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) - cameraPosition -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed; - if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) - cameraPosition += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed; - - if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) - cameraFront -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed * 0.25f; - if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) - cameraFront += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed * 0.25f; + if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) + cam.ProcessKeyboard(MovementDirection::FORWARD, deltaTime); + if(glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) + cam.ProcessKeyboard(MovementDirection::BACKWARD, deltaTime); + if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) + cam.ProcessKeyboard(MovementDirection::LEFT, deltaTime); + if(glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) + cam.ProcessKeyboard(MovementDirection::RIGHT, deltaTime); } void OnMouseMove(GLFWwindow* window, double xpos, double ypos) @@ -85,32 +76,12 @@ void OnMouseMove(GLFWwindow* window, double xpos, double ypos) mouseLastX = xpos; mouseLastY = ypos; - const float sensitivity = 0.1f; - xoffset *= sensitivity; - yoffset *= sensitivity; - - yaw += xoffset; - pitch += yoffset; - - if (pitch > 89.0f) - pitch = 89.0f; - if (pitch < -89.0f) - pitch = -89.0f; - - glm::vec3 direction; - direction.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch)); - direction.y = sin(glm::radians(pitch)); - direction.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch)); - cameraFront = glm::normalize(direction); + cam.ProcessMouseMovement(xoffset, yoffset, true); } void OnScroll(GLFWwindow* window, double xoffset, double yoffset) { - fov -= (float)yoffset; - if (fov < 1.0f) - fov = 1.0f; - if (fov > 90.0f) - fov = 90.0f; + cam.ProcessMouseScroll(yoffset); } void Configure(GLFWwindow *window) @@ -152,6 +123,7 @@ int main() Configure(window); + float vertices[] = { // object coordinates, uv-coordinates -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, @@ -268,8 +240,8 @@ int main() ProcessInput(window); - mat4 viewMatrix = glm::lookAt(cameraPosition, cameraPosition + cameraFront, cameraUp); - mat4 projectionMatrix = glm::perspective(glm::radians(fov), 800.0f / 600.0f, 0.1f, 100.0f); + mat4 viewMatrix = cam.GetViewMatrix(); + mat4 projectionMatrix = glm::perspective(glm::radians(cam.Fov), 800.0f / 600.0f, 0.1f, 100.0f); shader->Use(); shader->SetInt("ourTexture1", 0); diff --git a/src/Engine/util/camera/camera.cpp b/src/Engine/util/camera/camera.cpp new file mode 100644 index 0000000..729cfb7 --- /dev/null +++ b/src/Engine/util/camera/camera.cpp @@ -0,0 +1 @@ +#include "camera.h" diff --git a/src/Engine/util/camera/camera.h b/src/Engine/util/camera/camera.h new file mode 100644 index 0000000..d9c5109 --- /dev/null +++ b/src/Engine/util/camera/camera.h @@ -0,0 +1,111 @@ +#pragma once +#include +#include +#include + +#include "../property.h" + +enum class MovementDirection +{ + FORWARD, + BACKWARD, + LEFT, + RIGHT +}; + +// Default values +const float YAW = -90.0f; +const float PITCH = 0.0f; +const float SPEED = 2.5f; +const float SENSITIVITY = 0.1f; +const float FOV = 45.0f; + +class Camera +{ +public: + glm::vec3 Position; + glm::vec3 Front; + glm::vec3 Up; + glm::vec3 Right; + glm::vec3 WorldUp; + + float Yaw; + float Pitch; + + float MovementSpeed; + float MouseSensitivity; + float Fov; // or zoom + + Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Fov(FOV) + { + Position = position; + WorldUp = up; + Yaw = yaw; + Pitch = pitch; + UpdateCameraVectors(); + } + + glm::mat4 GetViewMatrix() { return glm::lookAt(Position, Position + Front, Up); } + + // processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems) + void ProcessKeyboard(MovementDirection direction, float deltaTime) + { + float velocity = MovementSpeed * deltaTime; + if (direction == MovementDirection::FORWARD) + Position += Front * velocity; + if (direction == MovementDirection::BACKWARD) + Position -= Front * velocity; + if (direction == MovementDirection::LEFT) + Position -= Right * velocity; + if (direction == MovementDirection::RIGHT) + Position += Right * velocity; + } + + // processes input received from a mouse input system. Expects the offset value in both the x and y direction. + void ProcessMouseMovement(float xoffset, float yoffset, GLboolean constrainPitch = true) + { + xoffset *= MouseSensitivity; + yoffset *= MouseSensitivity; + + Yaw += xoffset; + Pitch += yoffset; + + // make sure that when pitch is out of bounds, screen doesn't get flipped + if (constrainPitch) + { + if (Pitch > 89.0f) + Pitch = 89.0f; + if (Pitch < -89.0f) + Pitch = -89.0f; + } + + // update Front, Right and Up Vectors using the updated Euler angles + UpdateCameraVectors(); + } + + // processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis + void ProcessMouseScroll(float yoffset) + { + Fov -= (float)yoffset; + if (Fov < 1.0f) + Fov = 1.0f; + if (Fov > 90.0f) + Fov = 90.0f; + } + +private: + // calculates the front vector from the Camera's (updated) Euler Angles + void UpdateCameraVectors() + { + glm::vec3 front; + front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch)); + front.y = sin(glm::radians(Pitch)); + front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch)); + Front = glm::normalize(front); + + // also re-calculate the Right and Up vector + Right = glm::normalize(glm::cross(Front, WorldUp)); // normalize the vectors, because their length gets closer to 0 the more you look up or down which results in slower movement. + Up = glm::normalize(glm::cross(Right, Front)); + } +}; + diff --git a/src/Engine/util/property.h b/src/Engine/util/property.h index 30f864c..8f23bd6 100644 --- a/src/Engine/util/property.h +++ b/src/Engine/util/property.h @@ -7,8 +7,25 @@ public: Property(const T &data): data{data}{} T operator()() { return data; } - void operator()(const T &d) { data = d; } + void operator()(const T& d) { data = d; } + Property operator=(const T& d) { data = d; } + operator T() const { return data; } // to easily pass a property to a function which takes a var of type T for example: void func(float f) => func(property) + private: T data; void operator=(const Property& p); // so this property can not be overwritten, since this might lead to a memory leak. Maybe this operator can be used to assign only the data (C#-like)? }; + +template +class ReadOnlyProperty +{ +public: + ReadOnlyProperty(const T &data): data{data}{} + + T operator()() { return data; } + operator T() const { return data; } // to easily pass a property to a function which takes a var of type T for example: void func(float f) => func(property) + +private: + T data; + void operator=(const ReadOnlyProperty& p); // so this property can not be overwritten, since this might lead to a memory leak. Maybe this operator can be used to assign only the data (C#-like)? +};