From 54c3874aee7e236ee4289d39a0847e055f2a08e4 Mon Sep 17 00:00:00 2001 From: Franciszek Szewczyk Date: Tue, 22 Oct 2024 21:20:47 +0200 Subject: [PATCH] Subsystem structure --- CMakeLists.txt | 2 +- resources/shaders/fragment/color.glsl | 9 + .../vertex/{camera_view.glsl => model.glsl} | 0 resources/shaders/vertex/wireframe.glsl | 13 + src/AssetManager/AssetManager.hpp | 14 +- src/AssetManager/CMakeLists.txt | 1 + src/AssetManager/Mesh.cpp | 140 +++++++++- src/AssetManager/Mesh.hpp | 9 +- src/AssetManager/Wireframe.cpp | 181 +++++++++++++ src/AssetManager/Wireframe.hpp | 47 ++++ src/Components/CMakeLists.txt | 1 + src/Components/CameraComponent.hpp | 57 ++--- src/Components/WireframeComponent.hpp | 33 +++ src/ECS/Registry.cpp | 10 +- src/ECS/Registry.hpp | 4 + src/Rendering/CMakeLists.txt | 2 - src/Rendering/Renderer.cpp | 240 ------------------ src/Rendering/Renderer.hpp | 46 ---- src/Runtime/CMakeLists.txt | 4 +- src/Runtime/Runtime.cpp | 32 ++- src/Runtime/Runtime.hpp | 46 ++-- src/Systems/CMakeLists.txt | 26 ++ src/Systems/CameraMovementSystem.cpp | 139 ++++++++++ src/Systems/CameraMovementSystem.hpp | 22 ++ src/Systems/ModelRendererSystem.cpp | 58 +++++ src/Systems/ModelRendererSystem.hpp | 20 ++ src/Systems/RenderingSystem.cpp | 76 ++++++ src/Systems/RenderingSystem.hpp | 28 ++ src/Systems/WireframeRendererSystem.cpp | 42 +++ src/Systems/WireframeRendererSystem.hpp | 21 ++ src/main.cpp | 74 +++++- src/ui/CMakeLists.txt | 3 +- src/ui/Components/CameraComponentUI.cpp | 14 - src/ui/Components/CameraComponentUI.hpp | 15 -- src/ui/Components/WireframeComponentUI.cpp | 36 +++ src/ui/Components/WireframeComponentUI.hpp | 20 ++ src/ui/UI.cpp | 5 +- src/ui/UI.hpp | 1 + src/ui/widgets/PropertiesWidget.cpp | 16 ++ src/ui/widgets/SceneWidget.cpp | 16 +- src/ui/widgets/SceneWidget.hpp | 6 - 41 files changed, 1083 insertions(+), 446 deletions(-) create mode 100644 resources/shaders/fragment/color.glsl rename resources/shaders/vertex/{camera_view.glsl => model.glsl} (100%) create mode 100644 resources/shaders/vertex/wireframe.glsl create mode 100644 src/AssetManager/Wireframe.cpp create mode 100644 src/AssetManager/Wireframe.hpp create mode 100644 src/Components/WireframeComponent.hpp delete mode 100644 src/Rendering/Renderer.cpp delete mode 100644 src/Rendering/Renderer.hpp create mode 100644 src/Systems/CMakeLists.txt create mode 100644 src/Systems/CameraMovementSystem.cpp create mode 100644 src/Systems/CameraMovementSystem.hpp create mode 100644 src/Systems/ModelRendererSystem.cpp create mode 100644 src/Systems/ModelRendererSystem.hpp create mode 100644 src/Systems/RenderingSystem.cpp create mode 100644 src/Systems/RenderingSystem.hpp create mode 100644 src/Systems/WireframeRendererSystem.cpp create mode 100644 src/Systems/WireframeRendererSystem.hpp delete mode 100644 src/ui/Components/CameraComponentUI.cpp delete mode 100644 src/ui/Components/CameraComponentUI.hpp create mode 100644 src/ui/Components/WireframeComponentUI.cpp create mode 100644 src/ui/Components/WireframeComponentUI.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d62b1ba0..cd65efb4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/src/Rendering) add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/src/Runtime) add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/src/UI) add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/src/InputManager) +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/src/Systems) add_executable(ShkyeraEngine src/main.cpp) @@ -47,5 +48,4 @@ target_link_libraries( UI Runtime - ECS ) diff --git a/resources/shaders/fragment/color.glsl b/resources/shaders/fragment/color.glsl new file mode 100644 index 00000000..5775ae32 --- /dev/null +++ b/resources/shaders/fragment/color.glsl @@ -0,0 +1,9 @@ +#version 330 core + +out vec4 FragColor; + +uniform vec3 fixedColor; + +void main() { + FragColor = vec4(fixedColor, 1.0); +} diff --git a/resources/shaders/vertex/camera_view.glsl b/resources/shaders/vertex/model.glsl similarity index 100% rename from resources/shaders/vertex/camera_view.glsl rename to resources/shaders/vertex/model.glsl diff --git a/resources/shaders/vertex/wireframe.glsl b/resources/shaders/vertex/wireframe.glsl new file mode 100644 index 00000000..f69ec71e --- /dev/null +++ b/resources/shaders/vertex/wireframe.glsl @@ -0,0 +1,13 @@ +#version 330 core + +layout(location = 0) in vec3 position; // Vertex position + +uniform mat4 modelMatrix; // Model matrix +uniform mat4 viewMatrix; // View matrix +uniform mat4 projectionMatrix; // Projection matrix + +void main() { + // Transform the vertex position to clip space + gl_Position = + projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0); +} diff --git a/src/AssetManager/AssetManager.hpp b/src/AssetManager/AssetManager.hpp index b6b6bd58..c89d40df 100644 --- a/src/AssetManager/AssetManager.hpp +++ b/src/AssetManager/AssetManager.hpp @@ -12,19 +12,25 @@ class AssetManager { static AssetManager& getInstance(); template - std::shared_ptr getAsset(const std::filesystem::path& path, Args... args) { - if (_assets.contains(path.string())) { - if (auto asset = _assets.at(path.string()).lock()) { + std::shared_ptr getAsset(const std::string& path, Args... args) { + if (_assets.contains(path)) { + if (auto asset = _assets.at(path).lock()) { return std::static_pointer_cast(asset); } } auto asset = std::make_shared(path, args...); _assetFilePaths[asset.get()] = path; - _assets[path.string()] = asset; + _assets[path] = asset; return asset; } + template + void addAsset(const std::string& path, std::shared_ptr asset) { + _assets[path] = asset; + _assetFilePaths[(void *)asset.get()] = path; + } + template std::optional getFilePath(AssetType* asset) { void* ptr = (void *)(asset); diff --git a/src/AssetManager/CMakeLists.txt b/src/AssetManager/CMakeLists.txt index f38128f4..f4d99e2c 100644 --- a/src/AssetManager/CMakeLists.txt +++ b/src/AssetManager/CMakeLists.txt @@ -7,6 +7,7 @@ add_library( ${CMAKE_CURRENT_LIST_DIR}/AssetManager.cpp ${CMAKE_CURRENT_LIST_DIR}/Shader.cpp ${CMAKE_CURRENT_LIST_DIR}/Mesh.cpp + ${CMAKE_CURRENT_LIST_DIR}/Wireframe.cpp ${CMAKE_CURRENT_LIST_DIR}/Material.cpp ) diff --git a/src/AssetManager/Mesh.cpp b/src/AssetManager/Mesh.cpp index d9c7697e..fb92fae6 100644 --- a/src/AssetManager/Mesh.cpp +++ b/src/AssetManager/Mesh.cpp @@ -5,7 +5,6 @@ #include #include -// Assuming you are using a simple OBJ loader. You could integrate a library like Assimp for more advanced formats. #include namespace std { @@ -19,11 +18,14 @@ namespace std { namespace shkyera { -// Constructor that loads the model from a file Mesh::Mesh(const std::string& filepath) { loadFromFile(filepath); } +Mesh::Mesh(const std::vector& vertices, std::vector indices) { + uploadToGPU(vertices, indices); +} + // Destructor to clean up OpenGL resources Mesh::~Mesh() { glDeleteVertexArrays(1, &_vao); @@ -45,9 +47,7 @@ static std::vector calculateNormals(const std::vector& glm::vec3 v1 = vertices[idx1].position; glm::vec3 v2 = vertices[idx2].position; - glm::vec3 edge1 = v1 - v0; - glm::vec3 edge2 = v2 - v0; - glm::vec3 faceNormal = glm::normalize(glm::cross(edge1, edge2)); + glm::vec3 faceNormal = glm::normalize(glm::cross(v1 - v0, v2 - v0)); faceNormals[v0].push_back(faceNormal); faceNormals[v1].push_back(faceNormal); @@ -60,7 +60,6 @@ static std::vector calculateNormals(const std::vector& const glm::vec3& position = entry.first; const std::vector& normals = entry.second; - // Average the face normals for each position glm::vec3 averagedNormal = glm::vec3(0.0f); for (const glm::vec3& normal : normals) { averagedNormal += normal; @@ -169,4 +168,133 @@ void Mesh::uploadToGPU(const std::vector& vertices, const std::vector vertices = { + // Front face + { { -1.0f, -1.0f, -1.0f }, { 0.0f, 0.0f, -1.0f }, { 0.0f, 0.0f } }, // 0 + { { 1.0f, -1.0f, -1.0f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 0.0f } }, // 1 + { { 1.0f, 1.0f, -1.0f }, { 0.0f, 0.0f, -1.0f }, { 1.0f, 1.0f } }, // 2 + { { -1.0f, 1.0f, -1.0f }, { 0.0f, 0.0f, -1.0f }, { 0.0f, 1.0f } }, // 3 + + // Back face + { { -1.0f, -1.0f, 1.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 0.0f } }, // 4 + { { 1.0f, -1.0f, 1.0f }, { 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f } }, // 5 + { { 1.0f, 1.0f, 1.0f }, { 0.0f, 0.0f, 1.0f }, { 0.0f, 1.0f } }, // 6 + { { -1.0f, 1.0f, 1.0f }, { 0.0f, 0.0f, 1.0f }, { 1.0f, 1.0f } }, // 7 + + // Left face + { { -1.0f, -1.0f, 1.0f }, { -1.0f, 0.0f, 0.0f }, { 0.0f, 0.0f } }, // 8 + { { -1.0f, 1.0f, 1.0f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f } }, // 9 + { { -1.0f, 1.0f, -1.0f }, { -1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f } }, // 10 + { { -1.0f, -1.0f, -1.0f }, { -1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f } }, // 11 + + // Right face + { { 1.0f, -1.0f, -1.0f }, { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f } }, // 12 + { { 1.0f, 1.0f, -1.0f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f } }, // 13 + { { 1.0f, 1.0f, 1.0f }, { 1.0f, 0.0f, 0.0f }, { 1.0f, 0.0f } }, // 14 + { { 1.0f, -1.0f, 1.0f }, { 1.0f, 0.0f, 0.0f }, { 0.0f, 0.0f } }, // 15 + + // Top face + { { -1.0f, 1.0f, -1.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 1.0f } }, // 16 + { { 1.0f, 1.0f, -1.0f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 1.0f } }, // 17 + { { 1.0f, 1.0f, 1.0f }, { 0.0f, 1.0f, 0.0f }, { 1.0f, 0.0f } }, // 18 + { { -1.0f, 1.0f, 1.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f } }, // 19 + + // Bottom face + { { -1.0f, -1.0f, -1.0f }, { 0.0f, -1.0f, 0.0f }, { 0.0f, 0.0f } }, // 20 + { { 1.0f, -1.0f, -1.0f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 0.0f } }, // 21 + { { 1.0f, -1.0f, 1.0f }, { 0.0f, -1.0f, 0.0f }, { 1.0f, 1.0f } }, // 22 + { { -1.0f, -1.0f, 1.0f }, { 0.0f, -1.0f, 0.0f }, { 0.0f, 1.0f } }, // 23 + }; + + std::vector indices = { + // Front face + 0, 1, 2, 2, 3, 0, + // Back face + 4, 5, 6, 6, 7, 4, + // Left face + 8, 11, 10, 10, 9, 8, + // Right face + 12, 13, 14, 14, 15, 12, + // Top face + 16, 17, 18, 18, 19, 16, + // Bottom face + 20, 23, 22, 22, 21, 20, + }; + + return new Mesh(vertices, indices); +} + +Mesh* Mesh::Factory::createCylinder() { + const int sectors = 36; + const float radius = 1.0f; + const float height = 2.0f; + + std::vector vertices; + std::vector indices; + + // Generate vertices + for (int i = 0; i <= sectors; ++i) { + float theta = 2.0f * M_PI * float(i) / float(sectors); + float x = radius * cos(theta); + float z = radius * sin(theta); + + vertices.push_back({ { x, -height / 2, z }, { x, 0.0f, z }, { float(i) / sectors, 0.0f } }); + vertices.push_back({ { x, height / 2, z }, { x, 0.0f, z }, { float(i) / sectors, 1.0f } }); + } + + // Generate indices for the sides + for (int i = 0; i < sectors; ++i) { + indices.push_back(i * 2); + indices.push_back(i * 2 + 1); + indices.push_back((i * 2 + 2) % (sectors * 2)); + + indices.push_back(i * 2 + 1); + indices.push_back((i * 2 + 3) % (sectors * 2)); + indices.push_back((i * 2 + 2) % (sectors * 2)); + } + + return new Mesh(vertices, indices); +} + +Mesh* Mesh::Factory::createSphere() { + const int stacks = 18; + const int sectors = 36; + const float radius = 1.0f; + + std::vector vertices; + std::vector indices; + + for (int i = 0; i <= stacks; ++i) { + float stackAngle = M_PI / 2.0f - i * (M_PI / stacks); + float xy = radius * cosf(stackAngle); + float z = radius * sinf(stackAngle); + + for (int j = 0; j <= sectors; ++j) { + float sectorAngle = j * (2.0f * M_PI / sectors); + float x = xy * cosf(sectorAngle); + float y = xy * sinf(sectorAngle); + + vertices.push_back({ { x, y, z }, { x / radius, y / radius, z / radius }, { float(j) / sectors, float(i) / stacks } }); + } + } + + for (int i = 0; i < stacks; ++i) { + for (int j = 0; j < sectors; ++j) { + unsigned int first = (i * (sectors + 1)) + j; + unsigned int second = first + sectors + 1; + + indices.push_back(first); + indices.push_back(second); + indices.push_back(first + 1); + + indices.push_back(second); + indices.push_back(second + 1); + indices.push_back(first + 1); + } + } + + return new Mesh(vertices, indices); +} + } diff --git a/src/AssetManager/Mesh.hpp b/src/AssetManager/Mesh.hpp index 1383480a..65cfff04 100644 --- a/src/AssetManager/Mesh.hpp +++ b/src/AssetManager/Mesh.hpp @@ -20,6 +20,7 @@ class Mesh : public Asset { }; Mesh(const std::string& filepath); + Mesh(const std::vector& vertices, std::vector indices); ~Mesh(); void bind() const { glBindVertexArray(_vao); } @@ -30,8 +31,12 @@ class Mesh : public Asset { GLuint getEBO() const { return _ebo; } GLsizei getMeshSize() const { return _meshSize; } - std::vector _vertices; - std::vector _indices; + class Factory { + public: + static Mesh* createCube(); + static Mesh* createCylinder(); + static Mesh* createSphere(); + }; private: void loadFromFile(const std::string& filepath); diff --git a/src/AssetManager/Wireframe.cpp b/src/AssetManager/Wireframe.cpp new file mode 100644 index 00000000..21fd88e6 --- /dev/null +++ b/src/AssetManager/Wireframe.cpp @@ -0,0 +1,181 @@ +#include "Wireframe.hpp" +#include +#include + +namespace shkyera { + +Wireframe::Wireframe(const std::string& filepath) { + loadFromFile(filepath); +} + +Wireframe::Wireframe(const std::vector& edges) { + uploadToGPU(edges); +} + +Wireframe::~Wireframe() { + glDeleteVertexArrays(1, &_vao); + glDeleteBuffers(1, &_vbo); +} + +void Wireframe::loadFromFile(const std::string& filepath) { + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + std::string warn, err; + + if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filepath.c_str())) { + std::cerr << "Failed to load OBJ file: " << filepath << std::endl; + if (!warn.empty()) std::cerr << "Warning: " << warn << std::endl; + if (!err.empty()) std::cerr << "Error: " << err << std::endl; + return; + } + + std::vector edges; + + for (const auto& shape : shapes) { + const auto& mesh = shape.mesh; + for (size_t faceIdx = 0; faceIdx < mesh.indices.size(); faceIdx += 3) { + glm::vec3 positions[3]; + for (int i = 0; i < 3; ++i) { + unsigned int idx = mesh.indices[faceIdx + i].vertex_index; + positions[i] = glm::vec3( + attrib.vertices[3 * idx + 0], + attrib.vertices[3 * idx + 1], + attrib.vertices[3 * idx + 2] + ); + } + + // Add edges between each vertex pair in the triangle + edges.emplace_back(positions[0], positions[1]); + edges.emplace_back(positions[1], positions[2]); + edges.emplace_back(positions[2], positions[0]); + } + } + + uploadToGPU(edges); +} + +void Wireframe::uploadToGPU(const std::vector& edges) { + _edgeCount = static_cast(edges.size() * 2); // Two vertices per edge + + std::vector edgeVertices; + edgeVertices.reserve(_edgeCount); + for (const auto& edge : edges) { + edgeVertices.push_back(edge.start); + edgeVertices.push_back(edge.end); + } + + // Generate and bind VAO and VBO + glGenVertexArrays(1, &_vao); + glBindVertexArray(_vao); + + glGenBuffers(1, &_vbo); + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, edgeVertices.size() * sizeof(glm::vec3), edgeVertices.data(), GL_STATIC_DRAW); + + // Set vertex attribute pointers + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), (void*)0); // Position + glEnableVertexAttribArray(0); + + // Unbind the VAO + glBindVertexArray(0); +} + +// Factory methods for creating primitive shapes (cube, cylinder, sphere) +Wireframe* Wireframe::Factory::createCube() { + std::vector edges = { + // Front face + { { -1.0f, -1.0f, -1.0f }, { 1.0f, -1.0f, -1.0f } }, + { { 1.0f, -1.0f, -1.0f }, { 1.0f, 1.0f, -1.0f } }, + { { 1.0f, 1.0f, -1.0f }, { -1.0f, 1.0f, -1.0f } }, + { { -1.0f, 1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } }, + + // Back face + { { -1.0f, -1.0f, 1.0f }, { 1.0f, -1.0f, 1.0f } }, + { { 1.0f, -1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f } }, + { { 1.0f, 1.0f, 1.0f }, { -1.0f, 1.0f, 1.0f } }, + { { -1.0f, 1.0f, 1.0f }, { -1.0f, -1.0f, 1.0f } }, + + // Connect front and back faces + { { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, 1.0f } }, + { { 1.0f, -1.0f, -1.0f }, { 1.0f, -1.0f, 1.0f } }, + { { 1.0f, 1.0f, -1.0f }, { 1.0f, 1.0f, 1.0f } }, + { { -1.0f, 1.0f, -1.0f }, { -1.0f, 1.0f, 1.0f } }, + }; + + return new Wireframe(edges); +} + +Wireframe* Wireframe::Factory::createCylinder() { + const int sectors = 36; + const float radius = 1.0f; + const float height = 2.0f; + + std::vector edges; + + // Generate vertices for the top and bottom circles + for (int i = 0; i < sectors; ++i) { + float theta = 2.0f * M_PI * float(i) / float(sectors); + float nextTheta = 2.0f * M_PI * float(i + 1) / float(sectors); + + float x = radius * cos(theta); + float z = radius * sin(theta); + float nextX = radius * cos(nextTheta); + float nextZ = radius * sin(nextTheta); + + glm::vec3 bottomCurrent = { x, -height / 2, z }; + glm::vec3 bottomNext = { nextX, -height / 2, nextZ }; + glm::vec3 topCurrent = { x, height / 2, z }; + glm::vec3 topNext = { nextX, height / 2, nextZ }; + + // Edges on bottom and top circles + edges.emplace_back(bottomCurrent, bottomNext); + edges.emplace_back(topCurrent, topNext); + + // Vertical edges connecting top and bottom + edges.emplace_back(bottomCurrent, topCurrent); + } + + return new Wireframe(edges); +} + +Wireframe* Wireframe::Factory::createSphere() { + const int stacks = 18; + const int sectors = 36; + const float radius = 1.0f; + + std::vector edges; + + for (int i = 0; i < stacks; ++i) { + float stackAngle = M_PI / 2.0f - i * (M_PI / stacks); + float nextStackAngle = M_PI / 2.0f - (i + 1) * (M_PI / stacks); + float xy = radius * cosf(stackAngle); + float z = radius * sinf(stackAngle); + float nextXY = radius * cosf(nextStackAngle); + float nextZ = radius * sinf(nextStackAngle); + + for (int j = 0; j < sectors; ++j) { + float sectorAngle = 2.0f * M_PI * j / sectors; + float nextSectorAngle = 2.0f * M_PI * (j + 1) / sectors; + + float x = xy * cosf(sectorAngle); + float y = xy * sinf(sectorAngle); + float nextX = xy * cosf(nextSectorAngle); + float nextY = xy * sinf(nextSectorAngle); + + glm::vec3 current = { x, y, z }; + glm::vec3 next = { nextX, nextY, z }; + glm::vec3 nextStackCurrent = { x * nextXY / xy, y * nextXY / xy, nextZ }; + + // Horizontal edge + edges.emplace_back(current, next); + + // Vertical edge to the next stack + edges.emplace_back(current, nextStackCurrent); + } + } + + return new Wireframe(edges); +} + +} // namespace shkyera diff --git a/src/AssetManager/Wireframe.hpp b/src/AssetManager/Wireframe.hpp new file mode 100644 index 00000000..75256e32 --- /dev/null +++ b/src/AssetManager/Wireframe.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include + +#include + +namespace shkyera { + +class Wireframe : public Asset { +public: + struct Edge { + glm::vec3 start; + glm::vec3 end; + + Edge(const glm::vec3& s, const glm::vec3& e) : start(s), end(e) {} + }; + + Wireframe(const std::string& filepath); + Wireframe(const std::vector& edges); + ~Wireframe(); + + void bind() const { glBindVertexArray(_vao); } + void unbind() const { glBindVertexArray(0); } + + GLuint getVAO() const { return _vao; } + GLuint getVBO() const { return _vbo; } + GLsizei getEdgeCount() const { return _edgeCount; } + + class Factory { + public: + static Wireframe* createCube(); + static Wireframe* createCylinder(); + static Wireframe* createSphere(); + }; + +private: + void loadFromFile(const std::string& filepath); + void uploadToGPU(const std::vector& edges); + + GLuint _vao, _vbo; + GLsizei _edgeCount; +}; + +} // namespace shkyera diff --git a/src/Components/CMakeLists.txt b/src/Components/CMakeLists.txt index 3d8bae90..3efb5be1 100644 --- a/src/Components/CMakeLists.txt +++ b/src/Components/CMakeLists.txt @@ -7,6 +7,7 @@ add_library( ${CMAKE_CURRENT_LIST_DIR}/NameComponent.hpp ${CMAKE_CURRENT_LIST_DIR}/TransformComponent.hpp ${CMAKE_CURRENT_LIST_DIR}/ModelComponent.hpp + ${CMAKE_CURRENT_LIST_DIR}/WireframeComponent.hpp ${CMAKE_CURRENT_LIST_DIR}/PointLightComponent.hpp ) diff --git a/src/Components/CameraComponent.hpp b/src/Components/CameraComponent.hpp index d38a6a24..2c410c73 100644 --- a/src/Components/CameraComponent.hpp +++ b/src/Components/CameraComponent.hpp @@ -6,7 +6,7 @@ namespace shkyera { -class CameraComponent : public TransformComponent { +class CameraComponent { public: enum class ProjectionType { Perspective, @@ -14,31 +14,16 @@ class CameraComponent : public TransformComponent { }; CameraComponent(float fov = 45.0f, float aspectRatio = 16.0f / 9.0f, float nearPlane = 0.1f, float farPlane = 10000.0f, ProjectionType projectionType = ProjectionType::Perspective) - : _fov(fov), _aspectRatio(aspectRatio), _nearPlane(nearPlane), _farPlane(farPlane), _projectionType(projectionType) {} - - // Set and get Field of View (for perspective projection) - float& getFov() { return _fov; } // Modifiable reference - const float& getFov() const { return _fov; } // Constant reference - - // Set and get aspect ratio (width/height of the screen) - float& getAspectRatio() { return _aspectRatio; } // Modifiable reference - const float& getAspectRatio() const { return _aspectRatio; } // Constant reference - - // Set and get near/far clipping planes - float& getNearPlane() { return _nearPlane; } // Modifiable reference - const float& getNearPlane() const { return _nearPlane; } // Constant reference - - float& getFarPlane() { return _farPlane; } // Modifiable reference - const float& getFarPlane() const { return _farPlane; } // Constant reference - - // Set projection type (Perspective or Orthographic) - ProjectionType& getProjectionType() { return _projectionType; } // Modifiable reference - const ProjectionType& getProjectionType() const { return _projectionType; } // Constant reference - - // Get the view matrix based on the camera's transform - glm::mat4 getViewMatrix() const { - glm::vec3 position = getPosition(); - glm::vec3 orientation = getOrientation(); + : fov(fov), aspectRatio(aspectRatio), nearPlane(nearPlane), farPlane(farPlane), projectionType(projectionType) {} + + float fov; + float aspectRatio; + float nearPlane, farPlane; + ProjectionType projectionType; + + glm::mat4 getViewMatrix(const TransformComponent& transformComponent) const { + glm::vec3 position = transformComponent.getPosition(); + glm::vec3 orientation = transformComponent.getOrientation(); // Calculate direction vectors glm::vec3 front; @@ -47,35 +32,23 @@ class CameraComponent : public TransformComponent { front.z = sin(orientation.y) * cos(orientation.x); front = glm::normalize(front); - // Define the world up vector (Y-axis) glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); - - // Get the camera's right vector using the front and world up glm::vec3 right = glm::normalize(glm::cross(front, up)); - - // Recalculate up vector based on the camera's orientation up = -glm::normalize(glm::cross(right, front)); return glm::lookAt(position, position + front, up); } - // Get the projection matrix (Perspective or Orthographic) glm::mat4 getProjectionMatrix() const { - if (_projectionType == ProjectionType::Perspective) { - return glm::perspective(glm::radians(_fov), _aspectRatio, _nearPlane, _farPlane); + if (projectionType == ProjectionType::Perspective) { + return glm::perspective(glm::radians(fov), aspectRatio, nearPlane, farPlane); } else { float orthoSize = 10.0f; // Can be configurable - float halfWidth = orthoSize * _aspectRatio * 0.5f; + float halfWidth = orthoSize * aspectRatio * 0.5f; float halfHeight = orthoSize * 0.5f; - return glm::ortho(-halfWidth, halfWidth, -halfHeight, halfHeight, _nearPlane, _farPlane); + return glm::ortho(-halfWidth, halfWidth, -halfHeight, halfHeight, nearPlane, farPlane); } } - -private: - float _fov; // Field of View (for perspective projection) - float _aspectRatio; // Aspect ratio (width/height) - float _nearPlane, _farPlane; // Near and far clipping planes - ProjectionType _projectionType; // Type of projection (Perspective/Orthographic) }; } // namespace shkyera diff --git a/src/Components/WireframeComponent.hpp b/src/Components/WireframeComponent.hpp new file mode 100644 index 00000000..f693071b --- /dev/null +++ b/src/Components/WireframeComponent.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include + +namespace shkyera { + +class WireframeComponent : public BaseComponent { +public: + WireframeComponent() = default; + + void setWireframe(std::shared_ptr wireframe) { + _wireframe = wireframe; + } + + Wireframe const* getWireframe() const { + return _wireframe.get(); + } + + void updateImpl() const { + if (_wireframe) { + _wireframe->bind(); + glDrawArrays(GL_LINES, 0, _wireframe->getEdgeCount()); + _wireframe->unbind(); + } + } + +private: + std::shared_ptr _wireframe; +}; + +} // namespace shkyera diff --git a/src/ECS/Registry.cpp b/src/ECS/Registry.cpp index 8f9d801d..5f02b44d 100644 --- a/src/ECS/Registry.cpp +++ b/src/ECS/Registry.cpp @@ -2,9 +2,11 @@ namespace shkyera { -static constexpr Entity InitialEntities = 100; +static constexpr Entity INITIAL_ENTITIES = 100; -Registry::Registry() : _entityProvider(InitialEntities) {} +Registry::Registry() : _entityProvider(INITIAL_ENTITIES) { + _camera = addEntity(); +} Entity Registry::addEntity() { return _entityProvider.requestEntity(); @@ -18,4 +20,8 @@ void Registry::removeEntity(Entity entity) { _entityProvider.removeEntity(entity); } +Entity Registry::getCamera() const { + return _camera; +} + } // namespace shkyera diff --git a/src/ECS/Registry.hpp b/src/ECS/Registry.hpp index a10fa07a..907cc3b0 100644 --- a/src/ECS/Registry.hpp +++ b/src/ECS/Registry.hpp @@ -132,6 +132,8 @@ class Registry { return getOrCreateComponentSet().getComponents(); } + Entity getCamera() const; + private: /** * Retrieves or creates the component set for the specified component type. @@ -165,6 +167,8 @@ class Registry { mutable std::unordered_map> _componentSets; //< Map of component sets by type ID. EntityProvider _entityProvider; //< Manages the creation and management of entities. + + Entity _camera; }; } // namespace shkyera diff --git a/src/Rendering/CMakeLists.txt b/src/Rendering/CMakeLists.txt index 58455662..6017b41e 100644 --- a/src/Rendering/CMakeLists.txt +++ b/src/Rendering/CMakeLists.txt @@ -3,7 +3,6 @@ add_library( STATIC ${CMAKE_CURRENT_LIST_DIR}/ShaderProgram.cpp - ${CMAKE_CURRENT_LIST_DIR}/Renderer.cpp ) target_include_directories( @@ -19,6 +18,5 @@ target_link_libraries( glad glm::glm - InputManager AssetManager ) diff --git a/src/Rendering/Renderer.cpp b/src/Rendering/Renderer.cpp deleted file mode 100644 index 74084bea..00000000 --- a/src/Rendering/Renderer.cpp +++ /dev/null @@ -1,240 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace shkyera { - -constexpr static float MOVEMENT_SPEED = 0.6; -constexpr static float MOUSE_SENSITIVITY = 0.0; - - -Renderer::Renderer(std::shared_ptr registry) : _registry(registry), _cameraControl(false) { - _camera = registry->addEntity(); - registry->addComponent(_camera); - registry->addComponent(_camera); - - setupFramebuffer(); - setupCameraMovement(); - - InputManager::getInstance().registerMouseButtonDownCallback(GLFW_MOUSE_BUTTON_LEFT, [this]() { - enableCameraMovement(); - }); - InputManager::getInstance().registerMouseButtonUpCallback(GLFW_MOUSE_BUTTON_LEFT, [this]() { - disableCameraMovement(); - }); - - auto vertexShader = AssetManager::getInstance().getAsset("resources/shaders/vertex/camera_view.glsl", Shader::Type::Vertex); - auto fragmentShader = AssetManager::getInstance().getAsset("resources/shaders/fragment/uber.glsl", Shader::Type::Fragment); - - _shaderProgram.attachShader(vertexShader); - _shaderProgram.attachShader(fragmentShader); - _shaderProgram.link(); - - glEnable(GL_DEPTH_TEST); -} - -Renderer::~Renderer() { - glDeleteFramebuffers(1, &_fbo); - glDeleteTextures(1, &_textureColorBuffer); - glDeleteRenderbuffers(1, &_rbo); -} - -void Renderer::draw() { - glBindFramebuffer(GL_FRAMEBUFFER, _fbo); - glViewport(0, 0, (GLsizei)_renderWidth, (GLsizei)_renderHeight); - glClearColor(0.2f, 0.3f, 0.3f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - const glm::mat4& viewMatrix = _registry->getComponent(_camera).getViewMatrix(); - const glm::mat4& projectionMatrix = _registry->getComponent(_camera).getProjectionMatrix(); - const glm::vec3& viewPos = _registry->getComponent(_camera).getPosition(); - - _shaderProgram.use(); - _shaderProgram.setUniform("viewMatrix", viewMatrix); - _shaderProgram.setUniform("projectionMatrix", projectionMatrix); - _shaderProgram.setUniform("viewPos", viewPos); // Set camera position - - int lightIndex = 0; - for(const auto& [entity, pointLightComponent] : _registry->getComponentSet()) { - const auto& transformComponent = _registry->getComponent(entity); - _shaderProgram.setUniform("lights[" + std::to_string(lightIndex) + "].position", transformComponent.getPosition()); - _shaderProgram.setUniform("lights[" + std::to_string(lightIndex) + "].ambient", pointLightComponent.ambient); - _shaderProgram.setUniform("lights[" + std::to_string(lightIndex) + "].diffuse", pointLightComponent.diffuse); - _shaderProgram.setUniform("lights[" + std::to_string(lightIndex) + "].specular", pointLightComponent.specular); - ++lightIndex; - } - _shaderProgram.setUniform("numLights", lightIndex); - - for(const auto& [entity, modelComponent] : _registry->getComponentSet()) { - const auto& transformComponent = _registry->getComponent(entity); - _shaderProgram.setUniform("modelMatrix", transformComponent.getTransformMatrix()); - - const Material* material = modelComponent.getMaterial(); - if (material) { - _shaderProgram.setUniform("material.diffuse", material->getDiffuseColor()); - _shaderProgram.setUniform("material.specular", material->getSpecularColor()); - _shaderProgram.setUniform("material.shininess", material->getShininess()); - } - - modelComponent.updateImpl(); - } - - _shaderProgram.stopUsing(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} - -GLuint Renderer::getTexture() const { - return _textureColorBuffer; -} - -void Renderer::enableCameraMovement() { - _cameraControl = true; -} -void Renderer::disableCameraMovement() { - _cameraControl = false; -} - -void Renderer::setupCameraMovement() { - auto& inputManager = InputManager::getInstance(); - auto& cameraTransform = _registry->getComponent(_camera); - - inputManager.registerKeyCallback(GLFW_KEY_W, [&cameraTransform, &enabled=_cameraControl]() { - if(enabled) { - glm::vec3 forward; - float yaw = cameraTransform.getOrientation().y; - float pitch = cameraTransform.getOrientation().x; - - forward.x = cos(yaw) * cos(pitch); - forward.y = sin(pitch); - forward.z = sin(yaw) * cos(pitch); - forward = glm::normalize(forward); - - cameraTransform.setPosition(cameraTransform.getPosition() + forward * MOVEMENT_SPEED); - } - }); - - inputManager.registerKeyCallback(GLFW_KEY_S, [&cameraTransform, &enabled=_cameraControl]() { - if(enabled) { - glm::vec3 backward; - float yaw = cameraTransform.getOrientation().y; - float pitch = cameraTransform.getOrientation().x; - - backward.x = -cos(yaw) * cos(pitch); - backward.y = -sin(pitch); - backward.z = -sin(yaw) * cos(pitch); - backward = glm::normalize(backward); - - cameraTransform.setPosition(cameraTransform.getPosition() + backward * MOVEMENT_SPEED); - } - }); - - inputManager.registerKeyCallback(GLFW_KEY_A, [&cameraTransform, &enabled=_cameraControl]() { - if(enabled) { - glm::vec3 left; - float yaw = cameraTransform.getOrientation().y; - - left.x = -sin(yaw); - left.y = 0.0f; - left.z = cos(yaw); - left = glm::normalize(left); - - cameraTransform.setPosition(cameraTransform.getPosition() + left * MOVEMENT_SPEED); - } - }); - - inputManager.registerKeyCallback(GLFW_KEY_D, [&cameraTransform, &enabled=_cameraControl]() { - if(enabled) { - glm::vec3 right; - float yaw = cameraTransform.getOrientation().y; - - right.x = sin(yaw); - right.y = 0.0f; - right.z = -cos(yaw); - right = glm::normalize(right); - - cameraTransform.setPosition(cameraTransform.getPosition() + right * MOVEMENT_SPEED); - } - }); - - - inputManager.registerKeyCallback(GLFW_KEY_Q, [&cameraTransform, &enabled=_cameraControl]() { - if(enabled) { - glm::vec3 down = glm::vec3(0.0f, -1.0f, 0.0f); // Down direction in world space - cameraTransform.setPosition(cameraTransform.getPosition() + down * MOVEMENT_SPEED); - } - }); - - inputManager.registerKeyCallback(GLFW_KEY_E, [&cameraTransform, &enabled=_cameraControl]() { - if(enabled) { - glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); // Up direction in world space - cameraTransform.setPosition(cameraTransform.getPosition() + up * MOVEMENT_SPEED); - } - }); - - inputManager.registerMouseMoveCallback([&cameraTransform, &enabled=_cameraControl](double xPos, double yPos) { - static double lastX = xPos, lastY = yPos; - - float xOffset = static_cast(xPos - lastX) * MOUSE_SENSITIVITY; - float yOffset = static_cast(lastY - yPos) * MOUSE_SENSITIVITY; // Y is inverted in OpenGL - - lastX = xPos; - lastY = yPos; - - if(enabled) { - glm::vec3 orientation = cameraTransform.getOrientation(); - orientation.y -= glm::radians(xOffset); // Yaw (Y-axis rotation) - orientation.x += glm::radians(yOffset); // Pitch (X-axis rotation) - - if (orientation.x > glm::radians(89.0f)) - orientation.x = glm::radians(89.0f); - if (orientation.x < glm::radians(-89.0f)) - orientation.x = glm::radians(-89.0f); - - cameraTransform.getOrientation() = orientation; - } - }); -} - -void Renderer::setupFramebuffer() { - glGenFramebuffers(1, &_fbo); - glBindFramebuffer(GL_FRAMEBUFFER, _fbo); - - // Create a texture to render the scene into - glGenTextures(1, &_textureColorBuffer); - glBindTexture(GL_TEXTURE_2D, _textureColorBuffer); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)_renderWidth, (GLsizei)_renderHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureColorBuffer, 0); - - // Create a renderbuffer object for depth and stencil attachment - glGenRenderbuffers(1, &_rbo); - glBindRenderbuffer(GL_RENDERBUFFER, _rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, (GLsizei)_renderWidth, (GLsizei)_renderHeight); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _rbo); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { - std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl; - } - - glBindFramebuffer(GL_FRAMEBUFFER, 0); -} - -void Renderer::setSize(uint32_t width, uint32_t height) { - _renderWidth = width; - _renderHeight = height; - - glBindTexture(GL_TEXTURE_2D, _textureColorBuffer); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)width, (GLsizei)height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - glBindRenderbuffer(GL_RENDERBUFFER, _rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, (GLsizei)width, (GLsizei)height); -} - -} diff --git a/src/Rendering/Renderer.hpp b/src/Rendering/Renderer.hpp deleted file mode 100644 index d1dd8e60..00000000 --- a/src/Rendering/Renderer.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include - -namespace shkyera { - -class Renderer { - public: - Renderer(std::shared_ptr registry); - ~Renderer(); - - void draw(); - - GLuint getTexture() const; - - void enableCameraMovement(); - void disableCameraMovement(); - - void setSize(uint32_t width, uint32_t height); - - private: - void drawScene(); - void setupCameraMovement(); - void setupFramebuffer(); - void cleanupFramebuffer(); - - std::shared_ptr _registry; - uint32_t _renderWidth; - uint32_t _renderHeight; - - GLuint _fbo = 0; - GLuint _textureColorBuffer = 0; - GLuint _rbo = 0; - - Entity _camera; - bool _cameraControl; - - ShaderProgram _shaderProgram; -}; - -} diff --git a/src/Runtime/CMakeLists.txt b/src/Runtime/CMakeLists.txt index d3986084..12cd9f86 100644 --- a/src/Runtime/CMakeLists.txt +++ b/src/Runtime/CMakeLists.txt @@ -16,7 +16,5 @@ target_link_libraries( Runtime PUBLIC - Rendering - - glad + Systems ) diff --git a/src/Runtime/Runtime.cpp b/src/Runtime/Runtime.cpp index 5fe20e62..6189686a 100644 --- a/src/Runtime/Runtime.cpp +++ b/src/Runtime/Runtime.cpp @@ -1,22 +1,32 @@ #include - -#include +#include +#include namespace shkyera { -Runtime::Runtime(std::shared_ptr registry) : _registry(registry), _renderer(registry) {} +Runtime::Runtime(std::shared_ptr registry) + : _registry(registry), + _cameraMovementSystem(registry), + _modelRendererSystem(registry), + _renderingSystem(registry), + _wireframeRendererSystem(registry) {} -void Runtime::run() { - _renderer.draw(); -} +void Runtime::update() { + _cameraMovementSystem.update(); + + _renderingSystem.startFrame(); + _modelRendererSystem.render(); + _wireframeRendererSystem.render(); -const Renderer& Runtime::getRenderer() const { - return _renderer; + _renderingSystem.endFrame(); } -Renderer& Runtime::getRenderer() { - return _renderer; +const RenderingSystem& Runtime::getRenderingSystem() const { + return _renderingSystem; } +RenderingSystem& Runtime::getRenderingSystem() { + return _renderingSystem; +} -} // namespace shkyera +} diff --git a/src/Runtime/Runtime.hpp b/src/Runtime/Runtime.hpp index fd5584ed..a7a4dabd 100644 --- a/src/Runtime/Runtime.hpp +++ b/src/Runtime/Runtime.hpp @@ -1,44 +1,30 @@ -/** - * @file Runtime.hpp - * - * @brief Contains the declaration of the `Runtime` class, representing the game environment. - */ - #pragma once #include -#include - #include -#include + +#include +#include +#include + +#include namespace shkyera { -/** - * @brief A class representing the game environment. - * - * The `Runtime` class is responsible for managing game objects within the game environment. - */ class Runtime { - public: - /** - * @brief Default constructor for the `Runtime` class. - */ +public: Runtime(std::shared_ptr registry); + void update(); - void run(); - - Renderer& getRenderer(); - const Renderer& getRenderer() const; - - /** - * @brief Default destructor for the `Runtime` class. - */ - ~Runtime() = default; + RenderingSystem& getRenderingSystem(); + const RenderingSystem& getRenderingSystem() const; - private: - Renderer _renderer; +private: std::shared_ptr _registry; + CameraMovementSystem _cameraMovementSystem; + ModelRendererSystem _modelRendererSystem; + RenderingSystem _renderingSystem; + WireframeRendererSystem _wireframeRendererSystem; }; -} // namespace shkyera +} diff --git a/src/Systems/CMakeLists.txt b/src/Systems/CMakeLists.txt new file mode 100644 index 00000000..269b7f01 --- /dev/null +++ b/src/Systems/CMakeLists.txt @@ -0,0 +1,26 @@ +add_library( + Systems + STATIC + + ${CMAKE_CURRENT_LIST_DIR}/CameraMovementSystem.cpp + ${CMAKE_CURRENT_LIST_DIR}/ModelRendererSystem.cpp + ${CMAKE_CURRENT_LIST_DIR}/RenderingSystem.cpp + ${CMAKE_CURRENT_LIST_DIR}/WireframeRendererSystem.cpp +) + +target_include_directories( + Systems + PUBLIC + + ${CMAKE_SOURCE_DIR}/src +) + +target_link_libraries( + Systems + PUBLIC + + glad + glm::glm + InputManager + ECS +) diff --git a/src/Systems/CameraMovementSystem.cpp b/src/Systems/CameraMovementSystem.cpp new file mode 100644 index 00000000..15f1c284 --- /dev/null +++ b/src/Systems/CameraMovementSystem.cpp @@ -0,0 +1,139 @@ +#include +#include +#include +#include + +namespace shkyera { + +constexpr static float MOVEMENT_SPEED = 0.6; +constexpr static float MOUSE_SENSITIVITY = 0.05; + +CameraMovementSystem::CameraMovementSystem(std::shared_ptr registry) + : _registry(registry), _cameraControl(false) { + setupCameraMovement(); +} + +void CameraMovementSystem::update() {} + +void CameraMovementSystem::setupCameraMovement() { + auto& inputManager = InputManager::getInstance(); + + inputManager.registerMouseButtonDownCallback(GLFW_MOUSE_BUTTON_LEFT, [this]() { + _cameraControl = true; + }); + inputManager.registerMouseButtonUpCallback(GLFW_MOUSE_BUTTON_LEFT, [this]() { + _cameraControl = false; + }); + + inputManager.registerKeyCallback(GLFW_KEY_W, [this]() { + auto& cameraTransform = _registry->getComponent(_registry->getCamera()); + + if(_cameraControl) { + glm::vec3 forward; + float yaw = cameraTransform.getOrientation().y; + float pitch = cameraTransform.getOrientation().x; + + forward.x = cos(yaw) * cos(pitch); + forward.y = sin(pitch); + forward.z = sin(yaw) * cos(pitch); + forward = glm::normalize(forward); + + cameraTransform.setPosition(cameraTransform.getPosition() + forward * MOVEMENT_SPEED); + } + }); + + inputManager.registerKeyCallback(GLFW_KEY_S, [this]() { + auto& cameraTransform = _registry->getComponent(_registry->getCamera()); + + if(_cameraControl) { + glm::vec3 backward; + float yaw = cameraTransform.getOrientation().y; + float pitch = cameraTransform.getOrientation().x; + + backward.x = -cos(yaw) * cos(pitch); + backward.y = -sin(pitch); + backward.z = -sin(yaw) * cos(pitch); + backward = glm::normalize(backward); + + cameraTransform.setPosition(cameraTransform.getPosition() + backward * MOVEMENT_SPEED); + } + }); + + inputManager.registerKeyCallback(GLFW_KEY_A, [this]() { + auto& cameraTransform = _registry->getComponent(_registry->getCamera()); + + if(_cameraControl) { + glm::vec3 left; + float yaw = cameraTransform.getOrientation().y; + + left.x = -sin(yaw); + left.y = 0.0f; + left.z = cos(yaw); + left = glm::normalize(left); + + cameraTransform.setPosition(cameraTransform.getPosition() + left * MOVEMENT_SPEED); + } + }); + + inputManager.registerKeyCallback(GLFW_KEY_D, [this]() { + auto& cameraTransform = _registry->getComponent(_registry->getCamera()); + + if(_cameraControl) { + glm::vec3 right; + float yaw = cameraTransform.getOrientation().y; + + right.x = sin(yaw); + right.y = 0.0f; + right.z = -cos(yaw); + right = glm::normalize(right); + + cameraTransform.setPosition(cameraTransform.getPosition() + right * MOVEMENT_SPEED); + } + }); + + + inputManager.registerKeyCallback(GLFW_KEY_Q, [this]() { + auto& cameraTransform = _registry->getComponent(_registry->getCamera()); + + if(_cameraControl) { + glm::vec3 down = glm::vec3(0.0f, -1.0f, 0.0f); // Down direction in world space + cameraTransform.setPosition(cameraTransform.getPosition() + down * MOVEMENT_SPEED); + } + }); + + inputManager.registerKeyCallback(GLFW_KEY_E, [this]() { + auto& cameraTransform = _registry->getComponent(_registry->getCamera()); + + if(_cameraControl) { + glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); // Up direction in world space + cameraTransform.setPosition(cameraTransform.getPosition() + up * MOVEMENT_SPEED); + } + }); + + inputManager.registerMouseMoveCallback([this](double xPos, double yPos) { + auto& cameraTransform = _registry->getComponent(_registry->getCamera()); + + static double lastX = xPos, lastY = yPos; + + float xOffset = static_cast(xPos - lastX) * MOUSE_SENSITIVITY; + float yOffset = static_cast(lastY - yPos) * MOUSE_SENSITIVITY; + + lastX = xPos; + lastY = yPos; + + if(_cameraControl) { + glm::vec3 orientation = cameraTransform.getOrientation(); + orientation.y -= glm::radians(xOffset); + orientation.x += glm::radians(yOffset); + + if (orientation.x > glm::radians(89.0f)) + orientation.x = glm::radians(89.0f); + if (orientation.x < glm::radians(-89.0f)) + orientation.x = glm::radians(-89.0f); + + cameraTransform.getOrientation() = orientation; + } + }); +} + +} diff --git a/src/Systems/CameraMovementSystem.hpp b/src/Systems/CameraMovementSystem.hpp new file mode 100644 index 00000000..3117bfa4 --- /dev/null +++ b/src/Systems/CameraMovementSystem.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include + +namespace shkyera { + +class CameraMovementSystem { +public: + CameraMovementSystem(std::shared_ptr registry); + void update(); + +private: + void setupCameraMovement(); + + bool _cameraControl; + Entity _camera; + std::shared_ptr _registry; +}; + +} diff --git a/src/Systems/ModelRendererSystem.cpp b/src/Systems/ModelRendererSystem.cpp new file mode 100644 index 00000000..36423459 --- /dev/null +++ b/src/Systems/ModelRendererSystem.cpp @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include + +namespace shkyera { + +ModelRendererSystem::ModelRendererSystem(std::shared_ptr registry) + : _registry(registry) { + auto modelVertexShader = AssetManager::getInstance().getAsset("resources/shaders/vertex/model.glsl", Shader::Type::Vertex); + auto modelFragmentShader = AssetManager::getInstance().getAsset("resources/shaders/fragment/uber.glsl", Shader::Type::Fragment); + + _modelShaderProgram.attachShader(modelVertexShader); + _modelShaderProgram.attachShader(modelFragmentShader); + _modelShaderProgram.link(); +} + +void ModelRendererSystem::render() { + const auto& cameraTransform = _registry->getComponent(_registry->getCamera()); + const glm::mat4& viewMatrix = _registry->getComponent(_registry->getCamera()).getViewMatrix(cameraTransform); + const glm::mat4& projectionMatrix = _registry->getComponent(_registry->getCamera()).getProjectionMatrix(); + + _modelShaderProgram.use(); + _modelShaderProgram.setUniform("viewMatrix", viewMatrix); + _modelShaderProgram.setUniform("projectionMatrix", projectionMatrix); + _modelShaderProgram.setUniform("viewPos", cameraTransform.getPosition()); + + int lightIndex = 0; + for(const auto& [entity, pointLightComponent] : _registry->getComponentSet()) { + const auto& transformComponent = _registry->getComponent(entity); + _modelShaderProgram.setUniform("lights[" + std::to_string(lightIndex) + "].position", transformComponent.getPosition()); + _modelShaderProgram.setUniform("lights[" + std::to_string(lightIndex) + "].ambient", pointLightComponent.ambient); + _modelShaderProgram.setUniform("lights[" + std::to_string(lightIndex) + "].diffuse", pointLightComponent.diffuse); + _modelShaderProgram.setUniform("lights[" + std::to_string(lightIndex) + "].specular", pointLightComponent.specular); + ++lightIndex; + } + _modelShaderProgram.setUniform("numLights", lightIndex); + + for (const auto& [entity, modelComponent] : _registry->getComponentSet()) { + const auto& transformComponent = _registry->getComponent(entity); + _modelShaderProgram.setUniform("modelMatrix", transformComponent.getTransformMatrix()); + + const Material* material = modelComponent.getMaterial(); + if (material) { + _modelShaderProgram.setUniform("material.diffuse", material->getDiffuseColor()); + _modelShaderProgram.setUniform("material.specular", material->getSpecularColor()); + _modelShaderProgram.setUniform("material.shininess", material->getShininess()); + } + + modelComponent.updateImpl(); + } + + _modelShaderProgram.stopUsing(); +} + +} diff --git a/src/Systems/ModelRendererSystem.hpp b/src/Systems/ModelRendererSystem.hpp new file mode 100644 index 00000000..b29a1618 --- /dev/null +++ b/src/Systems/ModelRendererSystem.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include + + +namespace shkyera { + +class ModelRendererSystem { +public: + ModelRendererSystem(std::shared_ptr registry); + void render(); + +private: + std::shared_ptr _registry; + ShaderProgram _modelShaderProgram; +}; + +} diff --git a/src/Systems/RenderingSystem.cpp b/src/Systems/RenderingSystem.cpp new file mode 100644 index 00000000..1272ef26 --- /dev/null +++ b/src/Systems/RenderingSystem.cpp @@ -0,0 +1,76 @@ +#include + +#include +#include + +namespace shkyera { + +RenderingSystem::RenderingSystem(std::shared_ptr registry) + : _registry(registry), _width(0), _height(0) { + setupFramebuffer(); +} + +void RenderingSystem::startFrame() { + glBindFramebuffer(GL_FRAMEBUFFER, _fbo); + glViewport(0, 0, (GLsizei)_width, (GLsizei)_height); + glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); +} + +void RenderingSystem::endFrame() { + glDisable(GL_DEPTH_TEST); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void RenderingSystem::setSize(uint32_t width, uint32_t height) { + if(width == _width && height == _height) { + return; + } + + _width = width; + _height = height; + + float aspectRatio = static_cast(width) / height; + _registry->getComponent(_registry->getCamera()).aspectRatio = aspectRatio; + + glBindTexture(GL_TEXTURE_2D, _textureColorBuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)_width, (GLsizei)_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glBindRenderbuffer(GL_RENDERBUFFER, _rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, (GLsizei)_width, (GLsizei)_height); +} + +GLuint RenderingSystem::getTexture() const { + return _textureColorBuffer; +} + +void RenderingSystem::setupFramebuffer() { + glGenFramebuffers(1, &_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, _fbo); + + glGenTextures(1, &_textureColorBuffer); + glBindTexture(GL_TEXTURE_2D, _textureColorBuffer); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei)_width, (GLsizei)_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureColorBuffer, 0); + + glGenRenderbuffers(1, &_rbo); + glBindRenderbuffer(GL_RENDERBUFFER, _rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, (GLsizei)_width, (GLsizei)_height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _rbo); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << std::endl; + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void RenderingSystem::cleanupFramebuffer() { + glDeleteFramebuffers(1, &_fbo); + glDeleteTextures(1, &_textureColorBuffer); + glDeleteRenderbuffers(1, &_rbo); +} + +} diff --git a/src/Systems/RenderingSystem.hpp b/src/Systems/RenderingSystem.hpp new file mode 100644 index 00000000..c326f956 --- /dev/null +++ b/src/Systems/RenderingSystem.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include + + +namespace shkyera { + +class RenderingSystem { +public: + RenderingSystem(std::shared_ptr registry); + + void startFrame(); + void endFrame(); + void setSize(uint32_t width, uint32_t height); + GLuint getTexture() const; + +private: + void setupFramebuffer(); + void cleanupFramebuffer(); + + std::shared_ptr _registry; + GLuint _fbo, _textureColorBuffer, _rbo; + uint32_t _width, _height; +}; + +} diff --git a/src/Systems/WireframeRendererSystem.cpp b/src/Systems/WireframeRendererSystem.cpp new file mode 100644 index 00000000..494eafc3 --- /dev/null +++ b/src/Systems/WireframeRendererSystem.cpp @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include + +namespace shkyera { + +WireframeRendererSystem::WireframeRendererSystem(std::shared_ptr registry) + : _registry(registry) { + + auto wireframeVertexShader = AssetManager::getInstance().getAsset("resources/shaders/vertex/model.glsl", Shader::Type::Vertex); + auto wireframeFragmentShader = AssetManager::getInstance().getAsset("resources/shaders/fragment/color.glsl", Shader::Type::Fragment); + + _wireframeShaderProgram.attachShader(wireframeVertexShader); + _wireframeShaderProgram.attachShader(wireframeFragmentShader); + _wireframeShaderProgram.link(); +} + +void WireframeRendererSystem::render() { + const auto& cameraTransform = _registry->getComponent(_registry->getCamera()); + const glm::mat4& viewMatrix = _registry->getComponent(_registry->getCamera()).getViewMatrix(cameraTransform); + const glm::mat4& projectionMatrix = _registry->getComponent(_registry->getCamera()).getProjectionMatrix(); + + _wireframeShaderProgram.use(); + _wireframeShaderProgram.setUniform("viewMatrix", viewMatrix); + _wireframeShaderProgram.setUniform("projectionMatrix", projectionMatrix); + + static const glm::vec3 wireframeColor{0.08, 0.7, 0.15}; + + for (const auto& [entity, wireframeComponent] : _registry->getComponentSet()) { + const auto& transformComponent = _registry->getComponent(entity); + _wireframeShaderProgram.setUniform("modelMatrix", transformComponent.getTransformMatrix()); + _wireframeShaderProgram.setUniform("fixedColor", wireframeColor); + wireframeComponent.updateImpl(); + } + + _wireframeShaderProgram.stopUsing(); +} + +} diff --git a/src/Systems/WireframeRendererSystem.hpp b/src/Systems/WireframeRendererSystem.hpp new file mode 100644 index 00000000..aebad5d4 --- /dev/null +++ b/src/Systems/WireframeRendererSystem.hpp @@ -0,0 +1,21 @@ + +#pragma once + +#include +#include +#include + + +namespace shkyera { + +class WireframeRendererSystem { +public: + WireframeRendererSystem(std::shared_ptr registry); + void render(); + +private: + std::shared_ptr _registry; + ShaderProgram _wireframeShaderProgram; +}; + +} diff --git a/src/main.cpp b/src/main.cpp index 4ec1565d..b1bbbafd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,32 +7,85 @@ #include #include #include +#include #include #include +#include #include #include + #include void loadScene(std::shared_ptr registry) { using namespace shkyera; - auto teapot = registry->addEntity(); - registry->addComponent(teapot); + auto camera = registry->getCamera(); + registry->addComponent(camera); + registry->addComponent(camera); + + // Cylinder entity with its model + auto cylinder = registry->addEntity(); + registry->addComponent(cylinder); + registry->getComponent(cylinder).setPosition({3, 0, -3}); + registry->addComponent(cylinder); + registry->getComponent(cylinder).setName("Cylinder"); + registry->addComponent(cylinder); + registry->getComponent(cylinder).setMesh(std::shared_ptr(Mesh::Factory::createCylinder())); + registry->getComponent(cylinder).setMaterial(std::make_shared()); + + // Corresponding wireframe entity for Cylinder + auto cylinderWireframe = registry->addEntity(); + registry->addComponent(cylinderWireframe); + registry->getComponent(cylinderWireframe).setPosition({3, 3, -3}); // Offset by 2 units on x-axis + registry->addComponent(cylinderWireframe); + registry->getComponent(cylinderWireframe).setName("Cylinder Wireframe"); + registry->addComponent(cylinderWireframe); + registry->getComponent(cylinderWireframe).setWireframe(std::shared_ptr(Wireframe::Factory::createCylinder())); + + // Cube entity with its model + auto cube = registry->addEntity(); + registry->addComponent(cube); + registry->getComponent(cube).setPosition({3, 0, 0}); + registry->addComponent(cube); + registry->getComponent(cube).setName("Cube"); + registry->addComponent(cube); + registry->getComponent(cube).setMesh(std::shared_ptr(Mesh::Factory::createCube())); + registry->getComponent(cube).setMaterial(std::make_shared()); - registry->addComponent(teapot); - registry->getComponent(teapot).setName("Teapot"); + // Corresponding wireframe entity for Cube + auto cubeWireframe = registry->addEntity(); + registry->addComponent(cubeWireframe); + registry->getComponent(cubeWireframe).setPosition({3, 3, 0}); // Offset by 2 units on x-axis + registry->addComponent(cubeWireframe); + registry->getComponent(cubeWireframe).setName("Cube Wireframe"); + registry->addComponent(cubeWireframe); + registry->getComponent(cubeWireframe).setWireframe(std::shared_ptr(Wireframe::Factory::createCube())); - registry->addComponent(teapot); - registry->getComponent(teapot).setMesh(AssetManager::getInstance().getAsset("resources/models/teapot.obj")); - registry->getComponent(teapot).setMaterial(std::make_shared()); + // Sphere entity with its model + auto sphere = registry->addEntity(); + registry->addComponent(sphere); + registry->getComponent(sphere).setPosition({3, 0, 3}); + registry->addComponent(sphere); + registry->getComponent(sphere).setName("Sphere"); + registry->addComponent(sphere); + registry->getComponent(sphere).setMesh(std::shared_ptr(Mesh::Factory::createSphere())); + registry->getComponent(sphere).setMaterial(std::make_shared()); + // Corresponding wireframe entity for Sphere + auto sphereWireframe = registry->addEntity(); + registry->addComponent(sphereWireframe); + registry->getComponent(sphereWireframe).setPosition({3, 3, 3}); // Offset by 2 units on x-axis + registry->addComponent(sphereWireframe); + registry->getComponent(sphereWireframe).setName("Sphere Wireframe"); + registry->addComponent(sphereWireframe); + registry->getComponent(sphereWireframe).setWireframe(std::shared_ptr(Wireframe::Factory::createSphere())); + + // Point light entity auto pointLight = registry->addEntity(); registry->addComponent(pointLight); - registry->getComponent(pointLight).setPosition({-50, 50, 50}); - + registry->getComponent(pointLight).setPosition({-2, 5, 5}); registry->addComponent(pointLight); registry->getComponent(pointLight).setName("Point Light"); - registry->addComponent(pointLight); } @@ -47,5 +100,6 @@ int main() { while (!ui.shouldClose()) { ui.draw(); } + return 0; } diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index de7323cc..1a5c0775 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -11,7 +11,7 @@ add_library( ${CMAKE_CURRENT_LIST_DIR}/Components/TransformComponentUI.cpp ${CMAKE_CURRENT_LIST_DIR}/Components/ModelComponentUI.cpp ${CMAKE_CURRENT_LIST_DIR}/Components/PointLightComponentUI.cpp - ${CMAKE_CURRENT_LIST_DIR}/Components/CameraComponentUI.cpp + ${CMAKE_CURRENT_LIST_DIR}/Components/WireframeComponentUI.cpp ${CMAKE_CURRENT_LIST_DIR}/Widgets/PreviewWidget.cpp ${CMAKE_CURRENT_LIST_DIR}/Widgets/ObjectsWidget.cpp @@ -40,6 +40,7 @@ target_link_libraries( Components AssetManager InputManager + Systems imgui glfw diff --git a/src/ui/Components/CameraComponentUI.cpp b/src/ui/Components/CameraComponentUI.cpp deleted file mode 100644 index 2170ddb7..00000000 --- a/src/ui/Components/CameraComponentUI.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include - -namespace shkyera { - -void CameraComponentUI::draw() { - ImGui::Image((ImTextureID)Image::ICON_COMPONENT_TRANSFORM.getTextureId(), - ImVec2(16, 16)); - ImGui::SameLine(); - if (ImGui::TreeNodeEx("Camera", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::TreePop(); - } -} - -} // namespace shkyera diff --git a/src/ui/Components/CameraComponentUI.hpp b/src/ui/Components/CameraComponentUI.hpp deleted file mode 100644 index 901d64f8..00000000 --- a/src/ui/Components/CameraComponentUI.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "imgui.h" - -#include -#include - -namespace shkyera { - -class CameraComponentUI : public ComponentUI { - public: - void draw() override; -}; - -} diff --git a/src/ui/Components/WireframeComponentUI.cpp b/src/ui/Components/WireframeComponentUI.cpp new file mode 100644 index 00000000..243c8253 --- /dev/null +++ b/src/ui/Components/WireframeComponentUI.cpp @@ -0,0 +1,36 @@ +#include "imgui.h" + +#include +#include +#include +#include + +namespace shkyera { + +WireframeComponentUI::WireframeComponentUI(WireframeComponent* wireframeComponent) : + _wireframeSelector("Mesh"), _wireframeComponent(wireframeComponent) { + + const auto& defaultWireframeFilePath = AssetManager::getInstance().getFilePath(wireframeComponent->getWireframe()); + if (defaultWireframeFilePath) { + _wireframeSelector.setFile(File(std::filesystem::path(*defaultWireframeFilePath))); + } + + _wireframeSelector.setUpdateCallback([this](const auto& file) { + _wireframeComponent->setWireframe(AssetManager::getInstance().getAsset(file.getPath())); + }); + + _wireframeSelector.setClearCallback([this]() { + _wireframeComponent->setWireframe(nullptr); + }); +} + +void WireframeComponentUI::draw() { + ImGui::Image((ImTextureID)Image::ICON_FILES_IMAGE.getTextureId(), ImVec2(16, 16)); + ImGui::SameLine(); + if (ImGui::TreeNodeEx("Wireframe", ImGuiTreeNodeFlags_DefaultOpen)) { + _wireframeSelector.draw(); + ImGui::TreePop(); + } +} + +} // namespace shkyera diff --git a/src/ui/Components/WireframeComponentUI.hpp b/src/ui/Components/WireframeComponentUI.hpp new file mode 100644 index 00000000..a052df27 --- /dev/null +++ b/src/ui/Components/WireframeComponentUI.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include + +namespace shkyera { + +class WireframeComponentUI : public ComponentUI { +public: + WireframeComponentUI(WireframeComponent* wireframeComponent); + + void draw() override; + +private: + WireframeComponent* _wireframeComponent; + FileSelector _wireframeSelector; +}; + +} diff --git a/src/ui/UI.cpp b/src/ui/UI.cpp index f4cada41..b4b96818 100644 --- a/src/ui/UI.cpp +++ b/src/ui/UI.cpp @@ -23,7 +23,7 @@ namespace shkyera { -UI::UI(std::shared_ptr registry) : _open(true), _registry(registry) { +UI::UI(std::shared_ptr registry) : _open(true), _registry(std::move(registry)) { initialize(); } @@ -102,8 +102,9 @@ void UI::initializeWidgets() { auto assetsWidget = std::make_unique("Assets"); assetsWidget->setDirectory("resources"); _widgets.emplace_back(std::move(assetsWidget)); - + auto sceneWidget = std::make_unique(_registry); + _widgets.emplace_back(std::move(sceneWidget)); } diff --git a/src/ui/UI.hpp b/src/ui/UI.hpp index 4906c86b..64a99534 100644 --- a/src/ui/UI.hpp +++ b/src/ui/UI.hpp @@ -15,6 +15,7 @@ #include #include + namespace shkyera { /** diff --git a/src/ui/widgets/PropertiesWidget.cpp b/src/ui/widgets/PropertiesWidget.cpp index 49bfb76f..56b223ca 100644 --- a/src/ui/widgets/PropertiesWidget.cpp +++ b/src/ui/widgets/PropertiesWidget.cpp @@ -5,11 +5,13 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -71,6 +73,13 @@ void PropertiesWidget::setupComponentsUI() { _componentsUi.emplace_back(std::move(componentUi)); } + if(_registry->hasComponent(*_selectedEntity)) { + auto &component = _registry->getComponent(*_selectedEntity); + auto componentUi = std::make_unique(&component); + + _componentsUi.emplace_back(std::move(componentUi)); + } + if(_registry->hasComponent(*_selectedEntity)) { auto &component = _registry->getComponent(*_selectedEntity); auto componentUi = std::make_unique(&component); @@ -97,6 +106,13 @@ void PropertiesWidget::drawNewComponentMenu() { ImGui::CloseCurrentPopup(); } + if (ImGui::Selectable("Wireframe")) { + _registry->addComponent(*_selectedEntity); + + setupComponentsUI(); + ImGui::CloseCurrentPopup(); + } + if (ImGui::Selectable("Point Light")) { _registry->addComponent(*_selectedEntity); setupComponentsUI(); diff --git a/src/ui/widgets/SceneWidget.cpp b/src/ui/widgets/SceneWidget.cpp index 2250281c..56b1ca45 100644 --- a/src/ui/widgets/SceneWidget.cpp +++ b/src/ui/widgets/SceneWidget.cpp @@ -11,25 +11,23 @@ #include #include + namespace shkyera { -SceneWidget::SceneWidget(std::shared_ptr registry) : Widget("Scene"), _runtime(registry) {} +SceneWidget::SceneWidget(std::shared_ptr registry) : Widget("Scene"), _runtime(std::move(registry)) {} void SceneWidget::draw() { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); ImGui::Begin(_name.c_str(), nullptr, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - adjustSize(); - _runtime.run(); + + auto renderSize = ImGui::GetContentRegionAvail(); + _runtime.getRenderingSystem().setSize(renderSize.x, renderSize.y); + _runtime.update(); - ImGui::Image((void*)(intptr_t)_runtime.getRenderer().getTexture(), _renderSize); + ImGui::Image((void*)(intptr_t)_runtime.getRenderingSystem().getTexture(), renderSize); ImGui::End(); ImGui::PopStyleVar(); } -void SceneWidget::adjustSize() { - _renderSize = ImGui::GetContentRegionAvail(); - _runtime.getRenderer().setSize(_renderSize.x, _renderSize.y); -} - } // namespace shkyera diff --git a/src/ui/widgets/SceneWidget.hpp b/src/ui/widgets/SceneWidget.hpp index dfad0485..e69b837c 100644 --- a/src/ui/widgets/SceneWidget.hpp +++ b/src/ui/widgets/SceneWidget.hpp @@ -30,14 +30,8 @@ class SceneWidget : public Widget { */ virtual void draw() override; - /** - * @brief Adjust the size of the scene widget. - */ - void adjustSize(); - private: Runtime _runtime; - ImVec2 _renderSize; }; } // namespace shkyera