From 2c6b8eaa4cf7cbec712d71974a964c2b6de5e583 Mon Sep 17 00:00:00 2001 From: Joeyrp Date: Fri, 3 Sep 2021 18:07:04 -0400 Subject: [PATCH] OglGraphics mostly implemented but needs testing Fonts and text rendering not yet implemented --- CMakeLists.txt | 4 + scripts/build.bat | 4 +- src/core/core.cpp | 4 +- src/graphics/DefaultShaders.h | 96 ++++ src/graphics/IGraphics.h | 78 ++++ src/graphics/Image.cpp | 48 ++ src/graphics/Image.h | 43 ++ src/graphics/OGLGraphics.cpp | 426 ++++++++++++++++++ src/graphics/OGLGraphics.h | 96 ++++ src/graphics/Shaders/DefaultImage.frag | 11 + src/graphics/Shaders/DefaultImage.vert | 13 + src/graphics/glShader.cpp | 322 +++++++++++++ src/graphics/glShader.h | 77 ++++ src/graphics/window.cpp | 12 +- src/graphics/window.h | 1 + src/test_main.cpp | 9 +- src/utils/Logger.cpp | 13 +- src/utils/Logger.h | 3 +- src/utils/types.cpp | 73 +++ src/utils/types.h | 58 ++- .../{test_state.xml => lunarium_state.xml} | 0 21 files changed, 1375 insertions(+), 16 deletions(-) create mode 100644 src/graphics/DefaultShaders.h create mode 100644 src/graphics/IGraphics.h create mode 100644 src/graphics/Image.cpp create mode 100644 src/graphics/Image.h create mode 100644 src/graphics/OGLGraphics.cpp create mode 100644 src/graphics/OGLGraphics.h create mode 100644 src/graphics/Shaders/DefaultImage.frag create mode 100644 src/graphics/Shaders/DefaultImage.vert create mode 100644 src/graphics/glShader.cpp create mode 100644 src/graphics/glShader.h create mode 100644 src/utils/types.cpp rename test_data/{test_state.xml => lunarium_state.xml} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b78d26..94ca967 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ set(LUNARIUM_SRC "src/core/core.cpp" "src/core/state.cpp" "src/core/Version.cpp" +"src/utils/types.cpp" "src/utils/Logger.cpp" "src/utils/HighResTimer.cpp" "src/utils/helpers.cpp" @@ -26,6 +27,9 @@ set(LUNARIUM_SRC "src/utils/Args.cpp" "src/utils/BinaryFileBuffer.cpp" "src/graphics/window.cpp" +"src/graphics/oglgraphics.cpp" +"src/graphics/glShader.cpp" +"src/graphics/image.cpp" ) # add the executable diff --git a/scripts/build.bat b/scripts/build.bat index f9f6074..169a182 100644 --- a/scripts/build.bat +++ b/scripts/build.bat @@ -10,10 +10,10 @@ IF not exist build/ ( IF "%~1" == "r" ( cmake --build build/ --target ALL_BUILD --config Release -xcopy /y test_data build\Release\test_data\ +xcopy /y test_data\lunarium_state.xml build\Release\ ) ELSE ( cmake --build build/ --target ALL_BUILD --config Debug -xcopy /y test_data build\Debug\test_data\ +xcopy /y test_data\lunarium_state.xml build\Debug\ ) :END \ No newline at end of file diff --git a/src/core/core.cpp b/src/core/core.cpp index 580fee9..bf8e5cc 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -66,13 +66,13 @@ namespace lunarium mpLog->AddListener(listeners[i]); } - mpLog->Log(LogCategory::CORE, LogLevel::INFO, "Running Lunarium version %s", Version::GetVersion().ToString().c_str()); + Logger::Log(LogCategory::CORE, LogLevel::INFO, "Running Lunarium version %s", Version::GetVersion().ToString().c_str()); // Attempt to load the engine state file. This file should be placed in the same directory as the lunarium program. mpLog->Log(LogCategory::CORE, LogLevel::INFO, "Attempting to load state file: lunarium_state.xml"); if (Failed(State::CreateFromFile("lunarium_state.xml", mState))) { - mpLog->Log(LogCategory::CORE, LogLevel::WARNING, "Unable to load state file: lunarium_state.xml. Loading default state."); + Logger::Log(LogCategory::CORE, LogLevel::WARNING, "Unable to load state file: lunarium_state.xml. Loading default state."); mState = State::CreateDefault(); } diff --git a/src/graphics/DefaultShaders.h b/src/graphics/DefaultShaders.h new file mode 100644 index 0000000..1f4b6a2 --- /dev/null +++ b/src/graphics/DefaultShaders.h @@ -0,0 +1,96 @@ +/****************************************************************************** +* File - DefaultShaders.h +* Author - Joey Pollack +* Date - 2018/01/12 (y/m/d) +* Mod Date - 2018/01/12 (y/m/d) +* Description - String definitions with default shader source code. +* +******************************************************************************/ + +#ifndef DEFAULT_SHADERS_H_ +#define DEFAULT_SHADERS_H_ + +namespace lunarium +{ + struct + { + friend class OglGraphics; + private: + const char* DefaultShapeVertex = "#version 330 core\n\ + layout(location = 0) in vec4 vertex;\ + \ + uniform mat4 model;\ + uniform mat4 projection;\ + \ + void main()\ + {\ + gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);\ + }"; + + const char* DefaultShapeFragment = "#version 330 core\n\ + in vec2 TexCoords;\ + out vec4 color;\ + \ + uniform vec4 shapeColor;\ + \ + void main()\ + {\ + color = shapeColor;\ + }"; + + const char* DefaultSpriteVertex = "#version 330 core\n\ + layout(location = 0) in vec4 vertex;\ + \ + out vec2 TexCoords;\ + \ + uniform vec4 uvManip;\ + uniform mat4 model;\ + uniform mat4 projection;\ + \ + void main()\ + {\ + TexCoords = vec2(vertex.z * uvManip.x + uvManip.y, vertex.w * uvManip.z + uvManip.w);\ + gl_Position = projection * model * vec4(vertex.xy, 0.0, 1.0);\ + }"; + + const char* DefaultSpriteFragment = "#version 330 core\n\ + in vec2 TexCoords;\ + out vec4 color;\ + \ + uniform sampler2D image;\ + uniform vec4 spriteColor;\ + \ + void main()\ + {\ + color = vec4(spriteColor) * texture(image, TexCoords);\ + }"; + + const char* DefaultTextVertex = "#version 330 core\n\ + layout(location = 0) in vec4 vertex; \ + out vec2 TexCoords;\ + \ + uniform mat4 projection;\ + \ + void main()\ + {\ + gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);\ + TexCoords = vertex.zw;\ + } "; + + const char* DefaultTextFragment = "#version 330 core\n\ + in vec2 TexCoords;\ + out vec4 color;\ + \ + uniform sampler2D text;\ + uniform vec4 textColor;\ + \ + void main()\ + {\ + vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);\ + color = vec4(textColor) * sampled;\ + }"; + + } OGLDefaultShaders; +} + +#endif // DEFAULT_SHADERS_H_ \ No newline at end of file diff --git a/src/graphics/IGraphics.h b/src/graphics/IGraphics.h new file mode 100644 index 0000000..4c1f9d2 --- /dev/null +++ b/src/graphics/IGraphics.h @@ -0,0 +1,78 @@ +/****************************************************************************** +* File - IGraphics.h +* Author - Joey Pollack +* Date - 2021/09/02 (y/m/d) +* Mod Date - 2021/09/02 (y/m/d) +* Description - Graphics interface for the engine. +* +******************************************************************************/ + +#ifndef IGRAPHICS_H_ +#define IGRAPHICS_H_ + +#include +#include + +namespace lunarium +{ + class Core; + class Window; + class Image; + + enum ImageFormat + { + RGB, + RGBA, + BGR, + BGRA + }; + + class IGraphics + { + protected: // Interface methods for use only by the engine + friend Core; + + IGraphics() : mbIsInit(false) {} + + virtual OpRes Initialized(Window* pWindow, bool enableDebugMessages = true) = 0; + virtual void Shutdown() = 0; + + virtual void ResizeCanvas() = 0; + + virtual void BeginDraw() = 0; + virtual void EndDraw() = 0; + + public: // + + virtual void SetClearColor(Color c) = 0; + virtual Color GetClearColor() const = 0; + + // Draw Methods + virtual void DrawLine(glm::vec2 point1, glm::vec2 point2, Color color, float lineWidth) = 0; + virtual void DrawEllipse(glm::vec2 center, glm::vec2 radii, Color color, float thickness, int resolution) = 0; + virtual void DrawFilledEllipse(glm::vec2 center, glm::vec2 radii, Color color, int resolution) = 0; + virtual void DrawBox(Rectangle dimensions, Color color, float thickness) = 0; + virtual void DrawFilledBox(glm::vec2 topLeft, glm::vec2 botRight, Color color) = 0; + virtual void DrawImage(Image& image, glm::vec2 topLeft, Color color) = 0; + virtual void DrawImage(Image& image, Rectangle source, Rectangle destination, Color color) = 0; + virtual void DrawString(const char* string, Rectangle boundingArea, Color color, int font = 0) = 0; + + // Takes raw image data and creates and Image class instance out of it. + // The raw data must be in one of the ImageFormats and it must be 1 byte per channel. + virtual Image* CreateImage(const unsigned char* pData, int width, int height, ImageFormat format) = 0; + + // Fonts + int DefaultFont() const; + + // For weight, 400 is normal and 700 is bold + virtual int CreateNewFont(const char* fontName, float size = 12.0f, int weight = 400) = 0; + + protected: + + bool mbIsInit; + int mDefaultFont; + Color mClearColor; + }; +} + +#endif // IGRAPHICS_H_ \ No newline at end of file diff --git a/src/graphics/Image.cpp b/src/graphics/Image.cpp new file mode 100644 index 0000000..baef763 --- /dev/null +++ b/src/graphics/Image.cpp @@ -0,0 +1,48 @@ +/****************************************************************************** +* File - Image.h +* Author - Joey Pollack +* Date - 2019/07/17 (y/m/d) +* Mod Date - 2019/07/18 (y/m/d) +* Description - Manage image data that can be rendered with OpenGL. +* Use the Graphics class to create instances of Image. +******************************************************************************/ + +#include "Image.h" + +namespace lunarium +{ + unsigned int Image::GetGLTextureID() const + { + return mGLTextureID; + } + + int Image::GetWidth() const + { + return mWidth; + } + + int Image::GetHeight() const + { + return mHeight; + } + + void Image::FreeRawData() + { + delete[] mRawData; + mRawData = nullptr; + + mRawDataSize = 0; + } + + Image::Image() + : mRawData(nullptr), mRawDataSize(0), mWidth(0), mHeight(0) + { + } + + Image::~Image() + { + delete[] mRawData; + mRawData = nullptr; + } + +} diff --git a/src/graphics/Image.h b/src/graphics/Image.h new file mode 100644 index 0000000..a9a0cc9 --- /dev/null +++ b/src/graphics/Image.h @@ -0,0 +1,43 @@ +/****************************************************************************** +* File - Image.h +* Author - Joey Pollack +* Date - 2019/07/17 (y/m/d) +* Mod Date - 2019/07/18 (y/m/d) +* Description - Manage image data that can be rendered with OpenGL. +* Use the Graphics class to create instances of Image. +******************************************************************************/ + +#ifndef IMAGE_H_ +#define IMAGE_H_ + + +namespace lunarium +{ + class OglGraphics; + class Image + { + friend OglGraphics; + + public: + + unsigned int GetGLTextureID() const; + int GetWidth() const; + int GetHeight() const; + + void FreeRawData(); + + private: + + Image(); + ~Image(); + + unsigned char* mRawData; + int mRawDataSize; + int mWidth; + int mHeight; + + unsigned int mGLTextureID; + }; +} + +#endif // IMAGE_H_ \ No newline at end of file diff --git a/src/graphics/OGLGraphics.cpp b/src/graphics/OGLGraphics.cpp new file mode 100644 index 0000000..a3feafd --- /dev/null +++ b/src/graphics/OGLGraphics.cpp @@ -0,0 +1,426 @@ +/****************************************************************************** +* File - OGLGraphics.cpp +* Author - Joey Pollack +* Date - 2021/08/30 (y/m/d) +* Mod Date - 2021/09/02 (y/m/d) +* Description - An openGL implementation of the engine Graphics interface. +******************************************************************************/ + +#include "OGLGraphics.h" +#include "DefaultShaders.h" +#include "window.h" +#include "image.h" +#include +#include +#include + +namespace lunarium +{ + //////////////////////////////////////////////////////////// + // DEBUG MESSAGE CALLBACK + //////////////////////////////////////////////////////////// + std::map OglGraphics::mDebugMsgTypes; + std::map OglGraphics::mDebugMsgSources; + std::map OglGraphics::mDebugMsgSeverity; + + void GLAPIENTRY MessageCallback(GLenum source, GLenum type, GLuint id, + GLenum severity, GLsizei length, const GLchar* message, const void* userParam) + { + + Logger::Log(LogCategory::GRAPHICS, LogLevel::OGL_DEBUG, + "%s (type: %s, source: %s, severity: %s), message: %s", + (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), + OglGraphics::mDebugMsgSources[source].c_str(), + OglGraphics::mDebugMsgTypes[type].c_str(), + OglGraphics::mDebugMsgSeverity[severity].c_str(), + message); + } + + //////////////////////////////////////////////////////////// + // RESTRICTED METHODS + //////////////////////////////////////////////////////////// + OglGraphics::OglGraphics() + { + + } + + OpRes OglGraphics::Initialized(Window* pWindow, bool enableDebugMessages) + { + if (!pWindow->IsInit()) + { + return OpRes::Fail("Can not initialize Graphics interface. The Window must be initialized first!"); + } + + if (mbIsInit) + { + return OpRes::Fail("Can not initialize Graphics interface. It is already initialized"); + } + + mpWindow = pWindow; + + if (enableDebugMessages) + { + InitDebugMsgSystem(); + } + + // Initialize the 2D drawing systems + InitImageSystem(); + // InitTextSystem(); + InitShapeSystem(); + + return OpRes::OK(); + } + + void OglGraphics::Shutdown() + { + // Nothing to clean up at this point + } + + + void OglGraphics::ResizeCanvas() + { + // Get viewport size from glfw window + int width = 0; + int height = 0; + glfwGetFramebufferSize(mpWindow->GetWindow(), &width, &height); + + glViewport(0, 0, width, height); + mProjection = glm::ortho(0.0f, (GLfloat)width, (GLfloat)height, 0.0f, -1.0f, 1.0f); + + Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO_VERBOSE, + "glViewport set to %d, %d", width, height); + } + + + void OglGraphics::BeginDraw() + { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + void OglGraphics::EndDraw() + { + mpWindow->SwapBuffers(); + } + //////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////// + // USER METHODS + //////////////////////////////////////////////////////////// + void OglGraphics::SetClearColor(Color c) + { + mClearColor = c; + glClearColor(mClearColor.Red, mClearColor.Green, mClearColor.Blue, mClearColor.Alpha); + } + + Color OglGraphics::GetClearColor() const + { + return mClearColor; + } + + // Draw Methods + void OglGraphics::DrawLine(glm::vec2 point1, glm::vec2 point2, Color color, float lineWidth) + { + mShapeShader.MakeActive(); + mShapeShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection)); + mShapeShader.SetUniformf("shapeColor", { color.Red, color.Green, color.Blue, color.Alpha }); + glBindVertexArray(mRectVAO); + + GLfloat lineVerts[6][4] = { + { point1.x, point1.y, }, + { point2.x, point2.y, }, + { 0.0f, 0.0f, }, + + { 0.0f, 0.0f, }, + { 0.0f, 0.0f, }, + { 0.0f, 0.0f, } + }; + glBindBuffer(GL_ARRAY_BUFFER, mRectVBO); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(lineVerts), lineVerts); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glLineWidth(lineWidth); + glDrawArrays(GL_LINES, 0, 2); + + glBindVertexArray(0); + } + + void OglGraphics::DrawEllipse(glm::vec2 center, glm::vec2 radii, Color color, float thickness, int resolution) + { + mShapeShader.MakeActive(); + mShapeShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection)); + mShapeShader.SetUniformf("shapeColor", { color.Red, color.Green, color.Blue, color.Alpha }); + glBindVertexArray(mEllipseVAO); + + GLfloat points[360][2]; + for (int i = 0; i < 360; i++) + { + float rad = i * 3.14159f / 180.0f; + points[i][0] = center.x + (radii.x * cos(rad)); + points[i][1] = center.y + (radii.y * sin(rad)); + } + + glBindBuffer(GL_ARRAY_BUFFER, mEllipseVBO); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glLineWidth(thickness); + glDrawArrays(GL_LINE_LOOP, 0, 360); + + glBindVertexArray(0); + } + + + void OglGraphics::DrawFilledEllipse(glm::vec2 center, glm::vec2 radii, Color color, int resolution) + { + mShapeShader.MakeActive(); + mShapeShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection)); + mShapeShader.SetUniformf("shapeColor", { color.Red, color.Green, color.Blue, color.Alpha }); + glBindVertexArray(mEllipseVAO); + + GLfloat points[362][2]; + points[0][0] = center.x; + points[0][1] = center.y; + for (int i = 1; i < 362; i++) + { + float rad = (i - 1) * 3.14159f / 180.0f; + points[i][0] = center.x + (radii.x * cos(rad)); + points[i][1] = center.y + (radii.y * sin(rad)); + } + + glBindBuffer(GL_ARRAY_BUFFER, mEllipseVBO); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 362); + + glBindVertexArray(0); + } + + void OglGraphics::DrawFilledBox(glm::vec2 topLeft, glm::vec2 botRight, Color color) + { + mShapeShader.MakeActive(); + mShapeShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection)); + mShapeShader.SetUniformf("shapeColor", { color.Red, color.Green, color.Blue, color.Alpha }); + glBindVertexArray(mRectVAO); + + GLfloat vertices[6][4] = { + { topLeft.x, botRight.y, }, + { botRight.x, topLeft.y, }, + { topLeft.x, topLeft.y, }, + + { topLeft.x, botRight.y, }, + { botRight.x, botRight.y, }, + { botRight.x, topLeft.y, } + }; + glBindBuffer(GL_ARRAY_BUFFER, mRectVBO); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); + glBindBuffer(GL_ARRAY_BUFFER, 0); + // Render quad + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + } + + void OglGraphics::DrawBox(Rectangle dimensions, Color color, float thickness) + { + glm::vec2 topLeft(dimensions.Left, dimensions.Top); + glm::vec2 botRight(dimensions.right(), dimensions.bottom()); + + // left side top to bottom + DrawLine(glm::vec2(topLeft.x, topLeft.y), glm::vec2(topLeft.x, botRight.y), color, thickness); + + // bottom left to right + DrawLine(glm::vec2(topLeft.x, botRight.y), glm::vec2(botRight.x, botRight.y), color, thickness); + + // right side bottom to top + DrawLine(glm::vec2(botRight.x, botRight.y), glm::vec2(botRight.x, topLeft.y), color, thickness); + + // top right to left + DrawLine(glm::vec2(botRight.x, topLeft.y), glm::vec2(topLeft.x, topLeft.y), color, thickness); + } + + void OglGraphics::DrawImage(Image& image, glm::vec2 topLeft, Color color) + { + DrawImage(image, Rectangle(0.0f, 0.0f, (float)image.GetWidth(), (float)image.GetHeight()), + Rectangle(topLeft.x, topLeft.y, (float)image.GetWidth(), (float)image.GetHeight()), color); + } + + void OglGraphics::DrawImage(Image& image, Rectangle source, Rectangle destination, Color color) + { + glm::mat4 id = glm::mat4(1.0f); + glm::vec3 pos = glm::vec3(destination.Left, destination.Top, 0.0f); + glm::mat4 trans = glm::translate(id, pos); + trans = glm::scale(trans, glm::vec3(destination.Width, destination.Height, 1.0f)); + + // float widthDiff = image.GetWidth() - source.Width; + + // if (source.Width == image.GetWidth() && source.Height == image.GetHeight()) + // { + // mImageShader.MakeActive(); + // mImageShader.SetUniformf("uvManip", { 1.0f, 0.0f, 1.0f, 0.0f }); // No uv Manipulation + // mImageShader.SetUniformMatrix("model", 1, glm::value_ptr(trans)); + // mImageShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection)); + // mImageShader.SetUniformf("spriteColor", { color.Red, color.Green, color.Blue, color.Alpha }); + // } + // else + // { + + // NOTE: Pretty sure these values will work out to be correct with out the if check + float xScale = source.Width / image.GetWidth(); + float xOffset = source.Left / image.GetWidth(); + float yScale = source.Height / image.GetHeight(); + float yOffset = source.Top / image.GetHeight(); + + mImageShader.SetUniformf("uvManip", { xScale, xOffset, yScale, yOffset }); + mImageShader.SetUniformMatrix("model", 1, glm::value_ptr(trans)); + mImageShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection)); + mImageShader.SetUniformf("spriteColor", { color.Red, color.Green, color.Blue, color.Alpha }); + //} + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, image.GetGLTextureID()); + + glBindVertexArray(mImageVAO); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + + } + + void OglGraphics::DrawString(const char* string, Rectangle boundingArea, Color color, int font) + { + + } + + // Takes raw image data and creates and Image class instance out of it. + // The raw data must be in one of the ImageFormats and it must be 1 byte per channel. + Image* OglGraphics::CreateImage(const unsigned char* pData, int width, int height, ImageFormat format) + { + return nullptr; + } + + // Fonts + int OglGraphics::DefaultFont() const + { + return mDefaultFont; + } + + // For weight, 400 is normal and 700 is bold + int OglGraphics::CreateNewFont(const char* fontName, float size, int weight) + { + return -1; + } + + //////////////////////////////////////////////////////////// + // HELPER INIT METHODS + //////////////////////////////////////////////////////////// + + void OglGraphics::InitDebugMsgSystem() + { + // DEBUG MESSAGE TYPES + mDebugMsgTypes[GL_DEBUG_TYPE_ERROR] = "ERROR"; + mDebugMsgTypes[GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR] = "DEPRECATED_BEHAVIOR"; + mDebugMsgTypes[GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR] = "UNDEFINED_BEHAVIOR"; + mDebugMsgTypes[GL_DEBUG_TYPE_PORTABILITY] = "PORTABILITY"; + mDebugMsgTypes[GL_DEBUG_TYPE_PERFORMANCE] = "PERFORMANCE"; + mDebugMsgTypes[GL_DEBUG_TYPE_OTHER] = "OTHER"; + mDebugMsgTypes[GL_DEBUG_TYPE_MARKER] = "MARKER"; + mDebugMsgTypes[GL_DEBUG_TYPE_PUSH_GROUP] = "PUSH_GROUP"; + mDebugMsgTypes[GL_DEBUG_TYPE_POP_GROUP] = "POP_GROUP"; + + // DEBUG MESSAGE SOURCES + mDebugMsgSources[GL_DEBUG_SOURCE_API] = "API"; + mDebugMsgSources[GL_DEBUG_SOURCE_WINDOW_SYSTEM] = "WINDOW_SYSTEM"; + mDebugMsgSources[GL_DEBUG_SOURCE_SHADER_COMPILER] = "SHADER_COMPILER"; + mDebugMsgSources[GL_DEBUG_SOURCE_THIRD_PARTY] = "THIRD_PARTY"; + mDebugMsgSources[GL_DEBUG_SOURCE_APPLICATION] = "APPLICATION"; + mDebugMsgSources[GL_DEBUG_SOURCE_OTHER] = "OTHER"; + + // DEBUG MESSAGE SEVERITY + mDebugMsgSeverity[GL_DEBUG_SEVERITY_HIGH] = "HIGH"; + mDebugMsgSeverity[GL_DEBUG_SEVERITY_MEDIUM] = "MEDIUM"; + mDebugMsgSeverity[GL_DEBUG_SEVERITY_LOW] = "LOW"; + mDebugMsgSeverity[GL_DEBUG_SEVERITY_NOTIFICATION] = "NOTIFICATION"; + + glEnable(GL_DEBUG_OUTPUT); + glDebugMessageCallback(MessageCallback, 0); + } + + void OglGraphics::InitImageSystem() + { + // Setup geometry + // https://learnopengl.com/In-Practice/2D-Game/Rendering-Sprites + GLuint VBO; + GLfloat vertices[] = { + // Pos // Tex + 0.0f, 1.0f, 0.0f, 1.0f, + 1.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + + 0.0f, 1.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 0.0f, 1.0f, 0.0f + }; + + glGenVertexArrays(1, &mImageVAO); + glGenBuffers(1, &VBO); + + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glBindVertexArray(mImageVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + // Setup Shader Program + mImageShader.SetSource(glShader::TYPE_VERTEX, OGLDefaultShaders.DefaultSpriteVertex, false); + mImageShader.SetSource(glShader::TYPE_FRAGMENT, OGLDefaultShaders.DefaultSpriteFragment, false); + if (!mImageShader.BuildProgram()) + { + Logger::Log(LogCategory::GRAPHICS, LogLevel::ERROR, "Unable to build default image shader program"); + } + } + + void OglGraphics::InitTextSystem() + { + // TODO: Check to see if Dear ImGui can be used to render text + // If it can render text on the app window and doesn't need + // to render onto one of it's own windows then it should work. + // If not add FreeType to the project and put the text rendering + // into it's own class. + } + + void OglGraphics::InitShapeSystem() + { + // Create rectangle buffers + glGenVertexArrays(1, &mRectVAO); + glGenBuffers(1, &mRectVBO); + glBindVertexArray(mRectVAO); + glBindBuffer(GL_ARRAY_BUFFER, mRectVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + // Create Ellipse buffers + glGenVertexArrays(1, &mEllipseVAO); + glGenBuffers(1, &mEllipseVBO); + glBindVertexArray(mEllipseVAO); + glBindBuffer(GL_ARRAY_BUFFER, mEllipseVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 362 * 2, NULL, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + + // Load shape shaders + mShapeShader.SetSource(glShader::TYPE_VERTEX, OGLDefaultShaders.DefaultShapeVertex, false); + mShapeShader.SetSource(glShader::TYPE_FRAGMENT, OGLDefaultShaders.DefaultShapeFragment, false); + if (!mShapeShader.BuildProgram()) + { + Logger::Log(LogCategory::GRAPHICS, LogLevel::WARNING, "Unable to build shape shader program."); + } + } +} \ No newline at end of file diff --git a/src/graphics/OGLGraphics.h b/src/graphics/OGLGraphics.h new file mode 100644 index 0000000..e1b12bc --- /dev/null +++ b/src/graphics/OGLGraphics.h @@ -0,0 +1,96 @@ +/****************************************************************************** +* File - OGLGraphics.h +* Author - Joey Pollack +* Date - 2021/08/30 (y/m/d) +* Mod Date - 2021/09/02 (y/m/d) +* Description - An openGL implementation of the engine Graphics interface. +******************************************************************************/ + +#ifndef OGLGRAPHICS_H_ +#define OGLGRAPHICS_H_ + +#include "IGraphics.h" +#include +#include "glShader.h" +#include +#include + + +namespace lunarium +{ + class OglGraphics : public IGraphics + { + private: // Interface methods for use only by the engine + friend Core; + + OglGraphics(); + + virtual OpRes Initialized(Window* pWindow, bool enableDebugMessages = true); + virtual void Shutdown(); + + virtual void ResizeCanvas(); + + virtual void BeginDraw(); + virtual void EndDraw(); + + public: // + + virtual void SetClearColor(Color c); + virtual Color GetClearColor() const; + + // Draw Methods + virtual void DrawLine(glm::vec2 point1, glm::vec2 point2, Color color, float lineWidth); + virtual void DrawEllipse(glm::vec2 center, glm::vec2 radii, Color color, float thickness, int resolution); + virtual void DrawFilledEllipse(glm::vec2 center, glm::vec2 radii, Color color, int resolution); + virtual void DrawBox(Rectangle dimensions, Color color, float thickness); + virtual void DrawFilledBox(glm::vec2 topLeft, glm::vec2 botRight, Color color); + virtual void DrawImage(Image& image, glm::vec2 topLeft, Color color); + virtual void DrawImage(Image& image, Rectangle source, Rectangle destination, Color color); + virtual void DrawString(const char* string, Rectangle boundingArea, Color color, int font = 0); + + // Takes raw image data and creates and Image class instance out of it. + // The raw data must be in one of the ImageFormats and it must be 1 byte per channel. + virtual Image* CreateImage(const unsigned char* pData, int width, int height, ImageFormat format); + + // Fonts + int DefaultFont() const; + + // For weight, 400 is normal and 700 is bold + virtual int CreateNewFont(const char* fontName, float size = 12.0f, int weight = 400); + + private: // DATA + Window* mpWindow; + glm::mat4 mProjection; + + // Sprite Data + unsigned int mImageVAO; + glShader mImageShader; + + // Shapes + GLuint mRectVAO; + GLuint mRectVBO; + glShader mShapeShader; + + // Ellipse + GLuint mEllipseVAO; + GLuint mEllipseVBO; + + private: // Helper Initializers + void InitDebugMsgSystem(); + void InitImageSystem(); + void InitTextSystem(); + void InitShapeSystem(); + + private: // Helper methods + + private: // Debug Message System + + friend void __stdcall MessageCallback(GLenum source, GLenum type, GLuint id, + GLenum severity, GLsizei length, const GLchar* message, const void* userParam); + static std::map mDebugMsgTypes; + static std::map mDebugMsgSources; + static std::map mDebugMsgSeverity; + }; +} + +#endif // OGLGRAPHICS_H_ \ No newline at end of file diff --git a/src/graphics/Shaders/DefaultImage.frag b/src/graphics/Shaders/DefaultImage.frag new file mode 100644 index 0000000..7837b32 --- /dev/null +++ b/src/graphics/Shaders/DefaultImage.frag @@ -0,0 +1,11 @@ +#version 330 core +in vec2 TexCoords; +out vec4 color; + +uniform sampler2D image; +uniform vec3 spriteColor; + +void main() +{ + color = vec4(spriteColor, 1.0) * texture(image, TexCoords); +} \ No newline at end of file diff --git a/src/graphics/Shaders/DefaultImage.vert b/src/graphics/Shaders/DefaultImage.vert new file mode 100644 index 0000000..bdf605a --- /dev/null +++ b/src/graphics/Shaders/DefaultImage.vert @@ -0,0 +1,13 @@ +#version 330 core +layout (location = 0) in vec4 vertex; // + +out vec2 TexCoords; + +uniform mat4 model; +uniform mat4 projection; + +void main() +{ + TexCoords = vertex.zw; + gl_Position = projection * model * vec4(vertex.xy, 0.0, 1.0); +} \ No newline at end of file diff --git a/src/graphics/glShader.cpp b/src/graphics/glShader.cpp new file mode 100644 index 0000000..c737e07 --- /dev/null +++ b/src/graphics/glShader.cpp @@ -0,0 +1,322 @@ +/****************************************************************************** +* File - glShader.cpp +* Author - Joey Pollack +* Date - 2018/06/26 (y/m/d) +* Mod Date - 2021/09/02 (y/m/d) +* Description - Manages a single OpenGL shader program +* +******************************************************************************/ + +#include "glShader.h" + +#include +#include +#include +#include + +#include + +#include + +namespace lunarium +{ + + glShader::glShader() + : mProgram(0), mbProgramBuilt(false), mpLogger(Logger::GetInstance()) + { + int glTypes[TYPE_COUNT]; + glTypes[TYPE_VERTEX] = GL_VERTEX_SHADER; + glTypes[TYPE_GEOMETRY] = GL_GEOMETRY_SHADER; + glTypes[TYPE_FRAGMENT] = GL_FRAGMENT_SHADER; + + for (int i = 0; i < TYPE_COUNT; i++) + { + mShaders[i].ID = 0; + mShaders[i].Source = ""; + mShaders[i].IsCompiled = false; + mShaders[i].GLType = glTypes[i]; + } + } + + bool glShader::IsBuilt() const + { + return mbProgramBuilt; + } + + + bool glShader::SetUniformi(const char * uniformName, std::vector values, bool asVector) + { + int uniformLocation = glGetUniformLocation(mProgram, uniformName); + + if (asVector) + { + int count = ((int)values.size()) / 4; + glUniform4iv(uniformLocation, count, (int*)values.data()); + return true; + } + + if (values.size() == 1) + { + glUniform1i(uniformLocation, values[0]); + return true; + } + else if (values.size() == 2) + { + glUniform2i(uniformLocation, values[0], values[1]); + return true; + } + else if (values.size() == 3) + { + glUniform3i(uniformLocation, values[0], values[1], values[2]); + return true; + } + else if (values.size() == 4) + { + glUniform4i(uniformLocation, values[0], values[1], values[2], values[3]); + return true; + } + return false; + } + + bool glShader::SetUniformf(const char * uniformName, std::vector values, bool asVector) + { + int uniformLocation = glGetUniformLocation(mProgram, uniformName); + + if (asVector) + { + int count = ((int)values.size()) / 4; + glUniform4fv(uniformLocation, count, (float*)values.data()); + return true; + } + + if (values.size() == 1) + { + glUniform1f(uniformLocation, values[0]); + return true; + } + else if (values.size() == 2) + { + glUniform2f(uniformLocation, values[0], values[1]); + return true; + } + else if (values.size() == 3) + { + glUniform3f(uniformLocation, values[0], values[1], values[2]); + return true; + } + else if (values.size() == 4) + { + glUniform4f(uniformLocation, values[0], values[1], values[2], values[3]); + return true; + } + return false; + } + + bool glShader::SetUniformMatrix(const char * uniformName, int numMats, float * pData) + { + int uniformLocation = glGetUniformLocation(mProgram, uniformName); + + if (-1 == uniformLocation) + { + Logger::Log(LogCategory::GRAPHICS, LogLevel::ERROR, + "Unable to find uniform location. Uniform name: %s", uniformName); + return false; + } + + glUniformMatrix4fv(uniformLocation, numMats, GL_FALSE, pData); + + return true; + } + + void glShader::LogAllUniforms() const + { + GLint size; // size of the variable + GLenum type; // type of the variable (float, vec3 or mat4, etc) + + const GLsizei bufSize = 16; // maximum name length + GLchar name[bufSize]; // variable name in GLSL + GLsizei length; // name length + int count = -1; + + glGetProgramiv(mProgram, GL_ACTIVE_UNIFORMS, &count); + Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO, "Active Uniforms: %d", count); + + for (int i = 0; i < count; i++) + { + glGetActiveUniform(mProgram, (GLuint)i, bufSize, &length, &size, &type, name); + + Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO, "Uniform #%d Type: %u Name: %s", i, type, name); + } + } + + bool glShader::SetSource(int sourceType, const char * source, bool loadFromFile) + { + if (sourceType < 0 || sourceType >= TYPE_COUNT) + { + Logger::Log(LogCategory::GRAPHICS, LogLevel::ERROR, + "Can not set shader source (%s) - Invalid Source Type (%d)", source, (int)sourceType); + return false; + } + + if (loadFromFile) + { + mShaders[sourceType].Source = LoadShaderFromFile(source); + if ("" == mShaders[sourceType].Source) + return false; + } + else + { + mShaders[sourceType].Source = source; + } + + + return true; + } + + + bool glShader::CompileShader(int sourceType) + { + if (sourceType < 0 || sourceType >= TYPE_COUNT) + { + Logger::Log(LogCategory::GRAPHICS, LogLevel::ERROR, + "Can not compile source - Invalid Source Type: %d", (int)sourceType); + return false; + } + + if ("" == mShaders[sourceType].Source) + { + Logger::Log(LogCategory::GRAPHICS, LogLevel::ERROR, + "Can not compile %s shader source - Source is empty", TypeNames[sourceType]); + return false; + } + + int success; + char infoLog[512]; + + // Create shader + mShaders[sourceType].ID = glCreateShader(mShaders[sourceType].GLType); + + // compile source + const char* tempSource = mShaders[sourceType].Source.c_str(); + glShaderSource(mShaders[sourceType].ID, 1, &tempSource, NULL); + glCompileShader(mShaders[sourceType].ID); + + + // check for errors + glGetShaderiv(mShaders[sourceType].ID, GL_COMPILE_STATUS, &success); + if (!success) + { + glGetShaderInfoLog(mShaders[sourceType].ID, 512, NULL, infoLog); + Logger::Log(LogCategory::GRAPHICS, LogLevel::ERROR, + "Error compiling %s shader source: %s", TypeNames[sourceType], infoLog); + return false; + } + + mShaders[sourceType].IsCompiled = true; + return true; + } + + bool glShader::BuildProgram(bool autoFreeShaders) + { + if ("" == mShaders[TYPE_VERTEX].Source || "" == mShaders[TYPE_FRAGMENT].Source) + { + Logger::Log(LogCategory::GRAPHICS, LogLevel::ERROR, + "Cannot create shader program - vertex and fragment shader must be set!"); + return false; + } + + + mProgram = glCreateProgram(); + + + for (int i = 0; i < TYPE_COUNT; i++) + { + + // Compile shaders if needed + // ------------------------------------------- + if (!mShaders[i].IsCompiled) + { + if (mShaders[i].Source == "") + { + Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO_VERBOSE, + "Skipping compilation of %s shader source - source is empty", TypeNames[i]); + } + else + { + if (!CompileShader(i)) + { + return false; + } + } + + } + + // Attach the shader to the program + // ------------------------------------------- + if (mShaders[i].Source != "") + glAttachShader(mProgram, mShaders[i].ID); + } + + + // Link and check for errors + glLinkProgram(mProgram); + + int success; + char infoLog[512]; + + glGetProgramiv(mProgram, GL_LINK_STATUS, &success); + if (!success) + { + glGetProgramInfoLog(mProgram, 512, NULL, infoLog); + Logger::Log(LogCategory::GRAPHICS, LogLevel::ERROR, + "Failed to link the shader program. Info Log: %s", infoLog); + return false; + } + + // Clean up + if (autoFreeShaders) + { + FreeShaders(); + } + + mbProgramBuilt = true; + return true; + } + + + void glShader::FreeShaders() + { + for (int i = 0; i < TYPE_COUNT; i++) + { + if (mShaders[i].IsCompiled) + { + glDeleteShader(mShaders[i].ID); + mShaders[i].ID = 0; + mShaders[i].IsCompiled = false; + } + } + } + + void glShader::MakeActive() + { + glUseProgram(mProgram); + } + + std::string glShader::LoadShaderFromFile(const char * filename) + { + std::ifstream ifs(filename); + + if (!ifs.is_open()) + { + Logger::Log(LogCategory::GRAPHICS, LogLevel::ERROR, + "Failed to load shader source from file (file not found): %s", filename); + return ""; + } + + std::stringstream stream; + stream << ifs.rdbuf(); + ifs.close(); + + return stream.str(); + } +} \ No newline at end of file diff --git a/src/graphics/glShader.h b/src/graphics/glShader.h new file mode 100644 index 0000000..6145e44 --- /dev/null +++ b/src/graphics/glShader.h @@ -0,0 +1,77 @@ +/****************************************************************************** +* File - glShader.h +* Author - Joey Pollack +* Date - 2018/06/26 (y/m/d) +* Mod Date - 2021/09/02 (y/m/d) +* Description - Manages a single OpenGL shader program. Uses GLEW. +* +******************************************************************************/ + +#ifndef GL_SHADER_H_ +#define GL_SHADER_H_ + + +#include +#include +#include + + +namespace lunarium +{ + class Logger; + + class glShader + { + private: + + struct ShaderInfo + { + unsigned int ID; + std::string Source; + bool IsCompiled; + int GLType; + }; + + public: + + // To support more shader types: + // 1) Add a TYPE_* enum value here before TYPE_COUNT + // 2) in the constructor add a new GLType to the array in the correct place + enum { TYPE_VERTEX, TYPE_GEOMETRY, TYPE_FRAGMENT, TYPE_COUNT, TYPE_INVALID = TYPE_COUNT }; + const char* TypeNames[3] = { "Vertex", "Geometry", "Fragment" }; + + glShader(); + + bool IsBuilt() const; + + bool SetSource(int sourceType, const char* source, bool loadFromFile = true); + bool CompileShader(int sourceType); + bool BuildProgram(bool autoFreeShaders = true); + void FreeShaders(); + + void MakeActive(); + + bool SetUniformi(const char* uniformName, std::vector values, bool asVector = false); + bool SetUniformf(const char* uniformName, std::vector values, bool asVector = false); + bool SetUniformMatrix(const char* uniformName, int numMats, float* pData); + + void LogAllUniforms() const; + + + private: + + unsigned int mProgram; + bool mbProgramBuilt; + + ShaderInfo mShaders[TYPE_COUNT]; + + Logger* mpLogger; + + private: // Helper Methods + + std::string LoadShaderFromFile(const char* filename); + }; +} + +#endif // GL_SHADER_H_ + diff --git a/src/graphics/window.cpp b/src/graphics/window.cpp index 2515ebd..735f618 100644 --- a/src/graphics/window.cpp +++ b/src/graphics/window.cpp @@ -41,7 +41,7 @@ namespace lunarium if( !glfwInit() ) { char buffer[1024]; - glfwGetError((char**)&buffer); + glfwGetError((const char**)&buffer); std::ostringstream oss; oss << "Failed to initialize GLFW: " << buffer; return OpRes::Fail(oss.str().c_str()); @@ -53,7 +53,7 @@ namespace lunarium glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, OPENGL_MAJOR_VERSION); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, OPENGL_MINOR_VERSION); - Logger::GetInstance()->Log(LogCategory::GRAPHICS, LogLevel::INFO, + Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO, "Creating OpenGL Context version %d, %d and glsl %s", OPENGL_MAJOR_VERSION, OPENGL_MINOR_VERSION, System::GetGLSLVersionString().c_str()); @@ -62,7 +62,7 @@ namespace lunarium { glfwTerminate(); char buffer[1024]; - glfwGetError((char**)&buffer); + glfwGetError((const char**)&buffer); std::ostringstream oss; oss << "Failed to initialize GLFWFailed to open GLFW window: " << buffer; return OpRes::Fail(oss.str().c_str()); @@ -79,7 +79,7 @@ namespace lunarium // Use glad2 to load extensions int version = gladLoadGL(glfwGetProcAddress); - Logger::GetInstance()->Log(LogCategory::GRAPHICS, LogLevel::INFO, + Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO, "Glad2 Loaded version: %d.%d", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version)); } else @@ -107,6 +107,10 @@ namespace lunarium glfwSetWindowSize(mpWindow, width, height); } + void Window::SetShouldCloseFlag(bool should_close) + { + glfwSetWindowShouldClose(mpWindow, should_close); + } // If fullscreen is true but we're already in fullscreen mode this function will change the // resolution. If fullscreen is false but we're not fullscreen this function will change diff --git a/src/graphics/window.h b/src/graphics/window.h index 44c1d29..7660660 100644 --- a/src/graphics/window.h +++ b/src/graphics/window.h @@ -36,6 +36,7 @@ namespace lunarium void GetFramebufferSize(int* width, int* height) const; + void SetShouldCloseFlag(bool should_close); bool ShouldWindowClose() const; static void PollEvents(); void SwapBuffers(); diff --git a/src/test_main.cpp b/src/test_main.cpp index a1cc886..b609b6d 100644 --- a/src/test_main.cpp +++ b/src/test_main.cpp @@ -108,12 +108,12 @@ int main(int argc, char** argv) std::cout <<"\nTesting loading a state from file..."; lunarium::State testState; - if (lunarium::IsOK(lunarium::State::CreateFromFile("test_data/test_state.xml", testState))) + if (lunarium::IsOK(lunarium::State::CreateFromFile("lunarium_state.xml", testState))) { std::cout << "\nIt worked! Full Screen Resolution Width: " << testState.Display.FullScreenResolution.Width; std::cout << "\nSaving out to test_save.xml"; - if (lunarium::IsOK(testState.SaveToFile("test_data/test_save.xml"))) + if (lunarium::IsOK(testState.SaveToFile("test_save.xml"))) { std::cout << "\nSuccess!\n"; } @@ -158,6 +158,11 @@ int main(int argc, char** argv) int version = gladLoadGL(glfwGetProcAddress); printf("GL %d.%d\n", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version)); + int testwidth = 0; + int testheight = 0; + glfwGetFramebufferSize(window, &testwidth, &testheight); + std::cout << "\nframe buffer size: " << testwidth << ", " << testheight << "\n"; + // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); diff --git a/src/utils/Logger.cpp b/src/utils/Logger.cpp index 76ece25..cf77034 100644 --- a/src/utils/Logger.cpp +++ b/src/utils/Logger.cpp @@ -329,11 +329,11 @@ namespace lunarium { mBacklog.clear(); } - - void Logger::Log(uint32_t logCategory, uint32_t logLevel, const char * message, ...) + + void Logger::Log(uint32_t logCategory, uint32_t logLevel, const char* message, ...) { // clear the buffer - memset(mBuffer, 0, BUFFER_SIZE); + memset(mInstance->mBuffer, 0, BUFFER_SIZE); if (strlen(message) >= BUFFER_SIZE) throw std::runtime_error("Log message size exceeds buffer size"); @@ -341,9 +341,14 @@ namespace lunarium // Fill the buffer with the formatted message va_list args; va_start(args, message); - vsprintf(mBuffer, message, args); + vsprintf(mInstance->mBuffer, message, args); va_end(args); + mInstance->Log_buff(logCategory, logLevel); + } + + void Logger::Log_buff(uint32_t logCategory, uint32_t logLevel) + { double timeStamp = mTimer.GetElapsedSeconds(); LogMessage lm; diff --git a/src/utils/Logger.h b/src/utils/Logger.h index fd7ffd6..08ac48c 100644 --- a/src/utils/Logger.h +++ b/src/utils/Logger.h @@ -156,7 +156,8 @@ namespace lunarium // The message argument and the variable argument list work just like // printf. Use the same formatters as printf when calling this function. // Messages must be shorter than 1024 bytes. - void Log(uint32_t logCategory, uint32_t logLevel, const char* message, ...); + static void Log(uint32_t logCategory, uint32_t logLevel, const char* message, ...); + void Log_buff(uint32_t logCategory, uint32_t logLevel); const std::vector& GetBacklog() const; diff --git a/src/utils/types.cpp b/src/utils/types.cpp new file mode 100644 index 0000000..eb013e5 --- /dev/null +++ b/src/utils/types.cpp @@ -0,0 +1,73 @@ +/****************************************************************************** +* File - types.cpp +* Author - Joey Pollack +* Date - 2021/08/30 (y/m/d) +* Mod Date - 2021/09/02 (y/m/d) +* Description - Defines some generic types for use through out the engine. +******************************************************************************/ + + +#include "types.h" + +namespace lunarium +{ + //////////////////////////////////////////////////////////// + // COLOR + //////////////////////////////////////////////////////////// + Color::Color(float _r, float _g, float _b, float _a) + : Red(_r), Green(_g), Blue(_b), Alpha(_a) + { + + } + + Color::Color() + : Red(0.0f), Green(0.0f), Blue(0.0f), Alpha(0.0f) + { + + } + + //////////////////////////////////////////////////////////// + // RECTANGLE + //////////////////////////////////////////////////////////// + Rectangle::Rectangle() + : Left(0.0f), Top(0.0f), Width(0.0f), Height(0.0f) + { + + } + + Rectangle::Rectangle(float _left, float _top, float _width, float _height) + : Left(_left), Top(_top), Width(_width), Height(_height) + { + + } + float Rectangle::Area() const + { + return Width * Height; + } + + bool Rectangle::ContainsPoint(glm::vec2 point) const + { + if (point.x < this->Left || point.x > this->right()) + return false; + + if (point.y < this->Top || point.y > this->bottom()) + return false; + + return true; + } + + bool Rectangle::Intersects(const Rectangle& other, glm::vec2& centers) const + { + glm::vec2 myCenter = glm::vec2(this->Left + (this->Width / 2.0f), this->Top + (this->Height / 2.0f)); + glm::vec2 otherCenter = glm::vec2(other.Left + (other.Width / 2.0f), other.Top + (other.Height / 2.0f)); + centers = myCenter - otherCenter; + + if (this->Left > other.right() || other.Left > this->right()) + return false; + + if (this->Top > other.bottom() || other.Top > this->bottom()) + return false; + + return true; + } +} \ No newline at end of file diff --git a/src/utils/types.h b/src/utils/types.h index 8c29bdd..1661b91 100644 --- a/src/utils/types.h +++ b/src/utils/types.h @@ -2,15 +2,20 @@ * File - types.h * Author - Joey Pollack * Date - 2021/08/30 (y/m/d) -* Mod Date - 2021/08/30 (y/m/d) +* Mod Date - 2021/09/02 (y/m/d) * Description - Defines some generic types for use through out the engine. ******************************************************************************/ #ifndef TYPES_H_ #define TYPES_H_ +#include + namespace lunarium { + /////////////////////////////////////////////////////// + // SIZE + ////////////////////////////////////////////////////// template struct Size { @@ -21,6 +26,57 @@ namespace lunarium typedef Size Sizei; typedef Size Sizeu; typedef Size Sizef; + ///////////////////////////////////////////////// + + ///////////////////////////////////////////////// + // COLOR + ///////////////////////////////////////////////// + struct Color + { + union + { + float arr[4]; + + struct + { + float Red; + float Green; + float Blue; + float Alpha; + }; + }; + + Color(); + Color(float _r, float _g, float _b, float _a = 1.0f); + }; + ///////////////////////////////////////////////// + + + ///////////////////////////////////////////////// + // SIZE + ///////////////////////////////////////////////// + struct Rectangle + { + float Left; + float Top; + float Width; + float Height; + + float right() const { return Left + Width; } + float bottom() const { return Top + Height; } + + Rectangle(); + Rectangle(float _left, float _top, float _width, float _height); + + float Area() const; + bool ContainsPoint(glm::vec2 point) const; + + // centers will be filled out with a vector the goes from the other + // Rectangle's center to the invoking object's center. + // This could be used for determining the angle of the intersection. + bool Intersects(const Rectangle& other, glm::vec2& centers) const; + }; + ///////////////////////////////////////////////// } #endif // TYPES_H_ \ No newline at end of file diff --git a/test_data/test_state.xml b/test_data/lunarium_state.xml similarity index 100% rename from test_data/test_state.xml rename to test_data/lunarium_state.xml