From 2f880981ac56d678d2b46e9b943c33ef4454d6b2 Mon Sep 17 00:00:00 2001 From: bailwillharr Date: Thu, 15 Dec 2022 15:54:11 +0000 Subject: [PATCH] Get ecs to a somewhat functional state --- CMakeLists.txt | 7 +- include/application.hpp | 8 +- include/components/mesh_renderer.hpp | 9 -- include/{ => ecs}/ecs_system.hpp | 4 +- include/ecs/mesh_renderer.hpp | 29 +++++++ include/resource_manager.hpp | 17 ++-- include/resources/texture.hpp | 22 +++++ include/scene.hpp | 16 +--- include/scene_manager.hpp | 8 +- include/texture.hpp | 25 ------ include/util/files.hpp | 1 + src/application.cpp | 40 +++++++++ src/resources/texture.cpp | 38 +++++++++ src/scene.cpp | 4 +- src/scene_manager.cpp | 3 +- src/texture.cpp | 122 --------------------------- src/util/files.cpp | 26 ++++++ test/src/game.cpp | 13 ++- 18 files changed, 198 insertions(+), 194 deletions(-) delete mode 100644 include/components/mesh_renderer.hpp rename include/{ => ecs}/ecs_system.hpp (80%) create mode 100644 include/ecs/mesh_renderer.hpp create mode 100644 include/resources/texture.hpp delete mode 100644 include/texture.hpp create mode 100644 src/resources/texture.cpp delete mode 100644 src/texture.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f1c9c5..f2d95c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ set(SRC_FILES "src/input_manager.cpp" "src/scene_manager.cpp" - "src/texture.cpp" + "src/resources/texture.cpp" "src/gfx_device_vulkan.cpp" @@ -38,13 +38,14 @@ set(INCLUDE_FILES "include/scene_manager.hpp" "include/resource_manager.hpp" - "include/texture.hpp" + "include/resources/texture.hpp" "include/gfx.hpp" "include/gfx_device.hpp" "include/scene.hpp" - "include/ecs_system.hpp" + "include/ecs/ecs_system.hpp" + "include/ecs/mesh_renderer.hpp" "include/util/files.hpp" ) diff --git a/include/application.hpp b/include/application.hpp index 8112bd7..9a8cc6f 100644 --- a/include/application.hpp +++ b/include/application.hpp @@ -1,6 +1,8 @@ #pragma once #include +#include +#include namespace engine { @@ -26,12 +28,16 @@ namespace engine { InputManager* inputManager() { return m_inputManager.get(); } SceneManager* sceneManager() { return m_sceneManager.get(); } + std::string getResourcePath(const std::string relativePath) { return (m_resourcesPath / relativePath).string(); } + private: std::unique_ptr m_window; std::unique_ptr m_gfx; std::unique_ptr m_inputManager; std::unique_ptr m_sceneManager; + std::filesystem::path m_resourcesPath; + }; -} \ No newline at end of file +} diff --git a/include/components/mesh_renderer.hpp b/include/components/mesh_renderer.hpp deleted file mode 100644 index cd92947..0000000 --- a/include/components/mesh_renderer.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -namespace engine::components { - - struct MeshRenderer { - int placeholder; - }; - -} diff --git a/include/ecs_system.hpp b/include/ecs/ecs_system.hpp similarity index 80% rename from include/ecs_system.hpp rename to include/ecs/ecs_system.hpp index d75d85e..4ad605a 100644 --- a/include/ecs_system.hpp +++ b/include/ecs/ecs_system.hpp @@ -3,10 +3,10 @@ #include #include -namespace engine::ecs { +namespace engine { template - class System { + class EcsSystem { public: std::map m_components{}; diff --git a/include/ecs/mesh_renderer.hpp b/include/ecs/mesh_renderer.hpp new file mode 100644 index 0000000..cb4a5ce --- /dev/null +++ b/include/ecs/mesh_renderer.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "ecs_system.hpp" + +#include "resources/texture.hpp" +#include "log.hpp" + +namespace engine::ecs { + + struct MeshRendererComponent { + int number; + const resources::Texture* texture; + }; + + class RendererSystem : public EcsSystem { + + public: + void onUpdate(float ts) override + { + for (const auto& [id, data] : m_components) { + DEBUG("rendering entity {}\tts={}", id, ts); + DEBUG(" with texture: {}, number = {}", (void*)data.texture, data.number); + } + } + }; + + + +} diff --git a/include/resource_manager.hpp b/include/resource_manager.hpp index 4c4f340..ec93e43 100644 --- a/include/resource_manager.hpp +++ b/include/resource_manager.hpp @@ -16,32 +16,27 @@ namespace engine { ResourceManager(const ResourceManager&) = delete; ResourceManager& operator=(const ResourceManager&) = delete; - std::shared_ptr add(const std::string& name, std::unique_ptr&& resource) + T* add(const std::string& name, std::unique_ptr&& resource) { if (m_resources.contains(name) == false) { - std::shared_ptr ptr = std::move(resource); - m_resources.emplace(name, ptr); + m_resources.emplace(name, std::move(resource)); } else { throw std::runtime_error("Cannot add a resource which already exists"); } - return m_resources.at(name).lock(); + return m_resources.at(name).get(); } - std::shared_ptr get(const std::string& name) + T* get(const std::string& name) { if (m_resources.contains(name)) { - std::weak_ptr resource = m_resources.at(name); - if (resource.expired() == false) { - return resource.lock(); - } + return m_resources.at(name).get(); } return {}; } private: - // weak ptrs are used to check a resource's use count. If the use count of a resource hits 0, the resource can safely be deleted. - std::unordered_map> m_resources{}; + std::unordered_map> m_resources{}; }; diff --git a/include/resources/texture.hpp b/include/resources/texture.hpp new file mode 100644 index 0000000..07c8a4b --- /dev/null +++ b/include/resources/texture.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "gfx_device.hpp" + +namespace engine::resources { + +class Texture { + +public: + Texture(GFXDevice* gfxDevice, const std::string& path); + ~Texture(); + Texture(const Texture&) = delete; + Texture& operator=(const Texture&) = delete; + + gfx::Texture* getHandle(); + +private: + GFXDevice* m_gfxDevice; + gfx::Texture* m_gpuTexture; +}; + +} diff --git a/include/scene.hpp b/include/scene.hpp index acbc1c7..a691121 100644 --- a/include/scene.hpp +++ b/include/scene.hpp @@ -1,7 +1,6 @@ #pragma once -#include "ecs_system.hpp" -#include "components/mesh_renderer.hpp" +#include "ecs/mesh_renderer.hpp" #include "log.hpp" @@ -9,17 +8,6 @@ namespace engine { - class RendererSystem : public ecs::System { - - public: - void onUpdate(float ts) override - { - for (const auto& [id, data] : m_components) { - DEBUG("rendering entity {}\tts={}", id, ts); - } - } - }; - class Scene { public: @@ -35,7 +23,7 @@ namespace engine { return m_nextEntityID++; } - std::unique_ptr m_renderSystem; + std::unique_ptr m_renderSystem; private: uint32_t m_nextEntityID = 1000; diff --git a/include/scene_manager.hpp b/include/scene_manager.hpp index 31d2386..ec0542c 100644 --- a/include/scene_manager.hpp +++ b/include/scene_manager.hpp @@ -8,6 +8,9 @@ namespace engine { class Scene; // "scene.hpp" + namespace resources { + class Texture; + } class SceneManager { @@ -21,11 +24,14 @@ namespace engine { void updateActiveScene(float ts); + /* getters */ + ResourceManager* getTextureManager() { return m_textureManager.get(); } + private: std::vector> m_scenes; int m_activeSceneIndex = -1; -// const std::unique_ptr> m_textureManager; + std::unique_ptr> m_textureManager; }; diff --git a/include/texture.hpp b/include/texture.hpp deleted file mode 100644 index 9d739db..0000000 --- a/include/texture.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#if 0 -#pragma once - -#include "engine_api.h" - -#include "resource.hpp" - -#include "gfx_device.hpp" - -namespace engine::resources { - -class ENGINE_API Texture : public Resource { - -public: - Texture(const std::filesystem::path& resPath); - ~Texture() override; - - gfx::Texture* getHandle(); - -private: - gfx::Texture* m_gpuTexture; -}; - -} -#endif \ No newline at end of file diff --git a/include/util/files.hpp b/include/util/files.hpp index ed24609..4745841 100644 --- a/include/util/files.hpp +++ b/include/util/files.hpp @@ -8,5 +8,6 @@ namespace engine::util { std::unique_ptr> readTextFile(const std::string& path); std::unique_ptr> readBinaryFile(const std::string& path); + std::unique_ptr> readImageFile(const std::string& path, int *width, int *height); } diff --git a/src/application.cpp b/src/application.cpp index ef6c73c..37a25ac 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -12,6 +12,43 @@ // To allow the FPS-limiter to put the thread to sleep #include +#ifdef _MSC_VER +#include +#include +#define MAX_PATH 260 +#endif + +static std::filesystem::path getResourcesPath() +{ + std::filesystem::path resourcesPath{}; + +#ifdef _MSC_VER + CHAR exeDirBuf[MAX_PATH + 1]; + GetModuleFileNameA(NULL, exeDirBuf, MAX_PATH + 1); + std::filesystem::path cwd = std::filesystem::path(exeDirBuf).parent_path(); + (void)_chdir((const char*)std::filesystem::absolute(cwd).c_str()); +#else + std::filesystem::path cwd = std::filesystem::current_path(); +#endif + + if (std::filesystem::is_directory(cwd / "res")) { + resourcesPath = cwd / "res"; + } + else { + resourcesPath = cwd.parent_path() / "share" / "sdltest"; + } + + if (std::filesystem::is_directory(resourcesPath) == false) { + resourcesPath = cwd.root_path() / "usr" / "local" / "share" / "sdltest"; + } + + if (std::filesystem::is_directory(resourcesPath) == false) { + throw std::runtime_error("Unable to determine resources location. CWD: " + cwd.string()); + } + + return resourcesPath; +} + namespace engine { Application::Application(const char* appName, const char* appVersion) @@ -20,6 +57,9 @@ namespace engine { m_gfx = std::make_unique(appName, appVersion, m_window->getHandle()); m_inputManager = std::make_unique(window()); m_sceneManager = std::make_unique(); + + // get base path for resources + m_resourcesPath = getResourcesPath(); } Application::~Application() {} diff --git a/src/resources/texture.cpp b/src/resources/texture.cpp new file mode 100644 index 0000000..5c51c59 --- /dev/null +++ b/src/resources/texture.cpp @@ -0,0 +1,38 @@ +#include "resources/texture.hpp" + +#include "util/files.hpp" +#include "log.hpp" + +#include + +namespace engine::resources { + +Texture::Texture(GFXDevice* gfxDevice, const std::string& path) + : m_gfxDevice(gfxDevice) +{ + + int width, height; + auto texbuf = util::readImageFile(path, &width, &height); + + gfx::TextureFilter filter = gfx::TextureFilter::LINEAR; + if (width <= 8 || height <= 8) { + filter = gfx::TextureFilter::NEAREST; + } + + m_gpuTexture = m_gfxDevice->createTexture(texbuf->data(), (uint32_t)width, (uint32_t)height, gfx::TextureFilter::LINEAR, filter); + + DEBUG("loaded texture {}, width: {} height: {} size: {}", path, width, height, texbuf->size()); + +} + +Texture::~Texture() +{ + m_gfxDevice->destroyTexture(m_gpuTexture); +} + +gfx::Texture* Texture::getHandle() +{ + return m_gpuTexture; +} + +} diff --git a/src/scene.cpp b/src/scene.cpp index 56c4ece..eb58c17 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -1,12 +1,10 @@ #include "scene.hpp" -#include "components/mesh_renderer.hpp" - namespace engine { Scene::Scene() { - m_renderSystem = std::make_unique(); + m_renderSystem = std::make_unique(); } Scene::~Scene() {} diff --git a/src/scene_manager.cpp b/src/scene_manager.cpp index 09371cd..49055ba 100644 --- a/src/scene_manager.cpp +++ b/src/scene_manager.cpp @@ -1,7 +1,7 @@ #include "scene_manager.hpp" #include "scene.hpp" -#include "log.hpp" +#include "resources/texture.hpp" #include @@ -9,6 +9,7 @@ namespace engine { SceneManager::SceneManager() { + m_textureManager = std::make_unique>(); } SceneManager::~SceneManager() {} diff --git a/src/texture.cpp b/src/texture.cpp deleted file mode 100644 index 5781c05..0000000 --- a/src/texture.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#if 0 - -#include "resources/texture.hpp" - -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" - -#include - -#include - -namespace engine::resources { - -// returns false if unable to open file -static bool readPNG(const std::string& path, std::vector* texbuf, int *width, int *height, bool *isRGBA) -{ - int x, y, n; - unsigned char *data = stbi_load(path.c_str(), &x, &y, &n, STBI_rgb_alpha); - - - if (data == nullptr) { - return false; - } - - const size_t size = (size_t)x * (size_t)y * 4; - - texbuf->resize(size); - memcpy(texbuf->data(), data, size); - - *width = x; - *height = y; - *isRGBA = true; - - stbi_image_free(data); - - return true; - -} - -static bool readGLRaw(const std::string& path, std::vector* texbuf, int *width, int *height, bool *isRGBA) -{ - FILE *fp = fopen(path.c_str(), "rb"); - if (!fp) { - return false; - } - - fseek(fp, 0x02, SEEK_SET); - uint64_t tex_data_offset; - fread(&tex_data_offset, sizeof(uint64_t), 1, fp); - - fseek(fp, 0L, SEEK_END); - uint64_t end = ftell(fp); - - texbuf->resize(end); - fseek(fp, (long)tex_data_offset, SEEK_SET); - fread(texbuf->data(), 1, end, fp); - - fclose(fp); - - *width = 4096; - *height = 4096; - *isRGBA = false; - - return true; - -} - -Texture::Texture(const std::filesystem::path& originalResPath) : Resource(originalResPath, "texture") -{ - - std::string resString = originalResPath.string(); - bool flipV = false; - if (resString.back() == '_') { - flipV = true; - resString.pop_back(); - } - - std::filesystem::path resPath{ resString }; - - auto texbuf = std::make_unique>(); - - int width, height; - bool isRGBA, success; - - if (resPath.extension() == ".png" || resPath.extension() == ".jpg") { - success = readPNG(resPath.string(), texbuf.get(), &width, &height, &isRGBA); - } else { - success = readGLRaw(resPath.string(), texbuf.get(), &width, &height, &isRGBA); - } - - if (!success) { - throw std::runtime_error("Unable to open texture: " + resPath.string()); - } - - if (isRGBA == false) { - throw std::runtime_error("Currently, only RGBA textures are supported. Size: " + std::to_string(texbuf->size())); - } - - gfx::TextureFilter filter = gfx::TextureFilter::LINEAR; - if (width <= 8 || height <= 8) { - filter = gfx::TextureFilter::NEAREST; - } - - m_gpuTexture = gfxdev->createTexture(texbuf->data(), (uint32_t)width, (uint32_t)height, gfx::TextureFilter::LINEAR, filter); - - DEBUG("loaded texture {} width: {} height: {} size: {}", resPath.filename().string(), width, height, texbuf->size()); - -} - -Texture::~Texture() -{ - gfxdev->destroyTexture(m_gpuTexture); -} - -gfx::Texture* Texture::getHandle() -{ - return m_gpuTexture; -} - -} - -#endif \ No newline at end of file diff --git a/src/util/files.cpp b/src/util/files.cpp index ad9356a..28d939c 100644 --- a/src/util/files.cpp +++ b/src/util/files.cpp @@ -1,5 +1,8 @@ #include "util/files.hpp" +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + #include namespace engine::util { @@ -48,5 +51,28 @@ namespace engine::util { return buffer; } + // returns false if unable to open file + std::unique_ptr> readImageFile(const std::string& path, int *width, int *height) + { + int x, y, n; + unsigned char *data = stbi_load(path.c_str(), &x, &y, &n, STBI_rgb_alpha); + + if (data == nullptr) { + throw std::runtime_error("Unable to open file " + path); + } + + const size_t size = (size_t)x * (size_t)y * 4; + + auto buffer = std::make_unique>(size); + memcpy(buffer->data(), data, buffer->size()); + + *width = x; + *height = y; + + stbi_image_free(data); + + return buffer; + } + } diff --git a/test/src/game.cpp b/test/src/game.cpp index 1f44220..421fd75 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -4,7 +4,7 @@ #include "window.hpp" #include "scene_manager.hpp" #include "scene.hpp" -#include "components/mesh_renderer.hpp" +#include "ecs/mesh_renderer.hpp" void playGame() { @@ -17,7 +17,16 @@ void playGame() auto entity1 = myScene->createEntity(); - myScene->m_renderSystem->m_components.emplace(entity1, engine::components::MeshRenderer()); + auto myTexture = std::make_unique(app.gfx(), app.getResourcePath("textures/grass.jpg")); + + app.sceneManager()->getTextureManager()->add("GRASS", std::move(myTexture)); + myScene->m_renderSystem->m_components.emplace( + entity1, + engine::ecs::MeshRendererComponent{ + .number = 69, + .texture = app.sceneManager()->getTextureManager()->get("GRASS"), + } + ); app.sceneManager()->createScene(std::move(myScene));