From a3b6c3b34607e9d9af61933171ab98ebb4da0cfb Mon Sep 17 00:00:00 2001 From: Derek Christ Date: Sat, 22 Oct 2022 23:26:34 +0200 Subject: [PATCH] Make scene loading part of gltf loader --- src/CMakeLists.txt | 2 +- src/Controller.cpp | 33 +++++---- src/Controller.h | 23 ++++-- src/Scene.cpp | 148 ------------------------------------- src/Scene.h | 36 --------- src/ShaderProgram_.cpp | 162 ----------------------------------------- src/ShaderProgram_.h | 46 ------------ src/camera.h | 2 + src/gltf.h | 51 +++++++++++++ src/gltf_loader.cpp | 126 +++++++++++++++++++++++++++----- src/gltf_loader.h | 41 +---------- src/scene.cpp | 75 +++++++++++++++++++ src/scene.h | 26 +++++++ src/shader.cpp | 8 +- 14 files changed, 306 insertions(+), 473 deletions(-) delete mode 100644 src/Scene.cpp delete mode 100644 src/Scene.h delete mode 100644 src/ShaderProgram_.cpp delete mode 100644 src/ShaderProgram_.h create mode 100644 src/gltf.h create mode 100644 src/scene.cpp create mode 100644 src/scene.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2a8beae..d7e67f8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,7 @@ add_library(fever_engine Controller.cpp Window.cpp Light.cpp - Scene.cpp + scene.cpp FrameBuffer.cpp Helper.cpp util/Log.cpp diff --git a/src/Controller.cpp b/src/Controller.cpp index df76872..439175f 100644 --- a/src/Controller.cpp +++ b/src/Controller.cpp @@ -23,29 +23,34 @@ using namespace entt::literals; Controller::Controller() - : m_scene(m_shader_cache), - m_gameWindow(std::make_shared()), + : m_gameWindow(std::make_shared()), m_postProcessFrameBuffer(m_gameWindow->dimensions().first, m_gameWindow->dimensions().second, - post_processing_shader) + post_processing_shader), + m_gltf_loader{.image_cache = m_image_cache, + .material_cache = m_material_cache, + .mesh_cache = m_mesh_cache, + .shader_cache = m_shader_cache, + .scene_cache = m_scene_cache, + .gltf_mesh_cache = m_gltf_mesh_cache, + .gltf_node_cache = m_gltf_node_cache}, + m_gltf_cache(m_gltf_loader) { - // if (!gltf.cameras.empty()) { - // auto const &gltf_camera = gltf.cameras.at(0); + // std::filesystem::path document_path("Lantern/glTF-Binary/Lantern.glb"); + std::filesystem::path document_path("ABeautifulGame.glb"); + entt::hashed_string document_hash(document_path.c_str()); - // assert(gltf_camera.type == fx::gltf::Camera::Type::Perspective); - // auto const &perspective = gltf_camera.perspective; + entt::resource gltf_document = + m_gltf_cache.load(document_hash, document_path).first->second; - // m_camera = std::make_shared(perspective.yfov, perspective.aspectRatio); - // } else { - // m_camera = std::make_shared(90., m_gameWindow->aspectRatio()); - // } + m_scene = gltf_document->default_scene.value().handle(); } void Controller::run() { updateExposure(post_processing_shader); - entt::hashed_string shader_hash (Material::SHADER_NAME.data()); + entt::hashed_string shader_hash(Material::SHADER_NAME.data()); auto standard_material_shader = m_shader_cache.load(shader_hash, Material::SHADER_NAME).first->second; @@ -74,7 +79,7 @@ void Controller::run() auto const &mouse_cursor_input = m_gameWindow->mouse_cursor_input(); static constexpr auto MICROSECONDS_PER_SECOND = 1'000'000; - m_scene.update( + m_scene->update( std::chrono::microseconds(static_cast(m_deltaTime * MICROSECONDS_PER_SECOND)), key_input, mouse_cursor_input, @@ -87,7 +92,7 @@ void Controller::run() m_postProcessFrameBuffer.bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - Render::render(m_scene.registry()); + Render::render(m_scene->registry()); Framebuffer::unbind(); m_postProcessFrameBuffer.drawOnEntireScreen(); diff --git a/src/Controller.h b/src/Controller.h index 189ffda..8fc1d47 100644 --- a/src/Controller.h +++ b/src/Controller.h @@ -1,14 +1,15 @@ #pragma once #include "FrameBuffer.h" -#include "Scene.h" +#include "scene.h" #include "shader.h" +#include "gltf_loader.h" +#include #include #include #include #include -#include class Window; class Scene; @@ -29,18 +30,28 @@ private: void update_window_dimensions(); std::shared_ptr m_gameWindow; - + Shader skybox_shader{"skybox", "data/shaders"}; Shader post_processing_shader{"post_processing", "data/shaders"}; Framebuffer m_postProcessFrameBuffer; - entt::resource_cache m_shader_cache; - static constexpr unsigned MAX_FPS = 60; - Scene m_scene; + std::shared_ptr m_scene; double m_deltaTime{}; float m_exposure = 1.0; + + // Resource caches + entt::resource_cache m_image_cache; + entt::resource_cache m_material_cache; + entt::resource_cache m_mesh_cache; + entt::resource_cache m_scene_cache; + entt::resource_cache m_shader_cache; + entt::resource_cache m_gltf_mesh_cache; + entt::resource_cache m_gltf_node_cache; + + GltfLoader m_gltf_loader; + entt::resource_cache m_gltf_cache; }; diff --git a/src/Scene.cpp b/src/Scene.cpp deleted file mode 100644 index 4155f10..0000000 --- a/src/Scene.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include "Scene.h" -#include "camera.h" -#include "mesh.h" -#include "name.h" -#include "relationship.h" -#include "shader.h" -#include "transform.h" -#include "util/Log.h" - -using namespace entt::literals; - -// TODO: make scene initialization part of gltf loader as seen in bevy -Scene::Scene(entt::resource_cache &shader_cache) -{ - GltfLoader loader{.image_cache = m_image_cache, - .material_cache = m_material_cache, - .mesh_cache = m_mesh_cache, - .shader_cache = shader_cache, - .gltf_mesh_cache = m_gltf_mesh_cache, - .gltf_node_cache = m_gltf_node_cache, - .gltf_scene_cache = m_gltf_scene_cache}; - - entt::resource_cache gltf_resource_cache{loader}; - - std::filesystem::path document_path("ABeautifulGame.glb"); - // std::filesystem::path document_path("Lantern/glTF-Binary/Lantern.glb"); - entt::hashed_string document_hash(document_path.c_str()); - - entt::resource gltf_document = - gltf_resource_cache.load(document_hash, document_path).first->second; - - auto default_scene = gltf_document->default_scene; - - // Spawn an entity for every node in scene - for (auto const &node : default_scene->nodes) { - std::function)> spawn_node = - [this, &spawn_node](GltfNode const &node, std::optional parent) { - auto entity = m_registry.create(); - m_registry.emplace(entity, node.name); - m_registry.emplace(entity, node.transform); - m_registry.emplace(entity, GlobalTransform{}); - - if (parent.has_value()) { - m_registry.emplace(entity, Parent{.parent = parent.value()}); - } - - std::vector child_entities; - - auto mesh = node.mesh; - if (mesh.has_value()) { - for (auto const &primitive : mesh.value()->primitives) { - auto mesh_entity = m_registry.create(); - m_registry.emplace(mesh_entity, Parent{.parent = entity}); - m_registry.emplace(mesh_entity, Transform{}); - m_registry.emplace(mesh_entity, GlobalTransform{}); - m_registry.emplace>(mesh_entity, primitive.mesh); - m_registry.emplace>(mesh_entity, - primitive.material); - - child_entities.push_back(mesh_entity); - } - } - - // Spawn child nodes - for (auto const &child : node.children) { - auto child_entity = spawn_node(child, entity); - child_entities.push_back(child_entity); - } - - m_registry.emplace(entity, Children{.children = child_entities}); - return entity; - }; - - spawn_node(node, {}); - } - - auto mesh_view = m_registry.view>(); - for (auto [entity, mesh] : mesh_view.each()) { - m_registry.emplace(entity, GpuMesh(mesh)); - - // Remove Mesh resource as it is no longer needed. - m_registry.erase>(entity); - } - - auto material_view = m_registry.view>(); - for (auto [entity, material] : material_view.each()) { - m_registry.emplace(entity, GpuMaterial(material)); - - // Remove Material resource as it is no longer needed. - m_registry.erase>(entity); - } - - // Spawn the camera - auto entity = m_registry.create(); - m_registry.emplace(entity, "Camera"); - m_registry.emplace(entity, Transform{.translation = glm::vec3(0.0, 0.25, -1.0)}); - m_registry.emplace(entity, GlobalTransform{}); - m_registry.emplace(entity, Camera{.projection = Camera::Perspective{}}); -} - -void Scene::update(std::chrono::duration delta, - KeyInput const &key_input, - MouseCursorInput const &mouse_cursor_input, - float aspect_ratio, - bool cursor_catched) -{ - { - // Update GlobalTransform components - // TODO: Only do this when the Transform changed. - auto root_transform_view = - m_registry.view(entt::exclude); - auto transform_view = m_registry.view(); - - for (auto [entity, transform, global_transform] : root_transform_view.each()) { - global_transform = transform; - - auto parent_global_transform = global_transform; - if (auto *children = m_registry.try_get(entity)) { - for (auto child : children->children) { - std::function - transform_propagate = [this, &transform_propagate, &transform_view]( - entt::entity entity, - GlobalTransform parent_global_transform) { - auto [transform, global_transform, parent] = transform_view.get(entity); - global_transform.transform = parent_global_transform.transform * - GlobalTransform(transform).transform; - - if (auto *children = m_registry.try_get(entity)) { - for (auto child : children->children) { - transform_propagate(child, global_transform); - } - } - }; - - transform_propagate(child, parent_global_transform); - } - } - } - } - - Camera::aspect_ratio_update(m_registry, aspect_ratio); - Camera::keyboard_movement(m_registry, key_input, delta); - if (cursor_catched) { - Camera::mouse_orientation(m_registry, mouse_cursor_input); - } - -} diff --git a/src/Scene.h b/src/Scene.h deleted file mode 100644 index e5c1330..0000000 --- a/src/Scene.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "Window.h" -#include "gltf_loader.h" -#include "material.h" -#include "mesh.h" - -#include -#include - -class Shader; - -class Scene -{ -public: - Scene(entt::resource_cache &shader_cache); - - void update(std::chrono::duration delta_time, - KeyInput const &key_input, - MouseCursorInput const &mouse_cursor_input, - float aspect_ratio, - bool cursor_catched); - - auto registry() -> entt::registry & { return m_registry; } - -private: - entt::registry m_registry; - - // Resource caches - entt::resource_cache m_image_cache; - entt::resource_cache m_material_cache; - entt::resource_cache m_mesh_cache; - entt::resource_cache m_gltf_mesh_cache; - entt::resource_cache m_gltf_node_cache; - entt::resource_cache m_gltf_scene_cache; // May be moved out of Scene -}; diff --git a/src/ShaderProgram_.cpp b/src/ShaderProgram_.cpp deleted file mode 100644 index dff1e18..0000000 --- a/src/ShaderProgram_.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include "ShaderProgram.h" -#include "util/Log.h" - -#include -#include -#include - -ShaderProgram::ShaderProgram(Prototype prototype) : m_shaderProgramId(glCreateProgram()) -{ - std::string vertexShaderSource = parse(prototype.vertexPath); - std::string fragmentShaderSource = parse(prototype.fragmentPath); - - GLuint vertexShader = compile(vertexShaderSource, GL_VERTEX_SHADER); - GLuint fragmentShader = compile(fragmentShaderSource, GL_FRAGMENT_SHADER); - - glAttachShader(m_shaderProgramId, vertexShader); - glAttachShader(m_shaderProgramId, fragmentShader); - - glLinkProgram(m_shaderProgramId); - - GLint isLinked = 0; - glGetProgramiv(m_shaderProgramId, GL_LINK_STATUS, &isLinked); - if (isLinked == 0) { - Log::logger().warn(R"(Failed to link shaderProgram "{}", "{}")", - prototype.vertexPath, - prototype.fragmentPath); - } - -#ifdef NDEBUG - glDetachShader(m_shaderProgramId, vertexShader); - glDetachShader(m_shaderProgramId, fragmentShader); - - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); -#endif - - Log::logger().trace(R"(Loaded shaderprogram "{}".)", prototype.name); -} - -ShaderProgram::~ShaderProgram() -{ - glDeleteProgram(m_shaderProgramId); -} - -void ShaderProgram::bind() const -{ - glUseProgram(m_shaderProgramId); -} - -void ShaderProgram::unbind() -{ - glUseProgram(0); -} - -auto ShaderProgram::parse(const std::filesystem::path &path) -> std::string -{ - std::fstream file; - file.open(path, std::ios::in); - - if (!file.is_open()) { - Log::logger().critical(R"(Shader "{}" not found!)", path.string()); - std::terminate(); - } - - return {(std::istreambuf_iterator(file)), (std::istreambuf_iterator())}; -} - -auto ShaderProgram::compile(const std::string &shaderSource, GLenum type) -> GLuint -{ - GLuint shaderId = glCreateShader(type); - const char *src = shaderSource.c_str(); - glShaderSource(shaderId, 1, &src, nullptr); - glCompileShader(shaderId); - - int result{}; - glGetShaderiv(shaderId, GL_COMPILE_STATUS, &result); - - if (result != GL_TRUE) { - int length{}; - glGetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &length); - - std::string message; - message.reserve(static_cast(length)); - - glGetShaderInfoLog(shaderId, length, &length, message.data()); - Log::logger().error("Shader compilation failed: {}", message); - - return 0; - } - - return shaderId; -} - -auto ShaderProgram::retrieveUniformLocation(std::string_view uniform_name) const -> GLint -{ - if (m_uniformLocationCache.find(uniform_name.data()) != m_uniformLocationCache.end()) { - return m_uniformLocationCache[uniform_name.data()]; - } - - GLint location = glGetUniformLocation(m_shaderProgramId, uniform_name.data()); - - if (location != -1) { - m_uniformLocationCache[uniform_name.data()] = location; - } else { - Log::logger().warn(R"(Uniform "{}" not found.)", uniform_name); - } - - return location; -} - -void ShaderProgram::set_uniform(const std::string &name, bool value) const -{ - GLint location = retrieveUniformLocation(name); - glUniform1i(location, (int)value); -} - -void ShaderProgram::set_uniform(const std::string &name, int value) const -{ - GLint location = retrieveUniformLocation(name); - glUniform1i(location, value); -} - -void ShaderProgram::set_uniform(const std::string &name, unsigned int value) const -{ - GLint location = retrieveUniformLocation(name); - glUniform1ui(location, value); -} - -void ShaderProgram::set_uniform(const std::string &name, float value) const -{ - GLint location = retrieveUniformLocation(name); - glUniform1f(location, value); -} - -void ShaderProgram::set_uniform(const std::string &name, glm::vec2 vector) const -{ - GLint location = retrieveUniformLocation(name); - glUniform2f(location, vector.x, vector.y); -} - -void ShaderProgram::set_uniform(const std::string &name, glm::vec3 vector) const -{ - GLint location = retrieveUniformLocation(name); - glUniform3f(location, vector.x, vector.y, vector.z); -} - -void ShaderProgram::set_uniform(const std::string &name, glm::mat3 matrix) const -{ - GLint location = retrieveUniformLocation(name); - glUniformMatrix3fv(location, 1, GL_FALSE, glm::value_ptr(matrix)); -} - -void ShaderProgram::set_uniform(const std::string &name, glm::mat4 matrix) const -{ - GLint location = retrieveUniformLocation(name); - glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(matrix)); -} - -auto ShaderProgram::getShaderProgramId() const -> GLuint -{ - return m_shaderProgramId; -} diff --git a/src/ShaderProgram_.h b/src/ShaderProgram_.h deleted file mode 100644 index 304beca..0000000 --- a/src/ShaderProgram_.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -class ShaderProgram -{ -public: - struct Prototype - { - std::string name; - std::string vertexPath; - std::string fragmentPath; - }; - - ShaderProgram(Prototype prototype); - ~ShaderProgram(); - - void bind() const; - static void unbind(); - - auto retrieveUniformLocation(std::string_view uniform_name) const -> GLint; - - // May be rewritten... - void set_uniform(const std::string &name, bool value) const; - void set_uniform(const std::string &name, int value) const; - void set_uniform(const std::string &name, unsigned int value) const; - void set_uniform(const std::string &name, float value) const; - void set_uniform(const std::string &name, glm::vec2 vector) const; - void set_uniform(const std::string &name, glm::vec3 vector) const; - void set_uniform(const std::string &name, glm::mat3 matrix) const; - void set_uniform(const std::string &name, glm::mat4 matrix) const; - - auto getShaderProgramId() const -> GLuint; - -private: - static auto parse(const std::filesystem::path &path) -> std::string; - static auto compile(const std::string &shaderSource, GLenum type) -> GLuint; - - GLuint m_shaderProgramId; - mutable std::unordered_map m_uniformLocationCache; -}; diff --git a/src/camera.h b/src/camera.h index d7ef1b3..d9bad00 100644 --- a/src/camera.h +++ b/src/camera.h @@ -20,6 +20,8 @@ struct Camera static constexpr float SPEED = 0.5; static constexpr float ACCELERATION = 5.0; + static constexpr glm::vec3 DEFAULT_POSITION = glm::vec3(0.0, 0.25, -1.0); + struct Perspective { float fov = DEFAULT_FOV; diff --git a/src/gltf.h b/src/gltf.h new file mode 100644 index 0000000..2f8d049 --- /dev/null +++ b/src/gltf.h @@ -0,0 +1,51 @@ +#pragma once + +#include "material.h" +#include "mesh.h" +#include "transform.h" + +#include +#include +#include +#include + +class Mesh; +class Scene; +class Material; +class Image; + +struct GltfPrimitive +{ + entt::resource mesh; + entt::resource material; +}; + +struct GltfMesh +{ + std::vector primitives; +}; + +struct GltfCamera +{ + std::variant projection; +}; + +struct GltfNode +{ + std::string name; + Transform transform; + std::optional> mesh; + std::optional camera; + std::vector> children; +}; + +struct Gltf +{ + std::vector> materials; + std::vector> meshes; + std::vector> nodes; + std::vector> scenes; + + std::optional> default_scene; + fx::gltf::Document document; +}; diff --git a/src/gltf_loader.cpp b/src/gltf_loader.cpp index 7162276..eddbc90 100644 --- a/src/gltf_loader.cpp +++ b/src/gltf_loader.cpp @@ -1,5 +1,9 @@ #include "gltf_loader.h" +#include "camera.h" #include "definitions/attribute_locations.h" +#include "name.h" +#include "relationship.h" +#include "scene.h" #include "util/Log.h" #include @@ -74,7 +78,8 @@ static auto load_material(fx::gltf::Material const &material, std::filesystem::path const &document_path, entt::resource_cache &material_cache, entt::resource_cache &image_cache, - entt::resource_cache &shader_cache) -> entt::resource + entt::resource_cache &shader_cache) + -> entt::resource { auto base_color_texture_id = material.pbrMetallicRoughness.baseColorTexture.index; auto normal_texture_id = material.normalTexture.index; @@ -315,6 +320,23 @@ auto GltfLoader::operator()(std::filesystem::path const &document_path) -> resul return {}; }(); + auto camera = [this, &node, &gltf]() -> std::optional { + if (node.camera != -1) { + auto const &camera = gltf.cameras.at(node.camera); + + if (camera.type != fx::gltf::Camera::Type::Perspective) { + Log::logger().warn("Only perspective projections supported."); + } + + // Only perspective supported until now + GltfCamera gltf_camera{.projection = camera.perspective}; + + return {gltf_camera}; + } + + return {}; + }(); + glm::vec3 translation(node.translation[0], node.translation[1], node.translation[2]); glm::quat rotation(node.rotation[3], node.rotation[0], node.rotation[1], node.rotation[2]); glm::vec3 scale(node.scale[0], node.scale[1], node.scale[2]); @@ -326,12 +348,14 @@ auto GltfLoader::operator()(std::filesystem::path const &document_path) -> resul } entt::hashed_string node_hash(node.name.c_str()); - entt::resource node_resource = - gltf_node_cache - .load(node_hash, - GltfNode{ - .name = node.name, .transform = transform, .mesh = mesh, .children = {}}) - .first->second; + entt::resource node_resource = gltf_node_cache + .load(node_hash, + GltfNode{.name = node.name, + .transform = transform, + .mesh = mesh, + .camera = camera, + .children = {}}) + .first->second; nodes_map.emplace(i, node_resource); } @@ -356,35 +380,103 @@ auto GltfLoader::operator()(std::filesystem::path const &document_path) -> resul } // Load scenes - std::vector> scenes; - for (auto const &scene : gltf.scenes) { + std::vector> scenes; + for (auto const &gltf_scene : gltf.scenes) { // Get nodes by hash std::vector> nodes; - nodes.reserve(scene.nodes.size()); + nodes.reserve(gltf_scene.nodes.size()); - for (auto node_id : scene.nodes) { + for (auto node_id : gltf_scene.nodes) { auto const &node = gltf.nodes.at(node_id); entt::hashed_string node_hash(node.name.c_str()); nodes.push_back(gltf_node_cache[node_hash]); } - if (scene.name.empty()) { + if (gltf_scene.name.empty()) { Log::logger().warn("glTF scene has no name."); } - entt::hashed_string scene_hash(scene.name.c_str()); - entt::resource scene_resource = - gltf_scene_cache.load(scene_hash, GltfScene{.nodes = std::move(nodes)}).first->second; + entt::registry registry; + + // Spawn an entity for every node in scene + for (auto const &node : nodes) { + std::function)> spawn_node = + [this, &spawn_node, ®istry](GltfNode const &node, + std::optional parent) { + auto entity = registry.create(); + registry.emplace(entity, node.name); + registry.emplace(entity, node.transform); + registry.emplace(entity, GlobalTransform{}); + + if (parent.has_value()) { + registry.emplace(entity, Parent{.parent = parent.value()}); + } + + std::vector child_entities; + + auto mesh = node.mesh; + if (mesh.has_value()) { + for (auto const &primitive : mesh.value()->primitives) { + auto mesh_entity = registry.create(); + registry.emplace(mesh_entity, Parent{.parent = entity}); + registry.emplace(mesh_entity, Transform{}); + registry.emplace(mesh_entity, GlobalTransform{}); + registry.emplace>(mesh_entity, primitive.mesh); + registry.emplace>(mesh_entity, + primitive.material); + + child_entities.push_back(mesh_entity); + } + } + + auto camera = node.camera; + if (camera.has_value()) { + auto perspective = + std::get(camera.value().projection); + Camera::Perspective camera_perspective{.fov = perspective.yfov, + .aspect_ratio = + perspective.aspectRatio, + .near = perspective.znear, + .far = perspective.zfar}; + registry.emplace(entity, Camera{.projection = camera_perspective}); + } + + // Spawn child nodes + for (auto const &child : node.children) { + auto child_entity = spawn_node(child, entity); + child_entities.push_back(child_entity); + } + + registry.emplace(entity, Children{.children = child_entities}); + return entity; + }; + + spawn_node(node, {}); + } + + auto camera_view = registry.view(); + if (camera_view.empty()) { + // Spawn default camera + auto entity = registry.create(); + registry.emplace(entity, "Camera"); + registry.emplace(entity, Transform{.translation = Camera::DEFAULT_POSITION}); + registry.emplace(entity, GlobalTransform{}); + registry.emplace(entity, Camera{.projection = Camera::Perspective{}}); + } + + entt::hashed_string scene_hash(gltf_scene.name.c_str()); + entt::resource scene_resource = + scene_cache.load(scene_hash, Scene{std::move(registry)}).first->second; scenes.push_back(scene_resource); } // Default scene - entt::resource default_scene = [&gltf, &scenes]() { + auto default_scene = [&gltf, &scenes]() -> std::optional> { if (gltf.scene != -1) { return scenes.at(gltf.scene); } - return scenes.at(0); + return {}; }(); return std::make_shared(Gltf{.materials = std::move(materials), diff --git a/src/gltf_loader.h b/src/gltf_loader.h index 186d417..5c82bc6 100644 --- a/src/gltf_loader.h +++ b/src/gltf_loader.h @@ -1,8 +1,6 @@ #pragma once -#include "image.h" -#include "material.h" -#include "mesh.h" +#include "gltf.h" #include "transform.h" #include @@ -11,41 +9,6 @@ static constexpr auto MAX_SIZE = 512 * 1024 * 1024; -struct GltfPrimitive -{ - entt::resource mesh; - entt::resource material; -}; - -struct GltfMesh -{ - std::vector primitives; -}; - -struct GltfNode -{ - std::string name; - Transform transform; - std::optional> mesh; - std::vector> children; -}; - -struct GltfScene { - std::vector> nodes; -}; - -// Move to own file. -struct Gltf -{ - std::vector> materials; - std::vector> meshes; - std::vector> nodes; - std::vector> scenes; - - entt::resource default_scene; - fx::gltf::Document document; -}; - struct GltfLoader final { using result_type = std::shared_ptr; @@ -56,8 +19,8 @@ struct GltfLoader final entt::resource_cache &material_cache; entt::resource_cache &mesh_cache; entt::resource_cache &shader_cache; + entt::resource_cache &scene_cache; entt::resource_cache &gltf_mesh_cache; entt::resource_cache &gltf_node_cache; - entt::resource_cache &gltf_scene_cache; }; diff --git a/src/scene.cpp b/src/scene.cpp new file mode 100644 index 0000000..7187a30 --- /dev/null +++ b/src/scene.cpp @@ -0,0 +1,75 @@ +#include "scene.h" +#include "camera.h" +#include "mesh.h" +#include "name.h" +#include "relationship.h" +#include "shader.h" +#include "transform.h" +#include "util/Log.h" + +Scene::Scene(entt::registry registry) : m_registry(std::move(registry)) +{ + auto mesh_view = m_registry.view>(); + for (auto [entity, mesh] : mesh_view.each()) { + m_registry.emplace(entity, GpuMesh(mesh)); + + // Remove Mesh resource as it is no longer needed. + m_registry.erase>(entity); + } + + auto material_view = m_registry.view>(); + for (auto [entity, material] : material_view.each()) { + m_registry.emplace(entity, GpuMaterial(material)); + + // Remove Material resource as it is no longer needed. + m_registry.erase>(entity); + } +} + +void Scene::update(std::chrono::duration delta, + KeyInput const &key_input, + MouseCursorInput const &mouse_cursor_input, + float aspect_ratio, + bool cursor_catched) +{ + { + // Update GlobalTransform components + // TODO: Only do this when the Transform changed. + auto root_transform_view = + m_registry.view(entt::exclude); + auto transform_view = m_registry.view(); + + for (auto [entity, transform, global_transform] : root_transform_view.each()) { + global_transform = transform; + + auto parent_global_transform = global_transform; + if (auto *children = m_registry.try_get(entity)) { + for (auto child : children->children) { + std::function + transform_propagate = [this, &transform_propagate, &transform_view]( + entt::entity entity, + GlobalTransform parent_global_transform) { + auto [transform, global_transform, parent] = transform_view.get(entity); + global_transform.transform = parent_global_transform.transform * + GlobalTransform(transform).transform; + + if (auto *children = m_registry.try_get(entity)) { + for (auto child : children->children) { + transform_propagate(child, global_transform); + } + } + }; + + transform_propagate(child, parent_global_transform); + } + } + } + } + + Camera::aspect_ratio_update(m_registry, aspect_ratio); + Camera::keyboard_movement(m_registry, key_input, delta); + if (cursor_catched) { + Camera::mouse_orientation(m_registry, mouse_cursor_input); + } +} diff --git a/src/scene.h b/src/scene.h new file mode 100644 index 0000000..309dbea --- /dev/null +++ b/src/scene.h @@ -0,0 +1,26 @@ +#pragma once + +#include "input.h" +#include "gltf.h" + +#include +#include + +class Shader; + +class Scene +{ +public: + Scene(entt::registry registry); + + void update(std::chrono::duration delta_time, + KeyInput const &key_input, + MouseCursorInput const &mouse_cursor_input, + float aspect_ratio, + bool cursor_catched); + + auto registry() -> entt::registry & { return m_registry; } + +private: + entt::registry m_registry; +}; diff --git a/src/shader.cpp b/src/shader.cpp index ec2e66c..5f2b759 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -33,11 +33,11 @@ Shader::Shader(std::string_view name, std::filesystem::path const &directory) } #ifdef NDEBUG - glDetachShader(m_ShaderId, vertexShader); - glDetachShader(m_ShaderId, fragmentShader); + glDetachShader(program, vertex_shader); + glDetachShader(program, fragment_shader); - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); + glDeleteShader(vertex_shader); + glDeleteShader(fragment_shader); #endif Log::logger().trace(R"(Loaded Shader "{}")", name);