OglGraphics mostly implemented but needs testing

Fonts and text rendering not yet implemented
Gui_Panel_Refactor
Joeyrp 4 years ago
parent a92e55ee01
commit 2c6b8eaa4c

@ -19,6 +19,7 @@ set(LUNARIUM_SRC
"src/core/core.cpp" "src/core/core.cpp"
"src/core/state.cpp" "src/core/state.cpp"
"src/core/Version.cpp" "src/core/Version.cpp"
"src/utils/types.cpp"
"src/utils/Logger.cpp" "src/utils/Logger.cpp"
"src/utils/HighResTimer.cpp" "src/utils/HighResTimer.cpp"
"src/utils/helpers.cpp" "src/utils/helpers.cpp"
@ -26,6 +27,9 @@ set(LUNARIUM_SRC
"src/utils/Args.cpp" "src/utils/Args.cpp"
"src/utils/BinaryFileBuffer.cpp" "src/utils/BinaryFileBuffer.cpp"
"src/graphics/window.cpp" "src/graphics/window.cpp"
"src/graphics/oglgraphics.cpp"
"src/graphics/glShader.cpp"
"src/graphics/image.cpp"
) )
# add the executable # add the executable

@ -10,10 +10,10 @@ IF not exist build/ (
IF "%~1" == "r" ( IF "%~1" == "r" (
cmake --build build/ --target ALL_BUILD --config Release 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 ( ) ELSE (
cmake --build build/ --target ALL_BUILD --config Debug 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 :END

@ -66,13 +66,13 @@ namespace lunarium
mpLog->AddListener(listeners[i]); 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. // 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"); mpLog->Log(LogCategory::CORE, LogLevel::INFO, "Attempting to load state file: lunarium_state.xml");
if (Failed(State::CreateFromFile("lunarium_state.xml", mState))) 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(); mState = State::CreateDefault();
} }

@ -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_

@ -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 <utils/types.h>
#include <utils/opRes.h>
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_

@ -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;
}
}

@ -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_

@ -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 <utils/logger.h>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
namespace lunarium
{
////////////////////////////////////////////////////////////
// DEBUG MESSAGE CALLBACK
////////////////////////////////////////////////////////////
std::map<int, std::string> OglGraphics::mDebugMsgTypes;
std::map<int, std::string> OglGraphics::mDebugMsgSources;
std::map<int, std::string> 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.");
}
}
}

@ -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 <glad/gl.h>
#include "glShader.h"
#include <map>
#include <string>
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<int, std::string> mDebugMsgTypes;
static std::map<int, std::string> mDebugMsgSources;
static std::map<int, std::string> mDebugMsgSeverity;
};
}
#endif // OGLGRAPHICS_H_

@ -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);
}

@ -0,0 +1,13 @@
#version 330 core
layout (location = 0) in vec4 vertex; // <vec2 position, vec2 texCoords>
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);
}

@ -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 <fstream>
#include <iostream>
#include <sstream>
#include <cstdarg>
#include <glad/gl.h>
#include <utils/logger.h>
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<int> 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<float> 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();
}
}

@ -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 <string>
#include <iostream>
#include <vector>
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<int> values, bool asVector = false);
bool SetUniformf(const char* uniformName, std::vector<float> 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_

@ -41,7 +41,7 @@ namespace lunarium
if( !glfwInit() ) if( !glfwInit() )
{ {
char buffer[1024]; char buffer[1024];
glfwGetError((char**)&buffer); glfwGetError((const char**)&buffer);
std::ostringstream oss; std::ostringstream oss;
oss << "Failed to initialize GLFW: " << buffer; oss << "Failed to initialize GLFW: " << buffer;
return OpRes::Fail(oss.str().c_str()); 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_MAJOR, OPENGL_MAJOR_VERSION);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, OPENGL_MINOR_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", "Creating OpenGL Context version %d, %d and glsl %s",
OPENGL_MAJOR_VERSION, OPENGL_MINOR_VERSION, System::GetGLSLVersionString().c_str()); OPENGL_MAJOR_VERSION, OPENGL_MINOR_VERSION, System::GetGLSLVersionString().c_str());
@ -62,7 +62,7 @@ namespace lunarium
{ {
glfwTerminate(); glfwTerminate();
char buffer[1024]; char buffer[1024];
glfwGetError((char**)&buffer); glfwGetError((const char**)&buffer);
std::ostringstream oss; std::ostringstream oss;
oss << "Failed to initialize GLFWFailed to open GLFW window: " << buffer; oss << "Failed to initialize GLFWFailed to open GLFW window: " << buffer;
return OpRes::Fail(oss.str().c_str()); return OpRes::Fail(oss.str().c_str());
@ -79,7 +79,7 @@ namespace lunarium
// Use glad2 to load extensions // Use glad2 to load extensions
int version = gladLoadGL(glfwGetProcAddress); 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)); "Glad2 Loaded version: %d.%d", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version));
} }
else else
@ -107,6 +107,10 @@ namespace lunarium
glfwSetWindowSize(mpWindow, width, height); 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 // 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 // resolution. If fullscreen is false but we're not fullscreen this function will change

