From be4e63046a4584ca4d86471e8f081010195fc58d Mon Sep 17 00:00:00 2001 From: Derek Christ Date: Thu, 8 Jul 2021 17:42:26 +0200 Subject: [PATCH] Some refactoring in multithreading. --- .clang-format | 1 - .clang-tidy | 45 +++++++++++++ CMakeLists.txt | 2 + data/lights.json | 28 ++++++-- data/models.json | 28 ++++++-- data/screens.json | 42 +++++++++--- data/shaderPrograms.json | 2 +- data/shaders/menu.frag | 3 +- src/CMakeLists.txt | 5 ++ src/Controller.cpp | 116 +++++++------------------------- src/Controller.h | 15 ++++- src/Entity.cpp | 7 +- src/FrameBuffer.cpp | 4 +- src/GLBucket.cpp | 16 +++++ src/GLBucket.h | 19 ++++++ src/Helper.h | 2 +- src/JsonParser.cpp | 45 +++---------- src/JsonParser.h | 5 +- src/Light.h | 2 +- src/Menu.cpp | 6 +- src/Mesh.cpp | 30 ++++++--- src/Mesh.h | 16 +++-- src/Model.cpp | 104 +++++++++++++--------------- src/Model.h | 25 +++---- src/Screen.cpp | 6 +- src/Screen.h | 2 +- src/Texture.cpp | 43 +++++++----- src/Texture.h | 15 ++++- src/VertexArray.cpp | 1 + src/Widget.cpp | 3 +- src/Window.cpp | 1 - src/Window.h | 2 + src/World.cpp | 39 ++++++++--- src/World.h | 2 +- src/imgui/EntityWindow.cpp | 0 src/imgui/EntityWindow.h | 0 src/imgui/GeneralInfoWindow.cpp | 58 ++++++++++++++++ src/imgui/GeneralInfoWindow.h | 40 +++++++++++ src/imgui/Handler.cpp | 42 ++++++++++++ src/imgui/Handler.h | 26 +++++++ src/imgui/Window.cpp | 20 ++++++ src/imgui/Window.h | 15 +++++ 42 files changed, 598 insertions(+), 285 deletions(-) create mode 100644 .clang-tidy create mode 100644 src/GLBucket.cpp create mode 100644 src/GLBucket.h create mode 100644 src/imgui/EntityWindow.cpp create mode 100644 src/imgui/EntityWindow.h create mode 100644 src/imgui/GeneralInfoWindow.cpp create mode 100644 src/imgui/GeneralInfoWindow.h create mode 100644 src/imgui/Handler.cpp create mode 100644 src/imgui/Handler.h create mode 100644 src/imgui/Window.cpp create mode 100644 src/imgui/Window.h diff --git a/.clang-format b/.clang-format index 39418f3..68d2527 100644 --- a/.clang-format +++ b/.clang-format @@ -9,6 +9,5 @@ ColumnLimit: '120' IndentWidth: '4' Language: Cpp PointerAlignment: Right -SortIncludes: false ... diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..8c981d4 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,45 @@ +--- +Checks: 'clang-diagnostic-*,clang-analyzer-*' +WarningsAsErrors: '' +HeaderFilterRegex: '' +AnalyzeTemporaryDtors: false +FormatStyle: none +CheckOptions: + - key: llvm-else-after-return.WarnOnConditionVariables + value: '0' + - key: modernize-loop-convert.MinConfidence + value: reasonable + - key: modernize-replace-auto-ptr.IncludeStyle + value: llvm + - key: cert-str34-c.DiagnoseSignedUnsignedCharComparisons + value: '0' + - key: google-readability-namespace-comments.ShortNamespaceLines + value: '10' + - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField + value: '0' + - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: '1' + - key: cert-dcl16-c.NewSuffixes + value: 'L;LL;LU;LLU' + - key: google-readability-braces-around-statements.ShortStatementLines + value: '1' + - key: modernize-pass-by-value.IncludeStyle + value: llvm + - key: google-readability-namespace-comments.SpacesBeforeComments + value: '2' + - key: modernize-loop-convert.MaxCopySize + value: '16' + - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors + value: '1' + - key: modernize-use-nullptr.NullMacros + value: 'NULL' + - key: llvm-qualified-auto.AddConstToQualified + value: '0' + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: llvm-else-after-return.WarnOnUnfixable + value: '0' + - key: google-readability-function-size.StatementThreshold + value: '800' +... + diff --git a/CMakeLists.txt b/CMakeLists.txt index 3df6f1d..8c676a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 3.10) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + project(Fall-Fever) if(WIN32) diff --git a/data/lights.json b/data/lights.json index cf5b8d7..f3d9d46 100644 --- a/data/lights.json +++ b/data/lights.json @@ -1,14 +1,30 @@ { "directionalLight": { - "intensity": 0.5, - "direction": [-0.2, -1.0, -0.3], - "color": [1.0, 1.0, 1.0] + "intensity": 0.25, + "direction": [ + -0.2, + -1.0, + -0.3 + ], + "color": [ + 1.0, + 1.0, + 1.0 + ] }, "pointLights": [ { "intensity": 7.5, - "position": [0.0, 1.0, 0.0], - "color": [1.0, 1.0, 1.0] + "position": [ + 0.0, + 1.0, + 0.0 + ], + "color": [ + 1.0, + 1.0, + 1.0 + ] } ] -} +} \ No newline at end of file diff --git a/data/models.json b/data/models.json index 60fd95f..3324492 100644 --- a/data/models.json +++ b/data/models.json @@ -26,16 +26,32 @@ "unique_name": "backpack", "model": "backpack", "shaderProgram": "defaultProgram", - "position": [0.0, 1.0, 0.0], - "rotation": [0.0, 0.0, 0.0], + "position": [ + 0.0, + 1.0, + 0.0 + ], + "rotation": [ + 0.0, + 0.0, + 0.0 + ], "scale": 0.6 }, { "unique_name": "container", "model": "container", "shaderProgram": "defaultProgram", - "position": [10.0, 1.0, 0.0], - "rotation": [45.0, 45.0, 45.0] + "position": [ + 10.0, + 1.0, + 0.0 + ], + "rotation": [ + 45.0, + 45.0, + 45.0 + ] }, { "unique_name": "ground", @@ -48,7 +64,7 @@ "shaderProgram": "lightProgram" } ], - "textures" : [ + "textures": [ { "unique_name": "fallback_normal", "path": "data/res/models/tex/fallback_normal.png" @@ -57,4 +73,4 @@ "skybox": { "texturePath": "data/res/textures/skybox/" } -} +} \ No newline at end of file diff --git a/data/screens.json b/data/screens.json index 4535d31..91a5cee 100644 --- a/data/screens.json +++ b/data/screens.json @@ -2,32 +2,56 @@ "loadingScreen": [ { "unique_name": "background", - "position": [0.0, 0.0], - "dimensions": [1.0, 1.0], + "position": [ + 0.0, + 0.0 + ], + "dimensions": [ + 1.0, + 1.0 + ], "texture": "data/res/textures/loading.png" } ], "mainMenuScreen": [ { "unique_name": "play", - "position": [0.4, 0.5], - "dimensions": [0.25, 0.1], + "position": [ + 0.4, + 0.5 + ], + "dimensions": [ + 0.25, + 0.1 + ], "texture": "data/res/textures/play.png", "callbackId": 1 }, { "unique_name": "exit", - "position": [0.4, 0.2], - "dimensions": [0.25, 0.10], + "position": [ + 0.4, + 0.2 + ], + "dimensions": [ + 0.25, + 0.10 + ], "texture": "data/res/textures/exit.png", "callbackId": 2 }, { "unique_name": "background", - "position": [0.0, 0.0], - "dimensions": [1.0, 1.0], + "position": [ + 0.0, + 0.0 + ], + "dimensions": [ + 1.0, + 1.0 + ], "texture": "data/res/textures/mainMenu.png", "callbackId": 0 } ] -} +} \ No newline at end of file diff --git a/data/shaderPrograms.json b/data/shaderPrograms.json index e5c62f2..5faec74 100644 --- a/data/shaderPrograms.json +++ b/data/shaderPrograms.json @@ -37,4 +37,4 @@ "geometryPath": "data/shaders/pointShadowDepth.geom" } ] -} +} \ No newline at end of file diff --git a/data/shaders/menu.frag b/data/shaders/menu.frag index 0e1eaa4..08b96d9 100644 --- a/data/shaders/menu.frag +++ b/data/shaders/menu.frag @@ -4,7 +4,8 @@ layout(location = 0) out vec4 f_color; in vec2 v_texCoord; -struct Material { +struct Material +{ sampler2D texture_diffuse0; }; uniform Material u_material; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5dc78eb..f7f9791 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,6 +18,11 @@ add_executable(Fall-Fever Menu.cpp JsonParser.cpp Helper.cpp + GLBucket.cpp + imgui/EntityWindow.cpp + imgui/GeneralInfoWindow.cpp + imgui/Handler.cpp + imgui/Window.cpp ) target_link_libraries( diff --git a/src/Controller.cpp b/src/Controller.cpp index f777d2f..9f4f331 100644 --- a/src/Controller.cpp +++ b/src/Controller.cpp @@ -9,32 +9,29 @@ #include #ifdef _DEBUG -#include -#include -#include +#include "imgui/GeneralInfoWindow.h" +#include "imgui/Handler.h" #endif +#include "Camera.h" #include "Controller.h" #include "Entity.h" +#include "EventHandler.h" #include "Helper.h" #include "JsonParser.h" +#include "Light.h" +#include "Menu.h" #include "Model.h" #include "Screen.h" +#include "ShaderProgram.h" #include "Texture.h" #include "VertexArray.h" #include "Widget.h" -#include "World.h" -#include "Menu.h" -#include "Camera.h" -#include "Light.h" #include "Window.h" -#include "Texture.h" -#include "ShaderProgram.h" -#include "EventHandler.h" +#include "World.h" -Controller::Controller() +Controller::Controller() : m_gameWindow(std::unique_ptr(new Window)) { - m_gameWindow = new Window(); m_gameEventHandler = new EventHandler(m_gameWindow->getGLFWwindow()); m_camera = new Camera(90.0f, m_gameWindow->getWindowAspectRatio()); @@ -58,27 +55,12 @@ Controller::Controller() m_world = new World(m_shaderPrograms); #ifdef _DEBUG - // Setup Dear ImGui context - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO &io = ImGui::GetIO(); - (void)io; - // Setup Platform/Renderer bindings - ImGui_ImplGlfw_InitForOpenGL(m_gameWindow->getGLFWwindow(), true); - ImGui_ImplOpenGL3_Init("#version 150"); - // Setup Dear ImGui style - ImGui::StyleColorsDark(); + m_imguiHandler = std::unique_ptr(new Imgui::Handler(m_gameWindow->getGLFWwindow())); #endif } Controller::~Controller() { -#ifdef _DEBUG - ImGui_ImplOpenGL3_Shutdown(); - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); -#endif - for (auto it = m_shaderPrograms.begin(); it != m_shaderPrograms.end(); it++) { delete *it; } @@ -88,7 +70,6 @@ Controller::~Controller() delete m_menu; delete m_postProcessFrameBuffer; delete m_gameEventHandler; - delete m_gameWindow; } void Controller::run() @@ -103,6 +84,17 @@ void Controller::run() m_camera->translate(glm::vec3(0.0f, 1.5f, 5.0f)); + // imgui stuff + bool rotateLightSource = false, rotateEntity = false, drawShadows = false; + glm::vec3 lightColor = glm::vec3(1.f); + float intensity = 7.5f; +#ifdef _DEBUG + std::shared_ptr imguiWindow = std::make_shared( + this, m_world, getShaderProgramByName("postProcessingProgram"), &rotateEntity, &drawShadows, &rotateLightSource, + &lightColor, &m_exposure, &intensity); + m_imguiHandler->addImguiWindow(imguiWindow); +#endif + // This is the game loop while (!glfwWindowShouldClose(m_gameWindow->getGLFWwindow())) { @@ -111,7 +103,6 @@ void Controller::run() // --- Update game --- - static bool rotateLightSource = false, rotateEntity = false; if (rotateLightSource) { float radius = 4.0; glm::vec3 newPos = glm::vec3(-cos(glfwGetTime() * 0.5), 0.5f, sin(glfwGetTime() * 0.5)) * radius; @@ -120,8 +111,7 @@ void Controller::run() if (rotateEntity) { m_world->getEntityById(0)->rotate(glm::vec3(0.0f, 1.0f, 0.0f), -0.2f * m_deltaTime); } - static glm::vec3 lightColor = glm::vec3(1.f); - static float intensity = 7.5f; + m_world->updatePointLight(0, true, m_world->getEntityByName("light")->getPosition(), lightColor, intensity); m_world->updateDirectionalLight(true, m_world->getDirectionalLight()->getDirection(), lightColor); getShaderProgramByName("lightProgram")->bind(); @@ -131,7 +121,6 @@ void Controller::run() // --- Render and buffer swap --- // Calc shadows - static bool drawShadows = false; static bool firstRun = true; getShaderProgramByName("defaultProgram")->bind(); getShaderProgramByName("defaultProgram")->setUniform("b_drawShadows", (int)drawShadows); @@ -161,8 +150,7 @@ void Controller::run() m_postProcessFrameBuffer->render(); #ifdef _DEBUG - renderImGui(m_world, &lightColor, &rotateEntity, &rotateLightSource, - getShaderProgramByName("postProcessingProgram"), &intensity, &drawShadows); + m_imguiHandler->renderWindows(); #endif } glfwSwapBuffers(m_gameWindow->getGLFWwindow()); @@ -186,7 +174,7 @@ void Controller::run() // Handle widget pressed event only when a screen is currently active if (m_menu->getActiveScreen()) - m_menu->handleMouseButtonActionMap(m_gameEventHandler->getMouseButtonActionMap(), m_gameWindow); + m_menu->handleMouseButtonActionMap(m_gameEventHandler->getMouseButtonActionMap(), m_gameWindow.get()); } } @@ -248,59 +236,3 @@ void Controller::setMaxFps(uint16_t fps) { m_MAX_FPS = fps; } - -#ifdef _DEBUG -void Controller::renderImGui(World *world, glm::vec3 *lightColor, bool *rotateEntity, bool *rotateLightSource, - ShaderProgram *postProcessingProgram, float *intensity, bool *drawShadows) -{ - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - - // render your GUI - ImGui::Begin("Debug Utils"); - ImGui::Text("Object"); - static float rotation = 0.0; - ImGui::SliderFloat("Rotation", &rotation, 0, 2 * M_PI); - static float translation[] = {0.0f, 1.0f, 0.0f}; - ImGui::SliderFloat3("Position", translation, -4.0, 4.0); - static float scale = 0.6f; - ImGui::SliderFloat("Scale", &scale, 0.02, 2.0); - ImGui::Checkbox("Rotate Object", rotateEntity); - - Entity *mainObject = world->getEntityById(0); - mainObject->setPosition(glm::vec3(translation[0], translation[1], translation[2])); - if (!*rotateEntity) { - mainObject->setRotation(glm::vec3(0.f, 1.0f, 0.f), rotation); - } - mainObject->setScale(scale); - - // color picker - ImGui::Text("\nLight Source"); - - updateExposure(postProcessingProgram); - - static float color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - - ImGui::SliderFloat("Intensity", intensity, 0, 250.f); - - ImGui::ColorEdit3("Color", color); - lightColor->x = color[0]; - lightColor->y = color[1]; - lightColor->z = color[2]; - - ImGui::Text("\nMiscellaneous"); - ImGui::SliderFloat("Exposure", &m_exposure, 0, 5.0f); - - ImGui::Checkbox("Draw Shadows", drawShadows); - ImGui::Checkbox("Rotate Lightsource", rotateLightSource); - - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0 / ImGui::GetIO().Framerate, - ImGui::GetIO().Framerate); - - ImGui::End(); - - ImGui::Render(); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); -} -#endif diff --git a/src/Controller.h b/src/Controller.h index 431437f..988471b 100644 --- a/src/Controller.h +++ b/src/Controller.h @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include class ShaderProgram; class Window; @@ -12,6 +12,10 @@ class Camera; class Menu; class FrameBuffer; +namespace Imgui { +class Handler; +} + class Controller { public: @@ -24,18 +28,19 @@ public: static ShaderProgram *getShaderProgramByName(std::vector shaderPrograms, const std::string &name); + void updateExposure(ShaderProgram *shaderProgram); + private: void limit_framerate(); void updateWindowDimensions(); - void updateExposure(ShaderProgram *shaderProgram); ShaderProgram *getShaderProgramByName(const std::string &name); void renderImGui(World *world, glm::vec3 *lightColor, bool *rotateEntity, bool *rotateLightSource, ShaderProgram *postProcessingProgram, float *intensity, bool *drawShadows); - Window *m_gameWindow; + std::unique_ptr m_gameWindow; EventHandler *m_gameEventHandler; World *m_world; @@ -45,6 +50,10 @@ private: std::vector m_shaderPrograms; +#ifdef _DEBUG + std::unique_ptr m_imguiHandler; +#endif + FrameBuffer *m_postProcessFrameBuffer; uint16_t m_MAX_FPS = 60; diff --git a/src/Entity.cpp b/src/Entity.cpp index 3202958..ac6d88d 100644 --- a/src/Entity.cpp +++ b/src/Entity.cpp @@ -1,8 +1,8 @@ #include "Entity.h" -#include "VertexArray.h" #include "Mesh.h" -#include "ShaderProgram.h" #include "Model.h" +#include "ShaderProgram.h" +#include "VertexArray.h" #include #include @@ -11,8 +11,7 @@ uint32_t Entity::s_idCounter = 0; Entity::Entity(const std::string &name, Model *model, ShaderProgram *shaderProgram) : m_uniqueName(name), m_model(model), m_shaderProgram(shaderProgram), m_id(s_idCounter++) -{ -} +{} void Entity::draw(glm::mat4 viewProjMatrix, glm::vec3 viewPosition) { diff --git a/src/FrameBuffer.cpp b/src/FrameBuffer.cpp index 773f25a..39b1530 100644 --- a/src/FrameBuffer.cpp +++ b/src/FrameBuffer.cpp @@ -142,8 +142,8 @@ DepthMap::DepthMap(DepthMapType type, int RESOLUTION) DepthMap::~DepthMap() { - if (m_cubeMap) - delete m_cubeMap; + // if (m_cubeMap) + // delete m_cubeMap; } void DepthMap::bind() diff --git a/src/GLBucket.cpp b/src/GLBucket.cpp new file mode 100644 index 0000000..24cb33e --- /dev/null +++ b/src/GLBucket.cpp @@ -0,0 +1,16 @@ +#include "GLBucket.h" + +#include + +std::unique_ptr GLBucket::s_instance = std::unique_ptr(new GLBucket); + +GLBucket &GLBucket::instance() +{ + return *s_instance.get(); +} + +void GLBucket::runGlCall(const std::function &f) +{ + std::lock_guard lock(m_mutex); + f(); +} diff --git a/src/GLBucket.h b/src/GLBucket.h new file mode 100644 index 0000000..3e92051 --- /dev/null +++ b/src/GLBucket.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +#include + +class GLBucket +{ +public: + static GLBucket &instance(); + + void runGlCall(const std::function &f); + +private: + GLBucket() = default; + + std::mutex m_mutex; + static std::unique_ptr s_instance; +}; \ No newline at end of file diff --git a/src/Helper.h b/src/Helper.h index 72ea70b..e81241d 100644 --- a/src/Helper.h +++ b/src/Helper.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include #include diff --git a/src/JsonParser.cpp b/src/JsonParser.cpp index 6e6689e..5e9a921 100644 --- a/src/JsonParser.cpp +++ b/src/JsonParser.cpp @@ -8,7 +8,6 @@ #include "Widget.h" #include -#include #include JsonParser::JsonParser(const std::string &path) @@ -33,46 +32,20 @@ JsonParser::JsonParser(const std::string &path) JsonParser::~JsonParser() {} -std::vector JsonParser::getModels() +std::vector JsonParser::getModelPrototypes() const { - std::vector temp_models; - const Json::Value modelsJson = m_root["models"]; - struct ModelSkeleton - { - std::string model_name; - std::string model_path; - }; - - std::vector model_skeletons; + std::vector modelPrototypes; for (unsigned int index = 0; index < modelsJson.size(); index++) { - std::string model_name = modelsJson[index]["unique_name"].asString(); - std::string model_path = modelsJson[index]["path"].asString(); - ModelSkeleton model_skeleton = {model_name, model_path}; - model_skeletons.push_back(model_skeleton); + std::string modelName = modelsJson[index]["unique_name"].asString(); + std::string modelPath = modelsJson[index]["path"].asString(); + Model::Prototype prototype{modelName, modelPath}; + modelPrototypes.push_back(prototype); } - std::vector> futures; - std::mutex mutex; - - auto *temp_models_ptr = &temp_models; - for (const auto &model_skeleton : model_skeletons) { - auto loadModel = [&]() { - Model *current_model = new Model(model_skeleton.model_name, model_skeleton.model_path); - if (current_model) { - std::lock_guard lock(mutex); - temp_models_ptr->push_back(current_model); - std::cout << "Loaded Model \"" << model_skeleton.model_name << "\" from \"" << model_skeleton.model_path - << "\"" << std::endl; - } - }; - - futures.push_back(std::async(std::launch::async, loadModel)); - } - - return temp_models; + return modelPrototypes; } std::vector JsonParser::getEntities(std::vector &models, std::vector shaderPrograms) @@ -275,7 +248,9 @@ std::vector JsonParser::getWidgetsFromScreen(const Json::Value &screen const Json::Value currentWidgetPosition = currentWidgetJson["position"]; const Json::Value currentWidgetDimensions = currentWidgetJson["dimensions"]; std::string name = currentWidgetJson["unique_name"].asString(); - Texture *currentWidgetTexture = new Texture(currentWidgetTextureJson.asString().c_str(), TextureType::Diffuse); + Texture::Prototype texturePrototype{currentWidgetTextureJson.asString(), TextureType::Diffuse}; + Texture *currentWidgetTexture = new Texture(texturePrototype); + currentWidgetTexture->initializeOnGPU(); Widget *currentWidget = new Widget(name, currentWidgetTexture, currentWidgetPosition[0].asFloat(), currentWidgetPosition[1].asFloat(), currentWidgetDimensions[0].asFloat(), diff --git a/src/JsonParser.h b/src/JsonParser.h index 8696a97..c78ece0 100644 --- a/src/JsonParser.h +++ b/src/JsonParser.h @@ -1,10 +1,11 @@ #pragma once +#include "Model.h" + #include #include #include -class Model; class Entity; class Light; class Screen; @@ -19,7 +20,7 @@ public: JsonParser(const std::string &path); ~JsonParser(); - std::vector getModels(); + std::vector getModelPrototypes() const; std::vector getEntities(std::vector &models, std::vector shaderPrograms); std::vector getLights(ShaderProgram *shaderProgram); std::vector getScreens(ShaderProgram *menuProgram, FrameBuffer *framebuffer); diff --git a/src/Light.h b/src/Light.h index a10ad66..80d0e0b 100644 --- a/src/Light.h +++ b/src/Light.h @@ -43,7 +43,7 @@ class PointLight : public Light { public: PointLight(glm::vec3 position, glm::vec3 color, float intensity, ShaderProgram *shaderProgram); - ~PointLight() = default; + ~PointLight() override = default; void setPosition(glm::vec3 position); diff --git a/src/Menu.cpp b/src/Menu.cpp index 76b4868..ab5a15f 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -1,11 +1,11 @@ #include "Menu.h" +#include "FrameBuffer.h" #include "Helper.h" #include "JsonParser.h" -#include "ShaderProgram.h" -#include "FrameBuffer.h" #include "Screen.h" -#include "Window.h" +#include "ShaderProgram.h" #include "Widget.h" +#include "Window.h" #include "definitions/eventActions.h" #include diff --git a/src/Mesh.cpp b/src/Mesh.cpp index f992847..eb21de5 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -1,13 +1,25 @@ #include "Mesh.h" -#include "Texture.h" #include "ShaderProgram.h" +#include "Texture.h" +#include "VertexArray.h" Mesh::Mesh(std::vector vertices, std::vector indices, std::vector textures) - : m_numElements(indices.size()), m_textures(textures), - m_vertexArray(static_cast(vertices.data()), static_cast(indices.data()), vertices.size(), - indices.size()) + : m_numElements(indices.size()), m_textures(textures), m_preInitializationVertexData{vertices, indices} {} +void Mesh::initializeOnGPU() +{ + m_vertexArray = + new VertexArray(static_cast(m_preInitializationVertexData.vertices.data()), + static_cast(m_preInitializationVertexData.indices.data()), + m_preInitializationVertexData.vertices.size(), m_preInitializationVertexData.indices.size()); +} + +Mesh::~Mesh() +{ + delete m_vertexArray; +} + void Mesh::draw(ShaderProgram *shaderProgram) { uint8_t typeNumberCount[static_cast(TextureType::TEXTURE_TYPE_NUM_ITEMS)]{0}; @@ -24,9 +36,9 @@ void Mesh::draw(ShaderProgram *shaderProgram) } // Draw elements - m_vertexArray.bind(); + m_vertexArray->bind(); glDrawElements(GL_TRIANGLES, m_numElements, GL_UNSIGNED_INT, 0); - m_vertexArray.unbind(); + m_vertexArray->unbind(); // Unbind all textures for (auto it = m_textures.begin(); it != m_textures.end(); it++) { @@ -36,12 +48,12 @@ void Mesh::draw(ShaderProgram *shaderProgram) void Mesh::drawWithoutTextures() { - m_vertexArray.bind(); + m_vertexArray->bind(); glDrawElements(GL_TRIANGLES, m_numElements, GL_UNSIGNED_INT, 0); - m_vertexArray.unbind(); + m_vertexArray->unbind(); } VertexArray *Mesh::getVertexArray() { - return &m_vertexArray; + return m_vertexArray; } diff --git a/src/Mesh.h b/src/Mesh.h index 43e8348..97f4589 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -1,18 +1,20 @@ #pragma once #include "definitions/models.h" -#include "VertexArray.h" #include class ShaderProgram; class Texture; +class VertexArray; class Mesh { public: Mesh(std::vector vertices, std::vector indices, std::vector textures); - ~Mesh() = default; + ~Mesh(); + + void initializeOnGPU(); void draw(ShaderProgram *shaderProgram); void drawWithoutTextures(); @@ -20,10 +22,16 @@ public: VertexArray *getVertexArray(); private: - void setupMesh(); + struct PreInitializationVertexData + { + std::vector vertices; + std::vector indices; + } m_preInitializationVertexData; + + bool m_isInitialized = false; uint32_t m_numElements; std::vector m_textures; - VertexArray m_vertexArray; + VertexArray *m_vertexArray; }; diff --git a/src/Model.cpp b/src/Model.cpp index 255ce6f..3dffbc6 100644 --- a/src/Model.cpp +++ b/src/Model.cpp @@ -1,36 +1,46 @@ #include "Model.h" +#include "GLBucket.h" #include "Mesh.h" #include "ShaderProgram.h" #include "Texture.h" #include +#include #include uint32_t Model::s_idCounter = 0; -Model::Model(const std::string &modelName, const std::string &modelPath) : m_uniqueName(modelName) +Model::Model(const Prototype &prototype) : m_uniqueName(prototype.modelName), m_id(s_idCounter++) { - m_workingPath = modelPath.substr(0, modelPath.find_last_of('/')); + m_workingPath = prototype.modelPath.substr(0, prototype.modelPath.find_last_of('/')); - loadModel(modelPath); - m_id = s_idCounter++; + loadModel(prototype.modelPath); +} + +void Model::initializeOnGPU() +{ + if (m_isInitialized) + return; + + m_isInitialized = true; + + for (auto texture : m_textures) + texture->initializeOnGPU(); + + for (auto mesh : m_meshes) + mesh->initializeOnGPU(); } Model::~Model() { // Go through all loaded textures and delete them - for (auto it = m_loadedTextures.begin(); it != m_loadedTextures.end(); it++) { + for (auto it = m_textures.begin(); it != m_textures.end(); it++) { delete (*it); } } void Model::draw(ShaderProgram *shaderProgram) { - if (!m_modelPrepared) { - std::cout << "WARNING: Model not prepared! Unable to draw!" << std::endl; - return; - } - // Iterate through every mesh and call the draw function for (auto mesh : m_meshes) { mesh->draw(shaderProgram); @@ -39,11 +49,6 @@ void Model::draw(ShaderProgram *shaderProgram) void Model::drawWithoutTextures() { - if (!m_modelPrepared) { - std::cout << "WARNING: Model not prepared! Unable to draw!" << std::endl; - return; - } - // Iterate through every mesh and call the draw function for (auto mesh : m_meshes) { mesh->drawWithoutTextures(); @@ -83,14 +88,23 @@ void Model::loadModel(const std::string &pathToModel) textureSources.push_back(currentTextureSource); } - for (unsigned int i = 0; i < numTextures; i++) { - TexturePrototype texture_prototype; - std::string texturePath = m_workingPath + '/' + textureSources[i].c_str(); + // Maybe write a texture loader class in future, that handles all this. + { + std::vector> futures; + std::mutex mutex; - texture_prototype.texturePath = std::move(texturePath); - texture_prototype.textureType = textureTypes[i]; + for (unsigned int i = 0; i < numTextures; i++) { + std::string texturePath = m_workingPath + '/' + textureSources[i].c_str(); + Texture::Prototype texturePrototype{texturePath, textureTypes[i]}; + auto loadModel = [=, &mutex]() { + Texture *currentTex = new Texture(texturePrototype); - m_modelTexturePrototypes.push_back(texture_prototype); + std::lock_guard lock(mutex); + m_textures.push_back(currentTex); + }; + + futures.push_back(std::async(std::launch::async, loadModel)); + } } // When there is no normal map bound, please use fallback texture @@ -101,12 +115,10 @@ void Model::loadModel(const std::string &pathToModel) } if (!hasNormalMap) { - TexturePrototype texture_prototype; + Texture::Prototype texturePrototype{"data/res/models/tex/fallback_normal.png", TextureType::Normal}; + Texture *currentTex = new Texture(texturePrototype); - texture_prototype.texturePath = "data/res/models/tex/fallback_normal.png"; - texture_prototype.textureType = TextureType::Normal; - - m_modelTexturePrototypes.push_back(texture_prototype); + m_textures.push_back(currentTex); } // Here starts the first mesh @@ -114,9 +126,6 @@ void Model::loadModel(const std::string &pathToModel) input.read((char *)&numMeshes, sizeof(uint32_t)); for (unsigned int j = 0; j < numMeshes; j++) { - - MeshPrototype mesh_prototype; - uint32_t numMeshVertices, numMeshIndices, numMeshTextureIds; input.read((char *)&numMeshVertices, sizeof(uint32_t)); @@ -131,52 +140,35 @@ void Model::loadModel(const std::string &pathToModel) std::vector meshVertices; meshVertices.resize(numMeshVertices); input.read((char *)meshVertices.data(), vertexBlockSize); - mesh_prototype.meshVertices = std::move(meshVertices); std::vector meshIndices; meshIndices.resize(numMeshIndices); input.read((char *)meshIndices.data(), indexBlockSize); - mesh_prototype.meshIndices = std::move(meshIndices); + + std::vector meshTextureIds; + std::vector meshTextures; for (unsigned int i = 0; i < numMeshTextureIds; i++) { uint32_t currentTextureId; input.read((char *)¤tTextureId, sizeof(uint32_t)); - mesh_prototype.textureIds.push_back(currentTextureId); + meshTextureIds.push_back(currentTextureId); } if (!hasNormalMap) { // This will be the last texture - mesh_prototype.textureIds.push_back(numTextures); + meshTextureIds.push_back(numTextures); } - m_modelMeshPrototypes.push_back(std::move(mesh_prototype)); + for (auto textureId : meshTextureIds) { + meshTextures.push_back(m_textures[textureId]); + } + + m_meshes.push_back(new Mesh(std::move(meshVertices), std::move(meshIndices), std::move(meshTextures))); } input.close(); } -void Model::prepareModel() -{ - m_modelPrepared = true; - - // Create textures on GPU - for (auto &it : m_modelTexturePrototypes) { - Texture *newTex = new Texture(it.texturePath.c_str(), it.textureType); - m_loadedTextures.push_back(newTex); - } - - // Create meshes on GPU - for (const auto &it : m_modelMeshPrototypes) { - std::vector meshTextures; - for (const auto it2 : it.textureIds) { - meshTextures.push_back(m_loadedTextures[it2]); - } - - Mesh *currentMesh = new Mesh(std::move(it.meshVertices), std::move(it.meshIndices), meshTextures); - m_meshes.push_back(currentMesh); - } -} - Mesh *Model::getMesh(unsigned int index) { return m_meshes[index]; diff --git a/src/Model.h b/src/Model.h index 25b3914..47bc666 100644 --- a/src/Model.h +++ b/src/Model.h @@ -9,12 +9,6 @@ class ShaderProgram; class Mesh; class Texture; -struct TexturePrototype -{ - TextureType textureType; - std::string texturePath; -}; - struct MeshPrototype { std::vector textureIds; @@ -25,10 +19,16 @@ struct MeshPrototype class Model { public: - Model(const std::string &modelName, const std::string &pathToModel); + struct Prototype + { + std::string modelName; + std::string modelPath; + }; + + Model(const Prototype &prototype); ~Model(); - void prepareModel(); + void initializeOnGPU(); void draw(ShaderProgram *shaderProgram); void drawWithoutTextures(); @@ -39,16 +39,13 @@ public: private: void loadModel(const std::string &pathToModel); - std::vector m_meshes; - std::vector m_loadedTextures; + bool m_isInitialized = false; - std::vector m_modelTexturePrototypes; - std::vector m_modelMeshPrototypes; + std::vector m_meshes; + std::vector m_textures; std::string m_workingPath; - bool m_modelPrepared = false; - static uint32_t s_idCounter; uint32_t m_id; std::string m_uniqueName; diff --git a/src/Screen.cpp b/src/Screen.cpp index d9e0bc1..7f78456 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -1,10 +1,10 @@ #include "Screen.h" -#include "Menu.h" -#include "Widget.h" #include "FrameBuffer.h" +#include "Helper.h" +#include "Menu.h" #include "ShaderProgram.h" #include "Texture.h" -#include "Helper.h" +#include "Widget.h" uint32_t Screen::s_idCounter = 0; diff --git a/src/Screen.h b/src/Screen.h index 1701208..a2337fc 100644 --- a/src/Screen.h +++ b/src/Screen.h @@ -1,8 +1,8 @@ #pragma once #include -#include #include +#include class Menu; class Widget; diff --git a/src/Texture.cpp b/src/Texture.cpp index ef3561f..5afe3fd 100644 --- a/src/Texture.cpp +++ b/src/Texture.cpp @@ -2,13 +2,29 @@ #include "ShaderProgram.h" #include -#include -Texture::Texture(const std::string &texturePath, TextureType textureType) - : m_texturePath(texturePath), m_textureType(textureType) +Texture::Texture(const Prototype &prototype) + : m_texturePath(prototype.texturePath), m_textureType(prototype.textureType) { stbi_set_flip_vertically_on_load(1); - auto *textureBuffer = stbi_load(texturePath.c_str(), &m_textureWidth, &m_textureHeight, &m_numComponents, 0); + m_textureBuffer = stbi_load(m_texturePath.c_str(), &m_textureWidth, &m_textureHeight, &m_numComponents, 0); + if (!m_textureBuffer) { + std::cout << "[Warning] Texture " << m_texturePath << " not found!" << std::endl; + return; + } +} + +Texture::~Texture() +{ + glDeleteTextures(1, &m_textureId); +} + +void Texture::initializeOnGPU() +{ + if (m_isInitialized) + return; + + m_isInitialized = true; GLenum internalFormat; GLenum dataFormat; @@ -16,10 +32,10 @@ Texture::Texture(const std::string &texturePath, TextureType textureType) internalFormat = GL_RED; dataFormat = GL_RED; } else if (m_numComponents == 3) { - internalFormat = (textureType == TextureType::Diffuse) ? GL_SRGB8 : GL_RGB8; + internalFormat = (m_textureType == TextureType::Diffuse) ? GL_SRGB8 : GL_RGB8; dataFormat = GL_RGB; } else if (m_numComponents == 4) { - internalFormat = (textureType == TextureType::Diffuse) ? GL_SRGB8_ALPHA8 : GL_RGBA8; + internalFormat = (m_textureType == TextureType::Diffuse) ? GL_SRGB8_ALPHA8 : GL_RGBA8; dataFormat = GL_RGBA; } @@ -34,22 +50,13 @@ Texture::Texture(const std::string &texturePath, TextureType textureType) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - if (!textureBuffer) { - std::cout << "[Warning] Texture " << texturePath << " not found!" << std::endl; - return; - } - glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_textureWidth, m_textureHeight, 0, dataFormat, GL_UNSIGNED_BYTE, - textureBuffer); + m_textureBuffer); glGenerateMipmap(GL_TEXTURE_2D); - stbi_image_free(textureBuffer); glBindTexture(GL_TEXTURE_2D, 0); -} -Texture::~Texture() -{ - glDeleteTextures(1, &m_textureId); + stbi_image_free(m_textureBuffer); } void Texture::bind(uint8_t textureUnit, ShaderProgram *shaderProgram, uint8_t textureTypeNum) @@ -176,7 +183,7 @@ CubeMap::CubeMap(int RESOLUTION) : m_textureWidth(RESOLUTION), m_textureHeight(R CubeMap::~CubeMap() { - glDeleteTextures(1, &m_textureId); + // glDeleteTextures(1, &m_textureId); } void CubeMap::bind(ShaderProgram *shaderProgram) diff --git a/src/Texture.h b/src/Texture.h index ab8e514..8c2b909 100644 --- a/src/Texture.h +++ b/src/Texture.h @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -24,9 +25,17 @@ enum cubeMapFaces class Texture { public: - Texture(const std::string &texturePath, TextureType textureType); + struct Prototype + { + std::string texturePath; + TextureType textureType; + }; + + Texture(const Prototype &prototype); ~Texture(); + void initializeOnGPU(); + void bind(uint8_t textureUnit, ShaderProgram *shaderProgram, uint8_t textureTypeNum); void unbind(); @@ -35,8 +44,12 @@ public: GLuint getTextureId(); private: + bool m_isInitialized = false; + std::string m_texturePath; + stbi_uc *m_textureBuffer; + int32_t m_textureWidth; int32_t m_textureHeight; int32_t m_numComponents; diff --git a/src/VertexArray.cpp b/src/VertexArray.cpp index 049e018..d0d8eac 100644 --- a/src/VertexArray.cpp +++ b/src/VertexArray.cpp @@ -1,4 +1,5 @@ #include "VertexArray.h" +#include "GLBucket.h" #include "definitions/models.h" #include diff --git a/src/Widget.cpp b/src/Widget.cpp index feae8e7..150c329 100644 --- a/src/Widget.cpp +++ b/src/Widget.cpp @@ -2,8 +2,8 @@ #include "Menu.h" #include "Mesh.h" #include "ShaderProgram.h" -#include "Window.h" #include "VertexArray.h" +#include "Window.h" #include @@ -34,6 +34,7 @@ Widget::Widget(std::string &name, Texture *texture, float p_x, float p_y, float m_widgetVertices = VertexArray::createVertices(widgetVerticesData, 12, widgetTextureCoordinates); m_widgetIndices.assign(widgetIndicesData, widgetIndicesData + 6); m_widgetMesh = new Mesh(m_widgetVertices, m_widgetIndices, m_widgetTextures); + m_widgetMesh->initializeOnGPU(); } Widget::~Widget() diff --git a/src/Window.cpp b/src/Window.cpp index 03ba40f..0cd11b5 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -3,7 +3,6 @@ #include "ShaderProgram.h" #include "definitions/window.h" -#include #include #include diff --git a/src/Window.h b/src/Window.h index 4d13aa4..e2dc2ee 100644 --- a/src/Window.h +++ b/src/Window.h @@ -2,6 +2,8 @@ #include "definitions/eventActions.h" +#include + class GLFWwindow; class Window diff --git a/src/World.cpp b/src/World.cpp index 762295a..b4a82e4 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1,14 +1,16 @@ #include "World.h" -#include "Entity.h" -#include "Controller.h" -#include "Model.h" -#include "Light.h" -#include "JsonParser.h" #include "Camera.h" -#include "Texture.h" +#include "Controller.h" +#include "Entity.h" +#include "JsonParser.h" +#include "Light.h" +#include "Model.h" #include "ShaderProgram.h" +#include "Texture.h" +#include #include +#include World::World(std::vector shaderPrograms) : m_shaderProgram(Controller::getShaderProgramByName(shaderPrograms, "defaultProgram")), @@ -26,12 +28,31 @@ World::World(std::vector shaderPrograms) m_shaderProgram->unbind(); JsonParser modelParser("data/models.json"); - m_models = modelParser.getModels(); + std::vector modelPrototypes = modelParser.getModelPrototypes(); - for (const auto &it : m_models) { - it->prepareModel(); + { + std::vector> futures; + std::mutex mutex; + + for (auto &prototype : modelPrototypes) { + + auto loadModel = [=, &mutex]() { + Model *current_model = new Model(prototype); + + std::cout << "Loaded Model \"" << prototype.modelName << "\" from \"" << prototype.modelPath << "\"" + << std::endl; + + std::lock_guard lock(mutex); + m_models.push_back(current_model); + }; + + futures.push_back(std::async(std::launch::async, loadModel)); + } } + for (auto &model : m_models) + model->initializeOnGPU(); + m_entities = modelParser.getEntities(m_models, shaderPrograms); m_skybox = modelParser.getSkybox(getModelByName("cube"), Controller::getShaderProgramByName(shaderPrograms, "skyboxProgram")); diff --git a/src/World.h b/src/World.h index 8c700a2..a1d7693 100644 --- a/src/World.h +++ b/src/World.h @@ -5,8 +5,8 @@ #include #include -#include #include +#include class Camera; class Entity; diff --git a/src/imgui/EntityWindow.cpp b/src/imgui/EntityWindow.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/imgui/EntityWindow.h b/src/imgui/EntityWindow.h new file mode 100644 index 0000000..e69de29 diff --git a/src/imgui/GeneralInfoWindow.cpp b/src/imgui/GeneralInfoWindow.cpp new file mode 100644 index 0000000..15c3221 --- /dev/null +++ b/src/imgui/GeneralInfoWindow.cpp @@ -0,0 +1,58 @@ +#include "GeneralInfoWindow.h" +#include "../Controller.h" +#include "../Entity.h" +#include "../ShaderProgram.h" +#include "../World.h" + +#include +#include + +Imgui::GeneralInfoWindow::GeneralInfoWindow(Controller *controller, World *world, ShaderProgram *postProcessingProgram, + bool *rotateEntity, bool *drawShadows, bool *rotateLightSource, + glm::vec3 *lightColor, float *exposure, float *intensity) + : m_controller(controller), m_world(world), m_postProcessingProgram(postProcessingProgram), + m_rotateEntity(rotateEntity), m_drawShadows(drawShadows), m_rotateLightSource(rotateLightSource), + m_lightColor(lightColor), m_exposure(exposure), m_intensity(intensity) +{} + +void Imgui::GeneralInfoWindow::addWidgets() +{ + ImGui::Begin("Debug Utils"); + ImGui::Text("Object"); + + ImGui::SliderFloat("Rotation", &m_rotation, 0, 2 * M_PI); + ImGui::SliderFloat3("Position", m_translation, -4.0, 4.0); + ImGui::SliderFloat("Scale", &m_scale, 0.02, 2.0); + + ImGui::Checkbox("Rotate Object", m_rotateEntity); + + Entity *mainObject = m_world->getEntityById(0); + mainObject->setPosition(glm::vec3(m_translation[0], m_translation[1], m_translation[2])); + if (!*m_rotateEntity) { + mainObject->setRotation(glm::vec3(0.f, 1.0f, 0.f), m_rotation); + } + mainObject->setScale(m_scale); + + // color picker + ImGui::Text("\nLight Source"); + + m_controller->updateExposure(m_postProcessingProgram); + + ImGui::SliderFloat("Intensity", m_intensity, 0, 250.f); + + ImGui::ColorEdit3("Color", m_color); + m_lightColor->x = m_color[0]; + m_lightColor->y = m_color[1]; + m_lightColor->z = m_color[2]; + + ImGui::Text("\nMiscellaneous"); + ImGui::SliderFloat("Exposure", m_exposure, 0, 5.0f); + + ImGui::Checkbox("Draw Shadows", m_drawShadows); + ImGui::Checkbox("Rotate Lightsource", m_rotateLightSource); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0 / ImGui::GetIO().Framerate, + ImGui::GetIO().Framerate); + + ImGui::End(); +} \ No newline at end of file diff --git a/src/imgui/GeneralInfoWindow.h b/src/imgui/GeneralInfoWindow.h new file mode 100644 index 0000000..53bc463 --- /dev/null +++ b/src/imgui/GeneralInfoWindow.h @@ -0,0 +1,40 @@ +#pragma once + +#include "Window.h" + +#include + +class World; +class ShaderProgram; +class Controller; + +namespace Imgui { + +class GeneralInfoWindow : public Window +{ +public: + GeneralInfoWindow(Controller *controller, World *world, ShaderProgram *postProcessingProgram, bool *rotateEntity, + bool *drawShadows, bool *rotateLightSource, glm::vec3 *lightColor, float *exposure, + float *intensity); + +private: + void addWidgets() override; + + Controller *m_controller; + World *m_world; + ShaderProgram *m_postProcessingProgram; + + bool *m_rotateEntity; + bool *m_drawShadows; + bool *m_rotateLightSource; + + float m_rotation = 0.0f; + float m_translation[3] = {0.0f, 1.0f, 0.0f}; + float m_scale = 0.6f; + float m_color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + glm::vec3 *m_lightColor; + float *m_exposure; + float *m_intensity; +}; + +}; // namespace Imgui diff --git a/src/imgui/Handler.cpp b/src/imgui/Handler.cpp new file mode 100644 index 0000000..12babc8 --- /dev/null +++ b/src/imgui/Handler.cpp @@ -0,0 +1,42 @@ +#include "Handler.h" +#include "Window.h" + +#include +#include +#include +#include + +Imgui::Handler::Handler(GLFWwindow *window) : m_GLFWwindow(window) +{ + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + + ImGui::CreateContext(); + + ImGuiIO &io = ImGui::GetIO(); + // io.IniFilename = nullptr; + + // Setup Platform/Renderer bindings + ImGui_ImplGlfw_InitForOpenGL(m_GLFWwindow, true); + ImGui_ImplOpenGL3_Init("#version 150"); + // Setup Dear ImGui style + ImGui::StyleColorsDark(); +} + +Imgui::Handler::~Handler() +{ + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); +} + +void Imgui::Handler::addImguiWindow(std::shared_ptr window) +{ + m_windows.push_back(window); +} + +void Imgui::Handler::renderWindows() +{ + for (auto window : m_windows) + window->render(); +} \ No newline at end of file diff --git a/src/imgui/Handler.h b/src/imgui/Handler.h new file mode 100644 index 0000000..f58f022 --- /dev/null +++ b/src/imgui/Handler.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +class GLFWwindow; + +namespace Imgui { + +class Window; + +class Handler +{ +public: + Handler(GLFWwindow *window); + ~Handler(); + + void addImguiWindow(std::shared_ptr window); + void renderWindows(); + +private: + std::vector> m_windows; + GLFWwindow *m_GLFWwindow; +}; + +} // namespace Imgui \ No newline at end of file diff --git a/src/imgui/Window.cpp b/src/imgui/Window.cpp new file mode 100644 index 0000000..2ebc566 --- /dev/null +++ b/src/imgui/Window.cpp @@ -0,0 +1,20 @@ +#include "Window.h" + +#include +#include +#include + +Imgui::Window::Window() +{} + +void Imgui::Window::render() +{ + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + addWidgets(); + + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); +} \ No newline at end of file diff --git a/src/imgui/Window.h b/src/imgui/Window.h new file mode 100644 index 0000000..c8d1188 --- /dev/null +++ b/src/imgui/Window.h @@ -0,0 +1,15 @@ +#pragma once + +namespace Imgui { + +class Window +{ +public: + Window(); + void render(); + +protected: + virtual void addWidgets() = 0; +}; + +} // namespace Imgui