From 5a10a883fbd763ddc78c4bf4c6eeba8ff88e18a0 Mon Sep 17 00:00:00 2001 From: elipzer Date: Sat, 8 Sep 2018 00:06:10 -0400 Subject: [PATCH] Camera Class Currently implemented a 2D camera class that creates an orthographic projection matrix. TODO is implementing a 3D camera class and test program. --- OpenGLEngine/Application.cpp | 82 ++++--- OpenGLEngine/Application.h | 13 +- OpenGLEngine/Camera.h | 18 ++ OpenGLEngine/Camera2D.cpp | 59 +++++ OpenGLEngine/Camera2D.h | 36 +++ OpenGLEngine/GLFWInputManager.cpp | 20 +- OpenGLEngine/InputManager.cpp | 18 +- OpenGLEngine/InputManager.h | 14 +- OpenGLEngine/MyApplication.cpp | 5 + OpenGLEngine/MyApplication.h | 2 + OpenGLEngine/MyBatch.h | 5 + OpenGLEngine/MyBatchTestVertexShader.glsl | 8 +- OpenGLEngine/MyObjectOrientedScene.cpp | 80 +++++-- OpenGLEngine/MyObjectOrientedScene.h | 5 +- OpenGLEngine/MySimpleScene.cpp | 3 +- OpenGLEngine/MySimpleScene.h | 2 +- OpenGLEngine/OpenGLEngine.vcxproj | 5 + OpenGLEngine/OpenGLEngine.vcxproj.filters | 259 +++++++++++++--------- OpenGLEngine/Scene.h | 10 + OpenGLEngine/constants.h | 10 + OpenGLEngine/main.cpp | 2 +- OpenGLEngine/mat4x4.h | 93 ++++---- OpenGLEngine/operations.h | 98 ++++++++ OpenGLEngine/vec2.h | 2 - OpenGLEngine/vec3.h | 2 - OpenGLEngine/vec4.h | 22 +- 26 files changed, 590 insertions(+), 283 deletions(-) create mode 100644 OpenGLEngine/Camera.h create mode 100644 OpenGLEngine/Camera2D.cpp create mode 100644 OpenGLEngine/Camera2D.h create mode 100644 OpenGLEngine/constants.h create mode 100644 OpenGLEngine/operations.h diff --git a/OpenGLEngine/Application.cpp b/OpenGLEngine/Application.cpp index a67094f..6a947f7 100644 --- a/OpenGLEngine/Application.cpp +++ b/OpenGLEngine/Application.cpp @@ -2,9 +2,46 @@ #include "Exception.h" -Application::Application() +Application::Application(int width, int height) + : m_screen_size(width, height) { - base_init(); + if (width < 0 || height < 0) + throw EXCEPTION("Invalid screen dimensions"); + + if (!glfwInit()) + throw EXCEPTION("Unable to Initialize GLFW"); + + m_p_window = glfwCreateWindow(width, height, "OpenGLEngine", NULL, NULL); + if (!m_p_window) + { + glfwTerminate(); + throw EXCEPTION("Unable to Create GLFW Window"); + } + + glfwSwapInterval(1); + + glfwMakeContextCurrent(m_p_window); + + glewExperimental = GL_TRUE; + GLenum glew_err = glewInit(); + if (glew_err != GLEW_OK) + { + glfwTerminate(); + throw EXCEPTION("Unable to Initialize GLEW: " + std::string((char*)glewGetErrorString(glew_err))); + } + + // Output Version Information + OutputDebugString("\nOpenGL Version Information:\nRenderer: "); + OutputDebugString((char*)glGetString(GL_RENDERER)); + OutputDebugString("\nOpenGL Version: "); + OutputDebugString((char*)glGetString(GL_VERSION)); + OutputDebugString("\n\n"); + + // TODO: Mouse Movement, Mouse Scroll + m_glfw_input_manager.init(m_p_window); + glfwSetKeyCallback(m_p_window, &GLFWInputManager::key_callback); + + m_fps.prepare(); } @@ -40,47 +77,6 @@ int Application::run() glfwTerminate(); throw e; } - -} - -void Application::close() -{ -} - -void Application::base_init() -{ - if (!glfwInit()) - { - throw EXCEPTION("Unable to Initialize GLFW"); - } - m_p_window = glfwCreateWindow(1280, 720, "OpenGLEngine", NULL, NULL); - if (!m_p_window) - { - glfwTerminate(); - throw EXCEPTION("Unable to Create GLFW Window"); - } - - glfwMakeContextCurrent(m_p_window); - - glewExperimental = GL_TRUE; - GLenum glew_err = glewInit(); - if (glew_err != GLEW_OK) - { - glfwTerminate(); - throw EXCEPTION("Unable to Initialize GLEW: " + std::string((char*)glewGetErrorString(glew_err))); - } - - // Output Version Information - OutputDebugString("\nOpenGL Version Information:\nRenderer: "); - OutputDebugString((char*)glGetString(GL_RENDERER)); - OutputDebugString("\nOpenGL Version: "); - OutputDebugString((char*)glGetString(GL_VERSION)); - OutputDebugString("\n\n"); - - m_glfw_input_manager.init(m_p_window); - glfwSetKeyCallback(m_p_window, &GLFWInputManager::key_callback); - - m_fps.prepare(); } void Application::base_close() diff --git a/OpenGLEngine/Application.h b/OpenGLEngine/Application.h index 72e2001..e1df6d8 100644 --- a/OpenGLEngine/Application.h +++ b/OpenGLEngine/Application.h @@ -14,11 +14,17 @@ using namespace egm; class Application { public: - Application(); + Application(int width = -1, int height = -1); virtual ~Application(); int run(); + const ivec2& get_screen_size() const { return m_screen_size; } + + const GLFWInputManager& get_input_manager() const { return m_glfw_input_manager; } + + const FPS& get_fps() const { return m_fps; } + protected: // Called on initialization of the application (called by base_init) virtual void init() = 0; @@ -28,15 +34,16 @@ protected: virtual void render() = 0; // Called on closing of the application (called before base_close) - virtual void close(); + virtual void close() {} GLFWwindow* m_p_window; + const ivec2 m_screen_size; + GLFWInputManager m_glfw_input_manager; FPS m_fps; private: - void base_init(); void base_close(); }; diff --git a/OpenGLEngine/Camera.h b/OpenGLEngine/Camera.h new file mode 100644 index 0000000..61e8662 --- /dev/null +++ b/OpenGLEngine/Camera.h @@ -0,0 +1,18 @@ +#pragma once + +#include "mat4x4.h" + +using namespace egm; + +class Camera +{ +public: + // Should update m_view_projection_matrix with the current + // view projection matrix. + virtual void update_view_projection_matrix() = 0; + + const mat4x4& get_view_projection_matrix() const { return m_view_projection_matrix; } + +protected: + mat4x4 m_view_projection_matrix; +}; \ No newline at end of file diff --git a/OpenGLEngine/Camera2D.cpp b/OpenGLEngine/Camera2D.cpp new file mode 100644 index 0000000..72a108c --- /dev/null +++ b/OpenGLEngine/Camera2D.cpp @@ -0,0 +1,59 @@ +#include "Camera2D.h" + +#include "operations.h" + +Camera2D::Camera2D(const vec2& size, const vec2& position) + : Camera2D(vec3(size.x, size.y, 2.0f), vec3(position.x, position.y, 0.0f)) {} + +Camera2D::Camera2D(const vec3& size, const vec3& position) +{ + update_size(size); + update_position(position); +} + +void Camera2D::update_size(const vec3& size) +{ + m_size = size; + update_scale(); +} + +void Camera2D::update_position(const vec3& position) +{ + m_position = position; + update_offset(); +} + +void Camera2D::translate(const vec2& position) +{ + translate(vec3(position.x, position.y, 0.0f)); +} + +void Camera2D::translate(const vec3& position) +{ + m_position += position; + update_offset(); +} + +void Camera2D::update_view_projection_matrix() +{ + m_view_projection_matrix.a.x = m_scale.x; + m_view_projection_matrix.b.y = m_scale.y; + m_view_projection_matrix.c.z = m_scale.z; + m_view_projection_matrix.a.w = m_offset.x; + m_view_projection_matrix.b.w = m_offset.y; + m_view_projection_matrix.c.w = m_offset.z; +} + +void Camera2D::update_scale() +{ + m_scale.x = 2.0f / m_size.x; + m_scale.y = 2.0f / m_size.y; + m_scale.z = -2.0f / m_size.z; +} + +void Camera2D::update_offset() +{ + m_offset.x = -m_position.x; + m_offset.y = -m_position.y; + m_offset.z = -m_position.z; +} \ No newline at end of file diff --git a/OpenGLEngine/Camera2D.h b/OpenGLEngine/Camera2D.h new file mode 100644 index 0000000..5f5ec6d --- /dev/null +++ b/OpenGLEngine/Camera2D.h @@ -0,0 +1,36 @@ +#pragma once + +#include "Camera.h" + +#include "vec2.h" +#include "vec3.h" + +using namespace egm; + +class Camera2D : public Camera +{ +public: + Camera2D(const vec2& size, const vec2& position = vec2(0.0f, 0.0f)); + Camera2D(const vec3& size = vec3(2.0f, 2.0f, 2.0f), const vec3& position = vec3(0.0f, 0.0f, 0.0f)); + + void update_size(const vec3& size); + void update_position(const vec3& position); + + void translate(const vec2& translation); + void translate(const vec3& translation); + + const vec3& get_size() { return m_size; } + const vec3& get_position() { return m_position; } + + void update_view_projection_matrix() override; + +private: + void update_scale(); + void update_offset(); + + vec3 m_size; + vec3 m_position; + + vec3 m_scale; + vec3 m_offset; +}; diff --git a/OpenGLEngine/GLFWInputManager.cpp b/OpenGLEngine/GLFWInputManager.cpp index 2e41394..a2e7fb4 100644 --- a/OpenGLEngine/GLFWInputManager.cpp +++ b/OpenGLEngine/GLFWInputManager.cpp @@ -12,9 +12,7 @@ GLFWInputManager::~GLFWInputManager() void GLFWInputManager::init(GLFWwindow* p_window) { if (m_p_window != nullptr) - { throw EXCEPTION("GLFWInputManager Already Initialized."); - } m_p_window = p_window; s_glfw_windows.insert(std::map::value_type(m_p_window, this)); } @@ -22,27 +20,15 @@ void GLFWInputManager::init(GLFWwindow* p_window) void GLFWInputManager::key_callback(GLFWwindow* p_window, int key, int scancode, int action, int mods) { std::map::iterator iter = s_glfw_windows.find(p_window); - if (iter == s_glfw_windows.end()) - { - // Ignore Unknown Windows - return; - } + if (iter == s_glfw_windows.end()) + return; // Ignore Unknown Windows GLFWInputManager& input_manager = *iter->second; if (action == GLFW_PRESS) - { input_manager.key_down(key); - } else if (action == GLFW_RELEASE) - { input_manager.key_up(key); - } - else if (action == GLFW_REPEAT) - { - // Ignored - } + else if (action == GLFW_REPEAT) { /* Ignored */} else - { throw Exception("Invalid GLFW Key Action: " + std::to_string(action) + " (" + std::to_string(scancode) + ")", "class GLFWInputManager"); - } } diff --git a/OpenGLEngine/InputManager.cpp b/OpenGLEngine/InputManager.cpp index 1e394cb..3e44fc0 100644 --- a/OpenGLEngine/InputManager.cpp +++ b/OpenGLEngine/InputManager.cpp @@ -38,12 +38,16 @@ void InputManager::mouse_scroll(int distance) m_scroll_distance += distance; } -bool InputManager::is_key_down(KeyCode key_code) +bool InputManager::is_key_down(KeyCode key_code) const { - return m_keys_down[key_code]; + auto iter = m_keys_down.find(key_code); + if (iter == m_keys_down.end()) + return false; + else + return iter->second; } -bool InputManager::is_key_pressed(KeyCode key_code) +bool InputManager::is_key_pressed(KeyCode key_code) const { auto iter = m_keys_pressed.find(key_code); if (iter == m_keys_pressed.end()) @@ -52,7 +56,7 @@ bool InputManager::is_key_pressed(KeyCode key_code) return iter->second; } -bool InputManager::is_key_released(KeyCode key_code) +bool InputManager::is_key_released(KeyCode key_code) const { auto iter = m_keys_pressed.find(key_code); if (iter == m_keys_pressed.end()) @@ -61,17 +65,17 @@ bool InputManager::is_key_released(KeyCode key_code) return !iter->second; } -const ivec2& InputManager::get_mouse_position() +const ivec2& InputManager::get_mouse_position() const { return m_mouse_position; } -const ivec2& InputManager::get_mouse_delta() +const ivec2& InputManager::get_mouse_delta() const { return m_mouse_delta; } -const int& InputManager::get_scroll_distance() +const int& InputManager::get_scroll_distance() const { return m_scroll_distance; } \ No newline at end of file diff --git a/OpenGLEngine/InputManager.h b/OpenGLEngine/InputManager.h index 3bd5b5a..3fb5f90 100644 --- a/OpenGLEngine/InputManager.h +++ b/OpenGLEngine/InputManager.h @@ -57,12 +57,12 @@ public: //Should be called after each frame to reset the keysPressed void mark(); - bool is_key_down(KeyCode key_code); - bool is_key_pressed(KeyCode key_code); - bool is_key_released(KeyCode key_code); - const ivec2& get_mouse_position(); - const ivec2& get_mouse_delta(); - const int& get_scroll_distance(); + bool is_key_down(KeyCode key_code) const; + bool is_key_pressed(KeyCode key_code) const; + bool is_key_released(KeyCode key_code) const; + const ivec2& get_mouse_position() const; + const ivec2& get_mouse_delta() const; + const int& get_scroll_distance() const; protected: void key_down(KeyCode key_code); @@ -86,7 +86,7 @@ private: //Change in mouse position since last mark() call ivec2 m_mouse_delta; - //The change in scroll (mouse wheel) sinc ethe last mark() call + //The change in scroll (mouse wheel) since the last mark() call int m_scroll_distance; //TODO: Controller Movement diff --git a/OpenGLEngine/MyApplication.cpp b/OpenGLEngine/MyApplication.cpp index 43d5715..e6691eb 100644 --- a/OpenGLEngine/MyApplication.cpp +++ b/OpenGLEngine/MyApplication.cpp @@ -1,5 +1,10 @@ #include "MyApplication.h" +MyApplication::MyApplication(int width, int height) + : Application(width, height), m_simple_scene(*this), m_object_oriented_scene(*this) +{ +} + void MyApplication::init() { m_simple_scene.init(); diff --git a/OpenGLEngine/MyApplication.h b/OpenGLEngine/MyApplication.h index 2b584cc..40f5794 100644 --- a/OpenGLEngine/MyApplication.h +++ b/OpenGLEngine/MyApplication.h @@ -8,6 +8,8 @@ class MyApplication : public Application { public: + MyApplication(int width = -1, int height = -1); + void init() override; void update(float delta_time, clock_t clock) override; diff --git a/OpenGLEngine/MyBatch.h b/OpenGLEngine/MyBatch.h index 3805823..1f17d4b 100644 --- a/OpenGLEngine/MyBatch.h +++ b/OpenGLEngine/MyBatch.h @@ -7,6 +7,11 @@ class MyBatch : public Batch { public: + MyBatch( + const MyBatchTestShaderProgram::Renderable* renderable, + const SizeType& element_count + ) : MyBatch(renderable, element_count, element_count) {} + MyBatch( const MyBatchTestShaderProgram::Renderable* renderable, const SizeType& element_count, diff --git a/OpenGLEngine/MyBatchTestVertexShader.glsl b/OpenGLEngine/MyBatchTestVertexShader.glsl index 70cbedb..09864e2 100644 --- a/OpenGLEngine/MyBatchTestVertexShader.glsl +++ b/OpenGLEngine/MyBatchTestVertexShader.glsl @@ -1,10 +1,14 @@ -#version 400 +#version 430 layout(location = 0) in vec3 vertex_position; layout(location = 1) in vec4 vertex_color; +layout(location = 2) in vec3 vertex_offset; + +// TODO: Try this with location 0 +layout(location = 3) uniform mat4 vp; out vec4 vert_color; void main() { - gl_Position = vec4(vertex_position, 1.0); + gl_Position = vp * vec4(vertex_position + vertex_offset, 1.0); vert_color = vertex_color; } \ No newline at end of file diff --git a/OpenGLEngine/MyObjectOrientedScene.cpp b/OpenGLEngine/MyObjectOrientedScene.cpp index 63799b0..e05fdad 100644 --- a/OpenGLEngine/MyObjectOrientedScene.cpp +++ b/OpenGLEngine/MyObjectOrientedScene.cpp @@ -1,16 +1,24 @@ #include "MyObjectOrientedScene.h" +#include + +#include "constants.h" + #include "DrawMode.h" #include "MeshFactory.h" -MyObjectOrientedScene::MyObjectOrientedScene() - : m_shape(MeshFactory::gen( +MyObjectOrientedScene::MyObjectOrientedScene(Application& application) + : Scene(application), + m_shape(MeshFactory::gen( DrawMode::DRAW_TRIANGLES, - MyBatchTestShaderProgram::Vertex(-0.1f, 0.1f, 0.0f), - MyBatchTestShaderProgram::Vertex(0.1f, 0.1f, 0.0f), - MyBatchTestShaderProgram::Vertex(-0.15f, -0.1f, 0.0f), - MyBatchTestShaderProgram::Vertex(0.15f, -0.1f, 0.0f) - ), DrawMode::DRAW_TRIANGLES), m_batch(&m_shape, 1, 1) + MyBatchTestShaderProgram::Vertex(-50.0f, 50.0f, 0.0f), + MyBatchTestShaderProgram::Vertex(50.0f, 150.0f, 0.0f), + MyBatchTestShaderProgram::Vertex(-100.0f, -50.0f, 0.0f), + MyBatchTestShaderProgram::Vertex(100.0f, -50.0f, 0.0f) + ), + DrawMode::DRAW_TRIANGLES), + m_batch(&m_shape, 2), + m_camera(m_screen_size) { } @@ -36,25 +44,56 @@ void MyObjectOrientedScene::unuse() void MyObjectOrientedScene::update(float delta_time, clock_t clock) { - float n; + float brightness; + float radians; + clock_t c; - c = (clock / 10) % 512; - if (c < 256) - { - n = (float)c / 256; - } + const clock_t intervals = 512 * CLOCKS_PER_SEC / 100; + const clock_t half_interval = 256 * CLOCKS_PER_SEC / 100; + c = clock % intervals; + if (c < half_interval) + brightness = (float)c / half_interval; else + brightness = (float)(intervals - c) / half_interval; + + radians = (float)egm::TAU * c / intervals; + { - n = (float)(512 - c) / 256; + MyBatchTestShaderProgram::Color& color = m_batch.get_color(0); + color.r = brightness; + color.g = brightness; + color.b = brightness; + color.a = 1.0f; + + MyBatchTestShaderProgram::Offset& offset = m_batch.get_offset(0); + offset.x = 200 * (float)cos(radians); + offset.y = 0.0f; + offset.z = 0.0f; + } + + { + MyBatchTestShaderProgram::Color& color = m_batch.get_color(1); + color.r = 1.0f - brightness; + color.g = 1.0f - brightness; + color.b = 1.0f - brightness; + color.a = 1.0f; + + MyBatchTestShaderProgram::Offset& offset = m_batch.get_offset(1); + offset.x = 0.0f; + offset.y = 200 * (float)sin(radians); + offset.z = 0.0f; } - // TODO: Movement Test + vec2 camera_translation; - MyBatchTestShaderProgram::Color& color = m_batch.get_color(0); - color.r = n; - color.g = n; - color.b = n; - color.a = 1.0f; + if (m_input_manager.is_key_down(GLFW_KEY_W)) camera_translation.y += 1; + if (m_input_manager.is_key_down(GLFW_KEY_S)) camera_translation.y -= 1; + if (m_input_manager.is_key_down(GLFW_KEY_A)) camera_translation.x -= 1; + if (m_input_manager.is_key_down(GLFW_KEY_D)) camera_translation.x += 1; + + m_camera.translate(camera_translation * delta_time); + + m_camera.update_view_projection_matrix(); // TODO: Make a prerender function or move this to render m_batch.prerender(); @@ -64,5 +103,6 @@ void MyObjectOrientedScene::render() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_shader_program.use(); + glUniformMatrix4fv(3, 1, GL_TRUE, &m_camera.get_view_projection_matrix().a.x); m_batch.render(); } diff --git a/OpenGLEngine/MyObjectOrientedScene.h b/OpenGLEngine/MyObjectOrientedScene.h index e484c03..b3d7359 100644 --- a/OpenGLEngine/MyObjectOrientedScene.h +++ b/OpenGLEngine/MyObjectOrientedScene.h @@ -2,13 +2,15 @@ #include "Scene.h" +#include "Camera2D.h" + #include "MyBatch.h" #include "MyBatchTestShaderProgram.h" class MyObjectOrientedScene : public Scene { public: - MyObjectOrientedScene(); + MyObjectOrientedScene(Application& application); ~MyObjectOrientedScene(); void init() override; @@ -24,4 +26,5 @@ private: MyBatch m_batch; MyBatchTestShaderProgram::Renderable m_shape; MyBatchTestShaderProgram m_shader_program; + Camera2D m_camera; }; \ No newline at end of file diff --git a/OpenGLEngine/MySimpleScene.cpp b/OpenGLEngine/MySimpleScene.cpp index 0d03733..d64aefe 100644 --- a/OpenGLEngine/MySimpleScene.cpp +++ b/OpenGLEngine/MySimpleScene.cpp @@ -1,6 +1,7 @@ #include "MySimpleScene.h" -MySimpleScene::MySimpleScene() +MySimpleScene::MySimpleScene(Application& application) + : Scene(application) { } diff --git a/OpenGLEngine/MySimpleScene.h b/OpenGLEngine/MySimpleScene.h index 401a1ac..e613d2d 100644 --- a/OpenGLEngine/MySimpleScene.h +++ b/OpenGLEngine/MySimpleScene.h @@ -9,7 +9,7 @@ class MySimpleScene : public Scene { public: - MySimpleScene(); + MySimpleScene(Application& application); ~MySimpleScene(); void init() override; diff --git a/OpenGLEngine/OpenGLEngine.vcxproj b/OpenGLEngine/OpenGLEngine.vcxproj index 9be5622..3d0e911 100644 --- a/OpenGLEngine/OpenGLEngine.vcxproj +++ b/OpenGLEngine/OpenGLEngine.vcxproj @@ -150,6 +150,7 @@ + @@ -172,6 +173,9 @@ + + + @@ -186,6 +190,7 @@ + diff --git a/OpenGLEngine/OpenGLEngine.vcxproj.filters b/OpenGLEngine/OpenGLEngine.vcxproj.filters index a801be0..36cc363 100644 --- a/OpenGLEngine/OpenGLEngine.vcxproj.filters +++ b/OpenGLEngine/OpenGLEngine.vcxproj.filters @@ -13,164 +13,209 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - {3011da99-7ced-44b5-b379-754b5db0a1c3} - {6a527248-fa21-4720-8864-49088116987e} {6f8b9833-6eed-478e-a52d-38bdb2573b92} - + + {053be292-7a70-4d73-8b07-dcb85d3d6ace} + + + {c38724ea-6e5b-4561-bb97-74da2a031319} + + + {51327f54-6f84-477f-8db8-883b91ebc5c2} + + + {2d1806dc-3a5d-4237-b7e3-4fe6d6576dc2} + + + {e8ae51e5-5508-47c6-804c-6d13408b8d13} + + + {1bb31cb4-7b36-47b6-b9ee-3d5de57f8f0c} + + + {3f9911e0-108f-4258-99c4-3f56e80ac27e} + + + {fd515372-39af-44d2-af2c-634b28e91878} + + + {dab3e00b-75ef-4281-b922-5ca6576c2dee} + + + {3361920b-2846-44ef-a1d1-5f867859bbbf} + + {0c68fb1a-eaef-450c-ab9e-56bcfd75fdff} - + + {9b6de612-281e-42cd-99a8-1917e2ba77bf} + + {922d67ef-ebba-4810-b4c4-fab05be62c9a} - - {9b6de612-281e-42cd-99a8-1917e2ba77bf} + + {3011da99-7ced-44b5-b379-754b5db0a1c3} - - Source Files - - - Source Files - - - Source Files - - - Source Files\Example - Source Files\Example - - Source Files - - - Source Files - - - Source Files - - - Source Files\Example - - - Source Files - - - Source Files - - - Source Files\Example - - - Source Files - - Source Files\Example\Scenes + Source Files\Example\Application\Scenes - Source Files\Example\Scenes + Source Files\Example\Application\Scenes + + + Source Files\Engine + + + Source Files\Engine + + + Source Files\Engine + + + Source Files\Engine\Application + + + Source Files\Engine\Application + + + Source Files\Engine\Application + + + Source Files\Engine\Application + + + Source Files\Engine\Rendering + + + Source Files\Engine\Rendering + + + Source Files\Example\Rendering - Source Files\Example + Source Files\Example\Rendering + + + Source Files\Example\Rendering + + + Source Files\Example\Application + + + Source Files\Engine\Rendering - - Header Files - - Header Files\math + Header Files\Engine\math - Header Files\math + Header Files\Engine\math - Header Files\math + Header Files\Engine\math - Header Files\math - - - Header Files - - - Header Files\Example - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files\Example - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files\Example - - - Header Files + Header Files\Engine\math - Header Files\Example\Scenes + Header Files\Example\Application\Scenes - Header Files\Example\Scenes + Header Files\Example\Application\Scenes + + + Header Files\Engine\math + + + Header Files\Engine\math + + + Header Files\Engine - Header Files + Header Files\Engine + + + Header Files\Engine + + + Header Files\Engine + + + Header Files\Engine\Application + + + Header Files\Engine\Application + + + Header Files\Engine\Application + + + Header Files\Engine\Application + + + Header Files\Engine\Application + + + Header Files\Engine\Rendering - Header Files + Header Files\Engine\Rendering + + + Header Files\Engine\Rendering + + + Header Files\Engine\Rendering + + + Header Files\Engine\Rendering + + + Header Files\Engine\Rendering + + + Header Files\Engine\Rendering + + + Header Files\Example\Rendering - Header Files\Example + Header Files\Example\Rendering + + + Header Files\Example\Rendering + + + Header Files\Example\Application + + + Header Files\Engine\Rendering - Source Files\Example\Shader Code + Source Files\Example\Rendering\Shader Code - Source Files\Example\Shader Code + Source Files\Example\Rendering\Shader Code - Source Files\Example\Shader Code + Source Files\Example\Rendering\Shader Code - Source Files\Example\Shader Code + Source Files\Example\Rendering\Shader Code \ No newline at end of file diff --git a/OpenGLEngine/Scene.h b/OpenGLEngine/Scene.h index 97d6f88..8e605ad 100644 --- a/OpenGLEngine/Scene.h +++ b/OpenGLEngine/Scene.h @@ -4,9 +4,15 @@ #include +#include "Application.h" + class Scene { public: + Scene(Application& application) + : m_screen_size(application.get_screen_size()), + m_input_manager(application.get_input_manager()), + m_fps(application.get_fps()) {}; virtual ~Scene() { }; // Called when the scene is ready to be initialized @@ -25,5 +31,9 @@ public: // Called when the frame is being rendered virtual void render() = 0; +protected: + const ivec2& m_screen_size; + const GLFWInputManager& m_input_manager; + const FPS& m_fps; }; diff --git a/OpenGLEngine/constants.h b/OpenGLEngine/constants.h new file mode 100644 index 0000000..253301a --- /dev/null +++ b/OpenGLEngine/constants.h @@ -0,0 +1,10 @@ +#pragma once + +namespace egm +{ + // 3.141592653589793238462643383279502884197169399375105820974944... + const double PI = 3.14159265358979323846; + + // 6.283185307179586476925286766559005768394338798750211641949889... + const double TAU = 6.28318530717958647693; +} \ No newline at end of file diff --git a/OpenGLEngine/main.cpp b/OpenGLEngine/main.cpp index f4a7b79..1d46bb8 100644 --- a/OpenGLEngine/main.cpp +++ b/OpenGLEngine/main.cpp @@ -10,7 +10,7 @@ int main(int argc, char** argv) { try { - MyApplication my_app; + MyApplication my_app(1280, 720); return my_app.run(); } catch (Exception& e) diff --git a/OpenGLEngine/mat4x4.h b/OpenGLEngine/mat4x4.h index ed602ff..85788c3 100644 --- a/OpenGLEngine/mat4x4.h +++ b/OpenGLEngine/mat4x4.h @@ -1,7 +1,5 @@ #pragma once -#include - #include "vec4.h" namespace egm @@ -80,7 +78,7 @@ namespace egm b + o.b, c + o.c, d + o.d - } + }; } tmat4x4& operator+=(const tmat4x4& o) @@ -99,7 +97,7 @@ namespace egm b - o.b, c - o.c, d - o.d - } + }; } tmat4x4& operator-=(const tmat4x4& o) @@ -130,49 +128,50 @@ namespace egm m.a.z * a.x + m.b.z * a.y + m.c.z * a.z + m.d.z * a.w,//Column 3b m.a.w * a.x + m.b.w * a.y + m.c.w * a.z + m.d.w * a.w,//Column 4b - //Row 2a - m.a.x * b.x + m.b.x * b.y + m.c.x * b.z + m.d.x * b.w,//Column 1b - m.a.y * b.x + m.b.y * b.y + m.c.y * b.z + m.d.y * b.w,//Column 2b - m.a.z * b.x + m.b.z * b.y + m.c.z * b.z + m.d.z * b.w,//Column 3b - m.a.w * b.x + m.b.w * b.y + m.c.w * b.z + m.d.w * b.w,//Column 4b + //Row 2a + m.a.x * b.x + m.b.x * b.y + m.c.x * b.z + m.d.x * b.w,//Column 1b + m.a.y * b.x + m.b.y * b.y + m.c.y * b.z + m.d.y * b.w,//Column 2b + m.a.z * b.x + m.b.z * b.y + m.c.z * b.z + m.d.z * b.w,//Column 3b + m.a.w * b.x + m.b.w * b.y + m.c.w * b.z + m.d.w * b.w,//Column 4b - //Row 3a - m.a.x * c.x + m.b.x * c.y + m.c.x * c.z + m.d.x * c.w,//Column 1b - m.a.y * c.x + m.b.y * c.y + m.c.y * c.z + m.d.y * c.w,//Column 2b - m.a.z * c.x + m.b.z * c.y + m.c.z * c.z + m.d.z * c.w,//Column 3b - m.a.w * c.x + m.b.w * c.y + m.c.w * c.z + m.d.w * c.w,//Column 4b + //Row 3a + m.a.x * c.x + m.b.x * c.y + m.c.x * c.z + m.d.x * c.w,//Column 1b + m.a.y * c.x + m.b.y * c.y + m.c.y * c.z + m.d.y * c.w,//Column 2b + m.a.z * c.x + m.b.z * c.y + m.c.z * c.z + m.d.z * c.w,//Column 3b + m.a.w * c.x + m.b.w * c.y + m.c.w * c.z + m.d.w * c.w,//Column 4b - //Row 4a - m.a.x * d.x + m.b.x * d.y + m.c.x * d.z + m.d.x * d.w,//Column 1b - m.a.y * d.x + m.b.y * d.y + m.c.y * d.z + m.d.y * d.w,//Column 2b - m.a.z * d.x + m.b.z * d.y + m.c.z * d.z + m.d.z * d.w,//Column 3b - m.a.w * d.x + m.b.w * d.y + m.c.w * d.z + m.d.w * d.w,//Column 4b + //Row 4a + m.a.x * d.x + m.b.x * d.y + m.c.x * d.z + m.d.x * d.w,//Column 1b + m.a.y * d.x + m.b.y * d.y + m.c.y * d.z + m.d.y * d.w,//Column 2b + m.a.z * d.x + m.b.z * d.y + m.c.z * d.z + m.d.z * d.w,//Column 3b + m.a.w * d.x + m.b.w * d.y + m.c.w * d.z + m.d.w * d.w,//Column 4b }; - //Backwards + + // Backwards (multiply and transpose) /*return { - //Row 1b - a.x * m.a.x + b.x * m.a.y + c.x * m.a.z + d.x * m.a.w,//Column 1a - a.y * m.a.x + b.y * m.a.y + c.y * m.a.z + d.y * m.a.w,//Column 2a - a.z * m.a.x + b.z * m.a.y + c.z * m.a.z + d.z * m.a.w,//Column 3a - a.w * m.a.x + b.w * m.a.y + c.w * m.a.z + d.w * m.a.w,//Column 4a + //Row 1b + a.x * m.a.x + b.x * m.a.y + c.x * m.a.z + d.x * m.a.w,//Column 1a + a.y * m.a.x + b.y * m.a.y + c.y * m.a.z + d.y * m.a.w,//Column 2a + a.z * m.a.x + b.z * m.a.y + c.z * m.a.z + d.z * m.a.w,//Column 3a + a.w * m.a.x + b.w * m.a.y + c.w * m.a.z + d.w * m.a.w,//Column 4a - //Row 2b - a.x * m.b.x + b.x * m.b.y + c.x * m.b.z + d.x * m.b.w,//Column 1a - a.y * m.b.x + b.y * m.b.y + c.y * m.b.z + d.y * m.b.w,//Column 2a - a.z * m.b.x + b.z * m.b.y + c.z * m.b.z + d.z * m.b.w,//Column 3a - a.w * m.b.x + b.w * m.b.y + c.w * m.b.z + d.w * m.b.w,//Column 4a + //Row 2b + a.x * m.b.x + b.x * m.b.y + c.x * m.b.z + d.x * m.b.w,//Column 1a + a.y * m.b.x + b.y * m.b.y + c.y * m.b.z + d.y * m.b.w,//Column 2a + a.z * m.b.x + b.z * m.b.y + c.z * m.b.z + d.z * m.b.w,//Column 3a + a.w * m.b.x + b.w * m.b.y + c.w * m.b.z + d.w * m.b.w,//Column 4a - //Row 3b - a.x * m.c.x + b.x * m.c.y + c.x * m.c.z + d.x * m.c.w,//Column 1a - a.y * m.c.x + b.y * m.c.y + c.y * m.c.z + d.y * m.c.w,//Column 2a - a.z * m.c.x + b.z * m.c.y + c.z * m.c.z + d.z * m.c.w,//Column 3a - a.w * m.c.x + b.w * m.c.y + c.w * m.c.z + d.w * m.c.w,//Column 4a + //Row 3b + a.x * m.c.x + b.x * m.c.y + c.x * m.c.z + d.x * m.c.w,//Column 1a + a.y * m.c.x + b.y * m.c.y + c.y * m.c.z + d.y * m.c.w,//Column 2a + a.z * m.c.x + b.z * m.c.y + c.z * m.c.z + d.z * m.c.w,//Column 3a + a.w * m.c.x + b.w * m.c.y + c.w * m.c.z + d.w * m.c.w,//Column 4a - //Row 4b - a.x * m.d.x + b.x * m.d.y + c.x * m.d.z + d.x * m.d.w,//Column 1a - a.y * m.d.x + b.y * m.d.y + c.y * m.d.z + d.y * m.d.w,//Column 2a - a.z * m.d.x + b.z * m.d.y + c.z * m.d.z + d.z * m.d.w,//Column 3a - a.w * m.d.x + b.w * m.d.y + c.w * m.d.z + d.w * m.d.w,//Column 4a + //Row 4b + a.x * m.d.x + b.x * m.d.y + c.x * m.d.z + d.x * m.d.w,//Column 1a + a.y * m.d.x + b.y * m.d.y + c.y * m.d.z + d.y * m.d.w,//Column 2a + a.z * m.d.x + b.z * m.d.y + c.z * m.d.z + d.z * m.d.w,//Column 3a + a.w * m.d.x + b.w * m.d.y + c.w * m.d.z + d.w * m.d.w,//Column 4a };*/ } @@ -188,7 +187,7 @@ namespace egm b * scalar, c * scalar, d * scalar - } + }; } tmat4x4& operator*=(const T& scalar) @@ -207,7 +206,7 @@ namespace egm b / scalar, c / scalar, d / scalar - } + }; } tmat4x4& operator/=(const T& scalar) @@ -219,16 +218,6 @@ namespace egm return *this; } - operator RECT() - { - return { - a, - b, - c, - d - } - } - float* data() { return &(a.x); diff --git a/OpenGLEngine/operations.h b/OpenGLEngine/operations.h new file mode 100644 index 0000000..5bae810 --- /dev/null +++ b/OpenGLEngine/operations.h @@ -0,0 +1,98 @@ +#pragma once + +#include "mat4x4.h" + +namespace egm +{ + // Multiplies a matrix into out + template + void multiply(const tmat4x4& a, const tmat4x4& b, tmat4x4& out) + { + out.a.x = a.a.x * b.a.x + a.a.y * b.b.x + a.a.z * b.c.x + a.a.w * b.d.x; + out.a.y = a.a.x * b.a.y + a.a.y * b.b.y + a.a.z * b.c.y + a.a.w * b.d.y; + out.a.z = a.a.x * b.a.z + a.a.y * b.b.z + a.a.z * b.c.z + a.a.w * b.d.z; + out.a.w = a.a.x * b.a.w + a.a.y * b.b.w + a.a.z * b.c.w + a.a.w * b.d.w; + + out.b.x = a.b.x * b.a.x + a.b.y * b.b.x + a.b.z * b.c.x + a.b.w * b.d.x; + out.b.y = a.b.x * b.a.y + a.b.y * b.b.y + a.b.z * b.c.y + a.b.w * b.d.y; + out.b.z = a.b.x * b.a.z + a.b.y * b.b.z + a.b.z * b.c.z + a.b.w * b.d.z; + out.b.w = a.b.x * b.a.w + a.b.y * b.b.w + a.b.z * b.c.w + a.b.w * b.d.w; + + out.c.x = a.c.x * b.a.x + a.c.y * b.b.x + a.c.z * b.c.x + a.c.w * b.d.x; + out.c.y = a.c.x * b.a.y + a.c.y * b.b.y + a.c.z * b.c.y + a.c.w * b.d.y; + out.c.z = a.c.x * b.a.z + a.c.y * b.b.z + a.c.z * b.c.z + a.c.w * b.d.z; + out.c.w = a.c.x * b.a.w + a.c.y * b.b.w + a.c.z * b.c.w + a.c.w * b.d.w; + + out.d.x = a.d.x * b.a.x + a.d.y * b.b.x + a.d.z * b.c.x + a.d.w * b.d.x; + out.d.y = a.d.x * b.a.y + a.d.y * b.b.y + a.d.z * b.c.y + a.d.w * b.d.y; + out.d.w = a.d.x * b.a.z + a.d.y * b.b.z + a.d.z * b.c.z + a.d.w * b.d.z; + out.d.w = a.d.x * b.a.w + a.d.y * b.b.w + a.d.z * b.c.w + a.d.w * b.d.w; + } + + // Multiplies and transposes a matrix into out. + template + void multiply_and_transpose(const tmat4x4& a, const tmat4x4& b, tmat4x4& out) + { + out.a.x = a.a.x * b.a.x + a.b.x * b.a.y + a.c.x * b.a.z + a.d.x * b.a.w; + out.a.y = a.a.y * b.a.x + a.b.y * b.a.y + a.c.y * b.a.z + a.d.y * b.a.w; + out.a.z = a.a.z * b.a.x + a.b.z * b.a.y + a.c.z * b.a.z + a.d.z * b.a.w; + out.a.w = a.a.w * b.a.x + a.b.w * b.a.y + a.c.w * b.a.z + a.d.w * b.a.w; + + out.b.x = a.a.x * b.b.x + a.b.x * b.b.y + a.c.x * b.b.z + a.d.x * b.b.w; + out.b.y = a.a.y * b.b.x + a.b.y * b.b.y + a.c.y * b.b.z + a.d.y * b.b.w; + out.b.z = a.a.z * b.b.x + a.b.z * b.b.y + a.c.z * b.b.z + a.d.z * b.b.w; + out.b.w = a.a.w * b.b.x + a.b.w * b.b.y + a.c.w * b.b.z + a.d.w * b.b.w; + + out.c.x = a.a.x * b.c.x + a.b.x * b.c.y + a.c.x * b.c.z + a.d.x * b.c.w; + out.c.y = a.a.y * b.c.x + a.b.y * b.c.y + a.c.y * b.c.z + a.d.y * b.c.w; + out.c.z = a.a.z * b.c.x + a.b.z * b.c.y + a.c.z * b.c.z + a.d.z * b.c.w; + out.c.w = a.a.w * b.c.x + a.b.w * b.c.y + a.c.w * b.c.z + a.d.w * b.c.w; + + out.d.x = a.a.x * b.d.x + a.b.x * b.d.y + a.c.x * b.d.z + a.d.x * b.d.w; + out.d.y = a.a.y * b.d.x + a.b.y * b.d.y + a.c.y * b.d.z + a.d.y * b.d.w; + out.d.w = a.a.z * b.d.x + a.b.z * b.d.y + a.c.z * b.d.z + a.d.z * b.d.w; + out.d.w = a.a.w * b.d.x + a.b.w * b.d.y + a.c.w * b.d.z + a.d.w * b.d.w; + } + + // Creates an orthoganal matrix + template + void ortho(const T& left, const T& right, const T& bottom, const T& top, const T& near, const T& far, tmat4x4& out) + { + out = tmat4x4(); + out.a.x = T(2) / (right - left); + out.b.y = T(2) / (top - bottom); + out.c.z = -T(2) / (far - near); + out.a.w = -(right + left) / (right - left); + out.b.w = -(top + bottom) / (top - bottom); + out.c.w = -(far + near) / (far - near); + } + + // Creates an orthogonal matrix centered at the origin + template + void ortho(const T& width, const T& height, const T& depth, tmat4x4& out) + { + out = tmat4x4(); + out.a.x = T(2) / width; + out.a.y = T(2) / height; + out.a.z = T(2) / depth; + } + + template + void translation(const T& x, const T& y, const T& z, tmat4x4& out) + { + out = tmat4x4(); + out.a.w = x; + out.b.w = y; + out.c.w = z; + } + + template + void apply_translation(const T& x, const T& y, const T& z, tmat4x4& out) + { + out.a.w = x; + out.b.w = y; + out.c.w = z; + } + + // TODO: Transpose function +} \ No newline at end of file diff --git a/OpenGLEngine/vec2.h b/OpenGLEngine/vec2.h index 69007cb..9b8c98d 100644 --- a/OpenGLEngine/vec2.h +++ b/OpenGLEngine/vec2.h @@ -1,7 +1,5 @@ #pragma once -#include - namespace egm { diff --git a/OpenGLEngine/vec3.h b/OpenGLEngine/vec3.h index cc67639..d87e0a5 100644 --- a/OpenGLEngine/vec3.h +++ b/OpenGLEngine/vec3.h @@ -1,7 +1,5 @@ #pragma once -#include - namespace egm { diff --git a/OpenGLEngine/vec4.h b/OpenGLEngine/vec4.h index 2071681..82ad84e 100644 --- a/OpenGLEngine/vec4.h +++ b/OpenGLEngine/vec4.h @@ -1,7 +1,5 @@ #pragma once -#include - #include "vec2.h" namespace egm @@ -61,7 +59,7 @@ namespace egm y + o.y, z + o.z, w + o.w - } + }; } tvec4& operator+=(const tvec4& o) @@ -80,7 +78,7 @@ namespace egm y - o.y, z - o.z, w - o.w - } + }; } tvec4& operator-=(const tvec4& o) @@ -99,7 +97,7 @@ namespace egm y * o.y, z * o.z, w * o.w - } + }; } tvec4& operator*=(const tvec4& o) @@ -118,7 +116,7 @@ namespace egm y * scalar, z * scalar, w * scalar - } + }; } tvec4& operator*=(const T& scalar) @@ -137,7 +135,7 @@ namespace egm y / o.y, z / o.z, w / o.w - } + }; } tvec4& operator/=(const tvec4& o) @@ -168,16 +166,6 @@ namespace egm return *this; } - operator RECT() - { - return { - x, - y, - z, - w - } - } - float* data() { return &x;