@ -36,6 +36,7 @@ namespace lunarium
void GetFramebufferSize(int* width, int* height) const; void GetFramebufferSize(int* width, int* height) const;
void SetShouldCloseFlag(bool should_close);
bool ShouldWindowClose() const; bool ShouldWindowClose() const;
static void PollEvents(); static void PollEvents();
void SwapBuffers(); void SwapBuffers();

@ -108,12 +108,12 @@ int main(int argc, char** argv)
std::cout <<"\nTesting loading a state from file..."; std::cout <<"\nTesting loading a state from file...";
lunarium::State testState; 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 << "\nIt worked! Full Screen Resolution Width: " << testState.Display.FullScreenResolution.Width;
std::cout << "\nSaving out to test_save.xml"; 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"; std::cout << "\nSuccess!\n";
} }
@ -158,6 +158,11 @@ int main(int argc, char** argv)
int version = gladLoadGL(glfwGetProcAddress); int version = gladLoadGL(glfwGetProcAddress);
printf("GL %d.%d\n", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version)); 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 // Setup Dear ImGui context
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
ImGui::CreateContext(); ImGui::CreateContext();

@ -330,10 +330,10 @@ namespace lunarium
mBacklog.clear(); 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 // clear the buffer
memset(mBuffer, 0, BUFFER_SIZE); memset(mInstance->mBuffer, 0, BUFFER_SIZE);
if (strlen(message) >= BUFFER_SIZE) if (strlen(message) >= BUFFER_SIZE)
throw std::runtime_error("Log message size exceeds 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 // Fill the buffer with the formatted message
va_list args; va_list args;
va_start(args, message); va_start(args, message);
vsprintf(mBuffer, message, args); vsprintf(mInstance->mBuffer, message, args);
va_end(args); va_end(args);
mInstance->Log_buff(logCategory, logLevel);
}
void Logger::Log_buff(uint32_t logCategory, uint32_t logLevel)
{
double timeStamp = mTimer.GetElapsedSeconds(); double timeStamp = mTimer.GetElapsedSeconds();
LogMessage lm; LogMessage lm;

@ -156,7 +156,8 @@ namespace lunarium
// The message argument and the variable argument list work just like // The message argument and the variable argument list work just like
// printf. Use the same formatters as printf when calling this function. // printf. Use the same formatters as printf when calling this function.
// Messages must be shorter than 1024 bytes. // 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<LogMessage>& GetBacklog() const; const std::vector<LogMessage>& GetBacklog() const;

@ -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;
}
}

@ -2,15 +2,20 @@
* File - types.h * File - types.h
* Author - Joey Pollack * Author - Joey Pollack
* Date - 2021/08/30 (y/m/d) * 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. * Description - Defines some generic types for use through out the engine.
******************************************************************************/ ******************************************************************************/
#ifndef TYPES_H_ #ifndef TYPES_H_
#define TYPES_H_ #define TYPES_H_
#include <glm/glm.hpp>
namespace lunarium namespace lunarium
{ {
///////////////////////////////////////////////////////
// SIZE
//////////////////////////////////////////////////////
template <typename T> template <typename T>
struct Size struct Size
{ {
@ -21,6 +26,57 @@ namespace lunarium
typedef Size<int> Sizei; typedef Size<int> Sizei;
typedef Size<unsigned> Sizeu; typedef Size<unsigned> Sizeu;
typedef Size<float> Sizef; typedef Size<float> 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_ #endif // TYPES_H_
Loading…
Cancel
Save