diff --git a/Assets/Materials/base_mat.icm b/Assets/Materials/base_mat.material.json similarity index 100% rename from Assets/Materials/base_mat.icm rename to Assets/Materials/base_mat.material.json diff --git a/Assets/Models/cube.obj b/Assets/Meshes/cube.obj similarity index 100% rename from Assets/Models/cube.obj rename to Assets/Meshes/cube.obj diff --git a/Assets/Models/sphere.obj b/Assets/Meshes/sphere.obj similarity index 100% rename from Assets/Models/sphere.obj rename to Assets/Meshes/sphere.obj diff --git a/Assets/Shaders/frag_uniforms.glsl b/Assets/Shaders/glsl/frag_uniforms.glsl similarity index 100% rename from Assets/Shaders/frag_uniforms.glsl rename to Assets/Shaders/glsl/frag_uniforms.glsl diff --git a/Assets/Shaders/lastpass.fs b/Assets/Shaders/glsl/lastpass.fs similarity index 100% rename from Assets/Shaders/lastpass.fs rename to Assets/Shaders/glsl/lastpass.fs diff --git a/Assets/Shaders/lastpass.vs b/Assets/Shaders/glsl/lastpass.vs similarity index 100% rename from Assets/Shaders/lastpass.vs rename to Assets/Shaders/glsl/lastpass.vs diff --git a/Assets/Shaders/normal.fs b/Assets/Shaders/glsl/normal.fs similarity index 100% rename from Assets/Shaders/normal.fs rename to Assets/Shaders/glsl/normal.fs diff --git a/Assets/Shaders/pbr.fs b/Assets/Shaders/glsl/pbr.fs similarity index 100% rename from Assets/Shaders/pbr.fs rename to Assets/Shaders/glsl/pbr.fs diff --git a/Assets/Shaders/phong.fs b/Assets/Shaders/glsl/phong.fs similarity index 100% rename from Assets/Shaders/phong.fs rename to Assets/Shaders/glsl/phong.fs diff --git a/Assets/Shaders/picking.fs b/Assets/Shaders/glsl/picking.fs similarity index 100% rename from Assets/Shaders/picking.fs rename to Assets/Shaders/glsl/picking.fs diff --git a/Assets/Shaders/skinning.vs b/Assets/Shaders/glsl/skinning.vs similarity index 93% rename from Assets/Shaders/skinning.vs rename to Assets/Shaders/glsl/skinning.vs index 085b09cb..7245dda7 100644 --- a/Assets/Shaders/skinning.vs +++ b/Assets/Shaders/glsl/skinning.vs @@ -14,7 +14,6 @@ layout (location = 6) in vec4 bone_weights; uniform mat4 model; uniform mat4 bonesTransformMatrices[MAX_BONES]; -uniform mat4 bonesOffsetMatrices[MAX_BONES]; out vec3 fnormal; out vec3 ftangent; @@ -46,7 +45,7 @@ void main() { break; } - mat4 finalBonesMatrix = bonesTransformMatrices[bone_ids[i]] * bonesOffsetMatrices[bone_ids[i]]; + mat4 finalBonesMatrix = bonesTransformMatrices[bone_ids[i]]; totalPosition += finalBonesMatrix * vec4(vertex, 1.0f) * bone_weights[i]; diff --git a/Assets/Shaders/skybox.fs b/Assets/Shaders/glsl/skybox.fs similarity index 100% rename from Assets/Shaders/skybox.fs rename to Assets/Shaders/glsl/skybox.fs diff --git a/Assets/Shaders/skybox.vs b/Assets/Shaders/glsl/skybox.vs similarity index 100% rename from Assets/Shaders/skybox.vs rename to Assets/Shaders/glsl/skybox.vs diff --git a/Assets/Shaders/solid.fs b/Assets/Shaders/glsl/solid.fs similarity index 100% rename from Assets/Shaders/solid.fs rename to Assets/Shaders/glsl/solid.fs diff --git a/Assets/Shaders/vert_uniforms.glsl b/Assets/Shaders/glsl/vert_uniforms.glsl similarity index 100% rename from Assets/Shaders/vert_uniforms.glsl rename to Assets/Shaders/glsl/vert_uniforms.glsl diff --git a/Assets/Shaders/lastpass.shader.json b/Assets/Shaders/lastpass.shader.json new file mode 100644 index 00000000..fa584148 --- /dev/null +++ b/Assets/Shaders/lastpass.shader.json @@ -0,0 +1,10 @@ +[ + { + "stage": "vertex", + "source": "glsl/lastpass.vs" + }, + { + "stage": "fragment", + "source": "glsl/lastpass.fs" + } +] \ No newline at end of file diff --git a/Assets/Shaders/normal.shader.json b/Assets/Shaders/normal.shader.json new file mode 100644 index 00000000..d3cc80d5 --- /dev/null +++ b/Assets/Shaders/normal.shader.json @@ -0,0 +1,10 @@ +[ + { + "stage": "vertex", + "source": "glsl/skinning.vs" + }, + { + "stage": "fragment", + "source": "glsl/normal.fs" + } +] \ No newline at end of file diff --git a/Assets/Shaders/pbr.shader.json b/Assets/Shaders/pbr.shader.json new file mode 100644 index 00000000..259a1796 --- /dev/null +++ b/Assets/Shaders/pbr.shader.json @@ -0,0 +1,10 @@ +[ + { + "stage": "vertex", + "source": "glsl/skinning.vs" + }, + { + "stage": "fragment", + "source": "glsl/pbr.fs" + } +] \ No newline at end of file diff --git a/Assets/Shaders/phong.shader.json b/Assets/Shaders/phong.shader.json new file mode 100644 index 00000000..158f01e4 --- /dev/null +++ b/Assets/Shaders/phong.shader.json @@ -0,0 +1,10 @@ +[ + { + "stage": "vertex", + "source": "glsl/skinning.vs" + }, + { + "stage": "fragment", + "source": "glsl/phong.fs" + } +] \ No newline at end of file diff --git a/Assets/Shaders/picking.shader.json b/Assets/Shaders/picking.shader.json new file mode 100644 index 00000000..606a78aa --- /dev/null +++ b/Assets/Shaders/picking.shader.json @@ -0,0 +1,10 @@ +[ + { + "stage": "vertex", + "source": "glsl/skinning.vs" + }, + { + "stage": "fragment", + "source": "glsl/picking.fs" + } +] \ No newline at end of file diff --git a/Assets/Shaders/skybox.shader.json b/Assets/Shaders/skybox.shader.json new file mode 100644 index 00000000..a5634f61 --- /dev/null +++ b/Assets/Shaders/skybox.shader.json @@ -0,0 +1,10 @@ +[ + { + "stage": "vertex", + "source": "glsl/skybox.vs" + }, + { + "stage": "fragment", + "source": "glsl/skybox.fs" + } +] \ No newline at end of file diff --git a/Assets/Shaders/solid.shader.json b/Assets/Shaders/solid.shader.json new file mode 100644 index 00000000..33324d75 --- /dev/null +++ b/Assets/Shaders/solid.shader.json @@ -0,0 +1,10 @@ +[ + { + "stage": "vertex", + "source": "glsl/skinning.vs" + }, + { + "stage": "fragment", + "source": "glsl/solid.fs" + } +] \ No newline at end of file diff --git a/ICE/Assets/CMakeLists.txt b/ICE/Assets/CMakeLists.txt index a3352f0e..77bb5578 100644 --- a/ICE/Assets/CMakeLists.txt +++ b/ICE/Assets/CMakeLists.txt @@ -7,7 +7,12 @@ add_library(${PROJECT_NAME} STATIC) target_sources(${PROJECT_NAME} PRIVATE src/AssetBank.cpp - src/AssetPath.cpp) + src/AssetPath.cpp + src/Shader.cpp + src/Model.cpp + src/Material.cpp + src/GPURegistry.cpp + src/Texture.cpp) target_link_libraries(${PROJECT_NAME} PUBLIC diff --git a/ICE/Assets/include/AssetBank.h b/ICE/Assets/include/AssetBank.h index 54600e16..f9492ca7 100644 --- a/ICE/Assets/include/AssetBank.h +++ b/ICE/Assets/include/AssetBank.h @@ -30,7 +30,7 @@ struct AssetBankEntry { class AssetBank { public: - AssetBank(const std::shared_ptr& factory); + AssetBank(); template std::shared_ptr getAsset(AssetUID uid) { @@ -167,6 +167,5 @@ class AssetBank { std::unordered_map nameMapping; std::unordered_map resources; AssetLoader loader; - std::shared_ptr graphics_factory; }; } // namespace ICE diff --git a/ICE/Assets/include/AssetLoader.h b/ICE/Assets/include/AssetLoader.h index 75d25cc2..d3a6d6d0 100644 --- a/ICE/Assets/include/AssetLoader.h +++ b/ICE/Assets/include/AssetLoader.h @@ -35,8 +35,8 @@ class AssetLoader { private: std::unordered_map< std::type_index, - std::variant>, std::shared_ptr>, std::shared_ptr>, - std::shared_ptr>, std::shared_ptr>>> + std::variant>, std::shared_ptr>, std::shared_ptr>, + std::shared_ptr>, std::shared_ptr>, std::shared_ptr>>> loaders; }; } // namespace ICE diff --git a/ICE/Assets/include/GPURegistry.h b/ICE/Assets/include/GPURegistry.h new file mode 100644 index 00000000..4e7fb661 --- /dev/null +++ b/ICE/Assets/include/GPURegistry.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include +#include + +#include + +#include "Asset.h" +#include "AssetBank.h" +#include "Mesh.h" +#include "Shader.h" +#include "Texture.h" + +namespace ICE { +class GPURegistry { + public: + GPURegistry(const std::shared_ptr &factory, const std::shared_ptr &bank); + + AssetUID getUID(const AssetPath &path) const { return m_asset_bank->getUID(path); } + std::shared_ptr getMaterial(const AssetPath &path) { return m_asset_bank->getAsset(getUID(path)); } + std::shared_ptr getMaterial(AssetUID id) { return m_asset_bank->getAsset(id); } + std::shared_ptr getShader(AssetUID id); + std::shared_ptr getShader(const AssetPath &path) { return getShader(getUID(path)); } + AABB getMeshAABB(AssetUID id) { return m_asset_bank->getAsset(id)->getBoundingBox(); } + std::shared_ptr getMesh(AssetUID id); + std::shared_ptr getMesh(const AssetPath &path) { return getMesh(getUID(path)); } + std::shared_ptr getTexture2D(AssetUID id); + std::shared_ptr getTexture2D(const AssetPath &path) { return getTexture2D(getUID(path)); } + std::shared_ptr getCubemap(AssetUID id); + + private: + std::unordered_map> m_shader_programs; + std::unordered_map> m_gpu_meshes; + std::unordered_map> m_gpu_tex2d; + std::unordered_map> m_gpu_cubemaps; + + std::shared_ptr m_graphics_factory; + std::shared_ptr m_asset_bank; +}; +} // namespace ICE diff --git a/ICE/Graphics/include/Material.h b/ICE/Assets/include/Material.h similarity index 100% rename from ICE/Graphics/include/Material.h rename to ICE/Assets/include/Material.h diff --git a/ICE/Graphics/include/Mesh.h b/ICE/Assets/include/Mesh.h similarity index 65% rename from ICE/Graphics/include/Mesh.h rename to ICE/Assets/include/Mesh.h index da0ae0de..a605b519 100644 --- a/ICE/Graphics/include/Mesh.h +++ b/ICE/Assets/include/Mesh.h @@ -1,70 +1,56 @@ -// -// Created by Thomas Ibanez on 16.11.20. -// - -#pragma once - -#include -#include - -#include -#include - -#include "VertexArray.h" - -namespace ICE { - -constexpr int MAX_BONES_PER_VERTEX = 4; -constexpr int MAX_BONES = 100; -constexpr int INVALID_BONE_ID = -1; - -struct MeshData { - std::vector vertices; - std::vector normals; - std::vector uvCoords; - std::vector tangents; - std::vector bitangents; - std::vector boneIDs; - std::vector boneWeights; - std::vector indices; -}; - -struct SkinningData { - std::unordered_map boneOffsetMatrices; -}; - -class Mesh : public Asset { - public: - Mesh(const MeshData &data); - Mesh(MeshData &&data); - - const std::vector &getVertices() const; - - const std::vector &getNormals() const; - - const std::vector &getUVCoords() const; - - const std::vector &getIndices() const; - - const std::shared_ptr getVertexArray() const; - void setVertexArray(const std::shared_ptr &vao); - - const AABB &getBoundingBox() const; - - std::string getTypeName() const override; - AssetType getType() const override; - bool usesBones() const { return m_has_bones; } - void setSkinningData(const SkinningData &skinningData) { - m_skinningData = skinningData; - m_has_bones = true; - } - - SkinningData getSkinningData() const { return m_skinningData; } - private: - MeshData m_data; - SkinningData m_skinningData; - bool m_has_bones = false; - std::shared_ptr vertexArray; - AABB boundingBox; -}; +// +// Created by Thomas Ibanez on 16.11.20. +// + +#pragma once + +#include +#include + +#include +#include + +#include "VertexArray.h" + +namespace ICE { + +constexpr int MAX_BONES_PER_VERTEX = 4; +constexpr int MAX_BONES = 100; +constexpr int INVALID_BONE_ID = -1; + +struct MeshData { + std::vector vertices; + std::vector normals; + std::vector uvCoords; + std::vector tangents; + std::vector bitangents; + std::vector boneIDs; + std::vector boneWeights; + std::vector indices; +}; + +class Mesh : public Asset { + public: + Mesh(const MeshData &data); + Mesh(MeshData &&data); + + const MeshData &getMeshData() const { return m_data; } + + const std::vector &getVertices() const; + + const std::vector &getNormals() const; + + const std::vector &getUVCoords() const; + + const std::vector &getIndices() const; + + const AABB &getBoundingBox() const; + + std::string getTypeName() const override; + AssetType getType() const override; + + private: + MeshData m_data; + AABB boundingBox; +}; } // namespace ICE \ No newline at end of file diff --git a/ICE/Graphics/include/Model.h b/ICE/Assets/include/Model.h similarity index 73% rename from ICE/Graphics/include/Model.h rename to ICE/Assets/include/Model.h index 34190164..760536d9 100644 --- a/ICE/Graphics/include/Model.h +++ b/ICE/Assets/include/Model.h @@ -16,28 +16,29 @@ class Model : public Asset { }; struct BoneInfo { - Eigen::Matrix4f finalTransformation; + Eigen::Matrix4f finalTransform; }; struct Skeleton { std::unordered_map boneMapping; std::vector bones; Eigen::Matrix4f globalInverseTransform; + std::vector inverseBindMatrices; }; - Model(const std::vector &nodes, const std::vector> &meshes, const std::vector &materials); + Model(const std::vector &nodes, const std::vector &meshes, const std::vector &materials); std::vector getNodes() const { return m_nodes; } std::vector &getNodes() { return m_nodes; } - std::vector> getMeshes() const { return m_meshes; } - std::vector getMaterialsIDs() const { return m_materials; } + std::vector getMeshes() const { return m_meshes; } + std::vector getMaterialsIDs() const { return m_materials; } AABB getBoundingBox() const { return m_boundingbox; } std::unordered_map getAnimations() const { return m_animations; } Skeleton &getSkeleton() { return m_skeleton; } void setSkeleton(const Skeleton &skeleton) { m_skeleton = skeleton; } void setAnimations(const std::unordered_map &animations) { m_animations = animations; } - void traverse(std::vector> &meshes, std::vector &materials, std::vector &transforms, + void traverse(std::vector &meshes, std::vector &materials, std::vector &transforms, const Eigen::Matrix4f &base_transform = Eigen::Matrix4f::Identity()); AssetType getType() const override { return AssetType::EModel; } @@ -45,8 +46,8 @@ class Model : public Asset { private: std::vector m_nodes; - std::vector> m_meshes; - std::vector m_materials; + std::vector m_meshes; + std::vector m_materials; std::unordered_map m_animations; Skeleton m_skeleton; AABB m_boundingbox{{0, 0, 0}, {0, 0, 0}}; diff --git a/ICE/Assets/include/Shader.h b/ICE/Assets/include/Shader.h new file mode 100644 index 00000000..383ce4b4 --- /dev/null +++ b/ICE/Assets/include/Shader.h @@ -0,0 +1,31 @@ +// +// Created by Thomas Ibanez on 20.11.20. +// + +#pragma once + +#include + +#include + +namespace ICE { +enum ShaderStage { Vertex, Fragment, Geometry, TessControl, TessEval, Compute }; + +// Map of shader stages to their source code {filename, source} +using ShaderSource = std::unordered_map>; + +class Shader : public Asset { + public: + Shader() = default; + Shader(const ShaderSource& sources) : m_sources(sources) {} + + ShaderSource getSources() const { return m_sources; } + + std::string getTypeName() const override; + + AssetType getType() const override; + + private: + ShaderSource m_sources; +}; +} // namespace ICE \ No newline at end of file diff --git a/ICE/Graphics/include/Texture.h b/ICE/Assets/include/Texture.h similarity index 58% rename from ICE/Graphics/include/Texture.h rename to ICE/Assets/include/Texture.h index 6de9653d..1e085892 100644 --- a/ICE/Graphics/include/Texture.h +++ b/ICE/Assets/include/Texture.h @@ -2,12 +2,10 @@ // Created by Thomas Ibanez on 22.12.20. // -#ifndef ICE_TEXTURE_H -#define ICE_TEXTURE_H -#include - +#pragma once #include #include +#include #include #include @@ -21,31 +19,40 @@ enum class TextureType { Tex2D = 0, CubeMap = 1 }; class Texture : public Asset { public: - virtual void bind(uint32_t slot = 0) const = 0; - virtual void setData(void* data, uint32_t size) = 0; - - virtual TextureFormat getFormat() const = 0; - - virtual uint32_t getWidth() const = 0; - virtual uint32_t getHeight() const = 0; + virtual ~Texture() { + if (data_ != nullptr) { + stbi_image_free(data_); + data_ = nullptr; + } + } + const void* data() const { return data_; } - virtual void* getTexture() const = 0; + TextureFormat getFormat() const { return m_format; } + TextureWrap getWrap() const { return m_wrap; } - virtual TextureType getTextureType() const = 0; + uint32_t getWidth() const { return m_width; } + uint32_t getHeight() const { return m_height; } + protected: static void* getDataFromFile(const std::string file, int* width, int* height, int* channels, int force = STBI_default) { stbi_uc* data = stbi_load(file.c_str(), width, height, channels, force); - if(data == nullptr) { + if (data == nullptr) { Logger::Log(Logger::ERROR, "Graphics", "Texture %s could not load: %s", file.c_str(), stbi_failure_reason()); } return data; } + + void* data_ = nullptr; + TextureWrap m_wrap = TextureWrap::Repeat; + TextureFormat m_format = TextureFormat::None; + int m_width = 0; + int m_height = 0; }; class Texture2D : public Texture { public: - virtual TextureWrap getWrap() const = 0; - virtual TextureType getTextureType() const = 0; + Texture2D(const std::string& path); + Texture2D(void* data, int width, int height, TextureFormat fmt); virtual AssetType getType() const override { return AssetType::ETex2D; } virtual std::string getTypeName() const override { return "Texture2D"; } @@ -53,12 +60,10 @@ class Texture2D : public Texture { class TextureCube : public Texture { public: - virtual TextureWrap getWrap() const = 0; - virtual TextureType getTextureType() const = 0; + TextureCube(const std::string& path); + TextureCube(void* data, int width, int height, TextureFormat fmt); virtual AssetType getType() const override { return AssetType::ETexCube; } virtual std::string getTypeName() const override { return "TextureCube"; } }; -} // namespace ICE - -#endif //ICE_TEXTURE_H +} // namespace ICE \ No newline at end of file diff --git a/ICE/Assets/src/AssetBank.cpp b/ICE/Assets/src/AssetBank.cpp index 3ac81f18..3665be7e 100644 --- a/ICE/Assets/src/AssetBank.cpp +++ b/ICE/Assets/src/AssetBank.cpp @@ -8,18 +8,20 @@ #include #include "MaterialLoader.h" +#include "MeshLoader.h" #include "ModelLoader.h" #include "ShaderLoader.h" #include "TextureLoader.h" namespace ICE { -AssetBank::AssetBank(const std::shared_ptr &factory) : graphics_factory(factory) { - loader.AddLoader(std::make_shared(factory)); - loader.AddLoader(std::make_shared(factory)); - loader.AddLoader(std::make_shared(factory, *this)); - loader.AddLoader(std::make_shared(factory)); +AssetBank::AssetBank() { + loader.AddLoader(std::make_shared()); + loader.AddLoader(std::make_shared()); + loader.AddLoader(std::make_shared(*this)); + loader.AddLoader(std::make_shared()); loader.AddLoader(std::make_shared()); + loader.AddLoader(std::make_shared()); } bool AssetBank::nameInUse(const AssetPath &name) { diff --git a/ICE/Assets/src/AssetPath.cpp b/ICE/Assets/src/AssetPath.cpp index 2460372e..67b5dc6b 100644 --- a/ICE/Assets/src/AssetPath.cpp +++ b/ICE/Assets/src/AssetPath.cpp @@ -13,6 +13,7 @@ namespace ICE { std::unordered_map AssetPath::typenames = {{typeid(Texture2D), "Textures"}, {typeid(TextureCube), "CubeMaps"}, + {typeid(Mesh), "Meshes"}, {typeid(Model), "Models"}, {typeid(Material), "Materials"}, {typeid(Shader), "Shaders"}}; diff --git a/ICE/Assets/src/GPURegistry.cpp b/ICE/Assets/src/GPURegistry.cpp new file mode 100644 index 00000000..10513c71 --- /dev/null +++ b/ICE/Assets/src/GPURegistry.cpp @@ -0,0 +1,98 @@ +#include "GPURegistry.h" + +#include + +namespace ICE { +GPURegistry::GPURegistry(const std::shared_ptr &factory, const std::shared_ptr &bank) + : m_graphics_factory(factory), + m_asset_bank(bank) { +} + +std::shared_ptr GPURegistry::getShader(AssetUID id) { + if (m_shader_programs.contains(id)) { + return m_shader_programs[id]; + } else { + auto shader_asset = m_asset_bank->getAsset(id); + if (!shader_asset) { + return nullptr; + } + auto program = m_graphics_factory->createShader(*shader_asset); + m_shader_programs[id] = program; + return program; + } +} + +std::shared_ptr GPURegistry::getMesh(AssetUID id) { + if (m_gpu_meshes.contains(id)) { + return m_gpu_meshes[id]; + } else { + auto mesh_asset = m_asset_bank->getAsset(id); + if (!mesh_asset) { + return nullptr; + } + + auto vertexArray = m_graphics_factory->createVertexArray(); + + auto vertexBuffer = m_graphics_factory->createVertexBuffer(); + auto normalsBuffer = m_graphics_factory->createVertexBuffer(); + auto uvBuffer = m_graphics_factory->createVertexBuffer(); + auto tangentBuffer = m_graphics_factory->createVertexBuffer(); + auto biTangentBuffer = m_graphics_factory->createVertexBuffer(); + auto boneIDBuffer = m_graphics_factory->createVertexBuffer(); + auto boneWeightBuffer = m_graphics_factory->createVertexBuffer(); + auto indexBuffer = m_graphics_factory->createIndexBuffer(); + + auto data = mesh_asset->getMeshData(); + vertexBuffer->putData(BufferUtils::CreateFloatBuffer(data.vertices), 3 * data.vertices.size() * sizeof(float)); + normalsBuffer->putData(BufferUtils::CreateFloatBuffer(data.normals), 3 * data.normals.size() * sizeof(float)); + tangentBuffer->putData(BufferUtils::CreateFloatBuffer(data.tangents), 3 * data.tangents.size() * sizeof(float)); + biTangentBuffer->putData(BufferUtils::CreateFloatBuffer(data.bitangents), 3 * data.bitangents.size() * sizeof(float)); + boneIDBuffer->putData(BufferUtils::CreateIntBuffer(data.boneIDs), 4 * data.boneIDs.size() * sizeof(int)); + boneWeightBuffer->putData(BufferUtils::CreateFloatBuffer(data.boneWeights), 4 * data.boneWeights.size() * sizeof(float)); + uvBuffer->putData(BufferUtils::CreateFloatBuffer(data.uvCoords), 2 * data.uvCoords.size() * sizeof(float)); + indexBuffer->putData(BufferUtils::CreateIntBuffer(data.indices), 3 * data.indices.size() * sizeof(int)); + + vertexArray->pushVertexBuffer(vertexBuffer, 0, 3); + vertexArray->pushVertexBuffer(normalsBuffer, 1, 3); + vertexArray->pushVertexBuffer(uvBuffer, 2, 2); + vertexArray->pushVertexBuffer(tangentBuffer, 3, 3); + vertexArray->pushVertexBuffer(biTangentBuffer, 4, 3); + vertexArray->pushVertexBuffer(boneIDBuffer, 5, 4); + vertexArray->pushVertexBuffer(boneWeightBuffer, 6, 4); + vertexArray->setIndexBuffer(indexBuffer); + + std::shared_ptr gpu_mesh = std::make_shared(vertexArray); + m_gpu_meshes[id] = gpu_mesh; + return gpu_mesh; + } +} + +std::shared_ptr GPURegistry::getTexture2D(AssetUID id) { + if (m_gpu_tex2d.contains(id)) { + return m_gpu_tex2d[id]; + } else { + auto tex_asset = m_asset_bank->getAsset(id); + if (!tex_asset) { + return nullptr; + } + + auto gpu_texture = m_graphics_factory->createTexture2D(*tex_asset); + m_gpu_tex2d[id] = gpu_texture; + return gpu_texture; + } +} + +std::shared_ptr GPURegistry::getCubemap(AssetUID id) { + if (m_gpu_cubemaps.contains(id)) { + return m_gpu_cubemaps[id]; + } else { + auto tex_asset = m_asset_bank->getAsset(id); + if (!tex_asset) { + return nullptr; + } + auto gpu_texture = m_graphics_factory->createTextureCube(*tex_asset); + m_gpu_cubemaps[id] = gpu_texture; + return gpu_texture; + } +} +} // namespace ICE diff --git a/ICE/Graphics/src/Material.cpp b/ICE/Assets/src/Material.cpp similarity index 100% rename from ICE/Graphics/src/Material.cpp rename to ICE/Assets/src/Material.cpp diff --git a/ICE/Graphics/src/Model.cpp b/ICE/Assets/src/Model.cpp similarity index 73% rename from ICE/Graphics/src/Model.cpp rename to ICE/Assets/src/Model.cpp index a7c67410..169ab7da 100644 --- a/ICE/Graphics/src/Model.cpp +++ b/ICE/Assets/src/Model.cpp @@ -1,16 +1,16 @@ #include "Model.h" namespace ICE { -Model::Model(const std::vector &nodes, const std::vector> &meshes, const std::vector &materials) +Model::Model(const std::vector &nodes, const std::vector &meshes, const std::vector &materials) : m_nodes(nodes), m_meshes(meshes), m_materials(materials) { - for (const auto &mesh : meshes) { + /* for (const auto &mesh : meshes) { m_boundingbox = m_boundingbox.unionWith(mesh->getBoundingBox()); - } + }*/ } -void Model::traverse(std::vector> &meshes, std::vector &materials, std::vector &transforms, +void Model::traverse(std::vector &meshes, std::vector &materials, std::vector &transforms, const Eigen::Matrix4f &base_transform) { std::function recursive_traversal = [&](int node_idx, const Eigen::Matrix4f &transform) { auto &node = m_nodes.at(node_idx); @@ -22,11 +22,12 @@ void Model::traverse(std::vector> &meshes, std::vectorusesBones()) { + /* if (mesh->usesBones()) { node_transform = transform; } else { node_transform = transform * node.animatedTransform; - } + }*/ + node_transform = transform * node.animatedTransform; meshes.push_back(mesh); materials.push_back(mtl_id); diff --git a/ICE/Assets/src/Shader.cpp b/ICE/Assets/src/Shader.cpp new file mode 100644 index 00000000..1cb05bfe --- /dev/null +++ b/ICE/Assets/src/Shader.cpp @@ -0,0 +1,13 @@ +#include "Shader.h" + +namespace ICE { + +std::string Shader::getTypeName() const { + return "Shader"; +}; + +AssetType Shader::getType() const { + return AssetType::EShader; +}; + +} // namespace ICE diff --git a/ICE/Assets/src/Texture.cpp b/ICE/Assets/src/Texture.cpp new file mode 100644 index 00000000..36b9e101 --- /dev/null +++ b/ICE/Assets/src/Texture.cpp @@ -0,0 +1,33 @@ +#include "Texture.h" + +namespace ICE { + +Texture2D::Texture2D(const std::string& path) { + int channels = 0; + data_ = getDataFromFile(path, &m_width, &m_height, &channels); + if (channels == 3) { + m_format = TextureFormat::RGB8; + } else if (channels == 4) { + m_format = TextureFormat::RGBA8; + } else if (channels == 1) { + m_format = TextureFormat::MONO8; + } else { + m_format = TextureFormat::None; + } +} +Texture2D::Texture2D(void* data, int width, int height, TextureFormat fmt) { + data_ = data; + m_width = width; + m_height = height; + m_format = fmt; +} + +TextureCube::TextureCube(const std::string& path) { +} +TextureCube::TextureCube(void* data, int width, int height, TextureFormat fmt) { + data_ = data; + m_width = width; + m_height = height; + m_format = fmt; +} +} // namespace ICE diff --git a/ICE/Assets/test/AssetBankTest.cpp b/ICE/Assets/test/AssetBankTest.cpp index 7c7ccd11..83d47857 100644 --- a/ICE/Assets/test/AssetBankTest.cpp +++ b/ICE/Assets/test/AssetBankTest.cpp @@ -5,14 +5,11 @@ #include #include "AssetBank.h" -#include "NoneGraphicsFactory.h" using namespace ICE; - TEST(AssetBankTest, AddedAssetsCanBeRetrieved) { - NoneGraphicsFactory g_fac; - AssetBank ab(std::make_shared(g_fac)); + AssetBank ab; auto mtl = std::make_shared(); ab.addAsset("a_ice_test_mtl", mtl); ASSERT_EQ(ab.getAsset("a_ice_test_mtl"), mtl); @@ -23,19 +20,19 @@ TEST(AssetBankTest, AddedAssetsCanBeRetrieved) { ASSERT_EQ(ab.getAsset("a_ice_test_mesh"), mesh); ASSERT_EQ(ab.getAsset("lel"), nullptr); - auto tex = g_fac.createTexture2D("Not needed for this"); + auto tex = std::make_shared(nullptr, 0, 0, ICE::TextureFormat::SRGB8); ab.addAsset("a_ice_test_tex", tex); ASSERT_EQ(ab.getAsset("a_ice_test_tex"), tex); ASSERT_EQ(ab.getAsset("lil"), nullptr); - auto shader = g_fac.createShader("", ""); + auto shader = std::make_shared(); ab.addAsset("a_ice_test_shader", shader); ASSERT_EQ(ab.getAsset("a_ice_test_shader"), shader); ASSERT_EQ(ab.getAsset("lul"), nullptr); } TEST(AssetBankTest, AssetsCanBeRenamed) { - AssetBank ab(std::make_shared()); + AssetBank ab; auto mtl = std::make_shared(); ab.addAsset("a_ice_test_mtl", mtl); ASSERT_EQ(ab.getAsset("a_ice_test_mtl"), mtl); @@ -47,7 +44,7 @@ TEST(AssetBankTest, AssetsCanBeRenamed) { } TEST(AssetBankTest, GetNameReturnsCorrectName) { - AssetBank ab(std::make_shared()); + AssetBank ab; auto mtl = std::make_shared(); ab.addAsset("a_ice_test_mtl", mtl); ASSERT_EQ(AssetPath("Materials/a_ice_test_mtl"), ab.getName(ab.getUID(AssetPath("Materials/a_ice_test_mtl")))); @@ -55,7 +52,7 @@ TEST(AssetBankTest, GetNameReturnsCorrectName) { } TEST(AssetBankTest, NameInUseBehavesCorrectly) { - AssetBank ab(std::make_shared()); + AssetBank ab; auto mtl = std::make_shared(); ab.addAsset("a_ice_test_mtl", mtl); ASSERT_TRUE(ab.nameInUse(AssetPath::WithTypePrefix("a_ice_test_mtl"))); diff --git a/ICE/Components/include/RenderComponent.h b/ICE/Components/include/RenderComponent.h index f44bb4b9..e5e44d36 100644 --- a/ICE/Components/include/RenderComponent.h +++ b/ICE/Components/include/RenderComponent.h @@ -11,8 +11,9 @@ namespace ICE { struct RenderComponent : public Component { - RenderComponent(AssetUID model_id) : model(model_id) {} - AssetUID model; + RenderComponent(AssetUID mesh_id, AssetUID material_id) : mesh(mesh_id), material(material_id) {} + AssetUID mesh; + AssetUID material; }; } // namespace ICE diff --git a/ICE/Components/include/SkeletonPoseComponent.h b/ICE/Components/include/SkeletonPoseComponent.h new file mode 100644 index 00000000..b68111bd --- /dev/null +++ b/ICE/Components/include/SkeletonPoseComponent.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace ICE { +struct SkeletonPoseComponent : public Component { + AssetUID skeletonModel = NO_ASSET_ID; + std::vector final_bone_matrices; +}; +} // namespace ICE \ No newline at end of file diff --git a/ICE/Components/include/SkinningComponent.h b/ICE/Components/include/SkinningComponent.h new file mode 100644 index 00000000..b7ee5c16 --- /dev/null +++ b/ICE/Components/include/SkinningComponent.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace ICE { +struct SkinningComponent : public Component { + Entity skeleton_entity = 0; +}; +} // namespace ICE \ No newline at end of file diff --git a/ICE/Components/include/TransformComponent.h b/ICE/Components/include/TransformComponent.h index 1ac2de52..1b87c697 100644 --- a/ICE/Components/include/TransformComponent.h +++ b/ICE/Components/include/TransformComponent.h @@ -1,7 +1,3 @@ -// -// Created by Thomas Ibanez on 16.11.20. -// - #pragma once #include @@ -10,53 +6,127 @@ #include "ICEMath.h" namespace ICE { + struct TransformComponent : public Component { - TransformComponent(const Eigen::Vector3f &pos, const Eigen::Vector3f &rot, const Eigen::Vector3f &sca) + TransformComponent(const Eigen::Vector3f& pos = Eigen::Vector3f::Zero(), const Eigen::Quaternionf& rot = Eigen::Quaternionf::Identity(), + const Eigen::Vector3f& sca = Eigen::Vector3f::Ones()) : m_position(pos), m_rotation(rot), m_scale(sca) {} + TransformComponent(const Eigen::Vector3f& pos = Eigen::Vector3f::Zero(), const Eigen::Vector3f& rot = Eigen::Vector3f::Zero(), + const Eigen::Vector3f& sca = Eigen::Vector3f::Ones()) + : m_position(pos), + m_scale(sca) { + setRotationEulerDeg(rot); + } + + TransformComponent(const Eigen::Matrix4f& matrix) { + m_position = matrix.block<3, 1>(0, 3); + + Eigen::Vector3f vX = matrix.block<3, 1>(0, 0); + Eigen::Vector3f vY = matrix.block<3, 1>(0, 1); + Eigen::Vector3f vZ = matrix.block<3, 1>(0, 2); + + m_scale << vX.norm(), vY.norm(), vZ.norm(); + + if (matrix.block<3, 3>(0, 0).determinant() < 0) { + m_scale.x() *= -1.0f; + vX *= -1.0f; // Flip the axis for rotation calculation + } + + vX.normalize(); + vY.normalize(); + vZ.normalize(); + + Eigen::Matrix3f rot_matrix; + rot_matrix << vX, vY, vZ; + + m_rotation = Eigen::Quaternionf(rot_matrix); + } + Eigen::Vector3f getPosition() const { return m_position; } - Eigen::Vector3f getRotation() const { return m_rotation; } + Eigen::Quaternionf getRotation() const { return m_rotation; } Eigen::Vector3f getScale() const { return m_scale; } + Eigen::Vector3f getRotationEulerDeg() const { return m_rotation.toRotationMatrix().eulerAngles(0, 1, 2) * 180.0 / M_PI; } + Eigen::Matrix4f getModelMatrix() const { if (m_dirty) { - m_model_matrix = transformationMatrix(m_position, m_rotation, m_scale); + m_model_matrix = Eigen::Matrix4f::Identity(); + + // Translation + m_model_matrix.block<3, 1>(0, 3) = m_position; + + // Rotation + m_model_matrix.block<3, 3>(0, 0) = m_rotation.toRotationMatrix(); + + // Scale + m_model_matrix.block<3, 3>(0, 0) *= m_scale.asDiagonal(); + m_dirty = false; } return m_model_matrix; } - Eigen::Vector3f &position() { + Eigen::Matrix4f getWorldMatrix() const { + if (m_dirty) { + m_world_matrix = m_parent_matrix * getModelMatrix(); + } + return m_world_matrix; + } + + void updateParentMatrix(const Eigen::Matrix4f& parent_matrix) { + m_parent_matrix = parent_matrix; + m_world_matrix = parent_matrix * getModelMatrix(); + } + + Eigen::Vector3f& position() { m_dirty = true; return m_position; } - Eigen::Vector3f &rotation() { + + Eigen::Quaternionf& rotation() { m_dirty = true; return m_rotation; } - Eigen::Vector3f &scale() { + + Eigen::Vector3f& scale() { m_dirty = true; return m_scale; } - void setPosition(const Eigen::Vector3f &_position) { + void setPosition(const Eigen::Vector3f& position) { + m_dirty = true; + m_position = position; + } + + void setRotation(const Eigen::Quaternionf& rotation) { m_dirty = true; - m_position = _position; + m_rotation = rotation.normalized(); } - void setRotation(const Eigen::Vector3f &_rotation) { + + void setRotationEulerDeg(const Eigen::Vector3f& eulerDeg) { m_dirty = true; - m_rotation = _rotation; + Eigen::Vector3f rad = eulerDeg * M_PI / 180.0; + m_rotation = Eigen::AngleAxisf(rad.x(), Eigen::Vector3f::UnitX()) * Eigen::AngleAxisf(rad.y(), Eigen::Vector3f::UnitY()) + * Eigen::AngleAxisf(rad.z(), Eigen::Vector3f::UnitZ()); } - void setScale(const Eigen::Vector3f &_scale) { + + void setScale(const Eigen::Vector3f& scale) { m_dirty = true; - m_scale = _scale; + m_scale = scale; } private: - Eigen::Vector3f m_position, m_rotation, m_scale; - mutable Eigen::Matrix4f m_model_matrix; + Eigen::Vector3f m_position; + Eigen::Quaternionf m_rotation; + Eigen::Vector3f m_scale; + + mutable Eigen::Matrix4f m_model_matrix = Eigen::Matrix4f::Identity(); + mutable Eigen::Matrix4f m_parent_matrix = Eigen::Matrix4f::Identity(); + mutable Eigen::Matrix4f m_world_matrix = Eigen::Matrix4f::Identity(); mutable bool m_dirty = true; }; + } // namespace ICE diff --git a/ICE/Core/include/ICEEngine.h b/ICE/Core/include/ICEEngine.h index 7ba3c3de..c7482fad 100644 --- a/ICE/Core/include/ICEEngine.h +++ b/ICE/Core/include/ICEEngine.h @@ -29,6 +29,7 @@ class ICEEngine { std::shared_ptr getCamera(); std::shared_ptr getAssetBank(); + std::shared_ptr getGPURegistry(); Entity getSelected() const; @@ -65,6 +66,5 @@ class ICEEngine { std::chrono::steady_clock::time_point lastFrameTime; EngineConfig config; - Registry registry; }; } // namespace ICE diff --git a/ICE/Core/src/ICEEngine.cpp b/ICE/Core/src/ICEEngine.cpp index f49aa776..1d54da41 100644 --- a/ICE/Core/src/ICEEngine.cpp +++ b/ICE/Core/src/ICEEngine.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include namespace ICE { ICEEngine::ICEEngine() : camera(std::make_shared(60, 16.f / 9.f, 0.1f, 100000)), config(EngineConfig::LoadFromFile()) { @@ -43,10 +45,14 @@ void ICEEngine::step() { void ICEEngine::setupScene(const std::shared_ptr &camera_) { auto renderer = std::make_shared(api, m_graphics_factory); - auto rs = std::make_shared(api, m_graphics_factory, project->getCurrentScene()->getRegistry(), project->getAssetBank()); + auto rs = std::make_shared(api, m_graphics_factory, project->getCurrentScene()->getRegistry(), project->getGPURegistry()); + auto as = std::make_shared(project->getCurrentScene()->getRegistry(), project->getAssetBank()); + auto sgs = std::make_shared(project->getCurrentScene()); rs->setCamera(camera_); rs->setRenderer(renderer); project->getCurrentScene()->getRegistry()->addSystem(rs); + project->getCurrentScene()->getRegistry()->addSystem(as); + project->getCurrentScene()->getRegistry()->addSystem(sgs); camera = camera_; auto [w, h] = m_window->getSize(); renderer->resize(w, h); @@ -60,6 +66,11 @@ std::shared_ptr ICEEngine::getAssetBank() { return project->getAssetBank(); } +std::shared_ptr ICEEngine::getGPURegistry() { + return project->getGPURegistry(); +} + + std::shared_ptr ICEEngine::getApi() const { return api; } diff --git a/ICE/Graphics/CMakeLists.txt b/ICE/Graphics/CMakeLists.txt index 86100b0d..726804a5 100644 --- a/ICE/Graphics/CMakeLists.txt +++ b/ICE/Graphics/CMakeLists.txt @@ -9,10 +9,8 @@ target_sources(${PROJECT_NAME} PRIVATE src/PerspectiveCamera.cpp src/OrthographicCamera.cpp src/ForwardRenderer.cpp - src/Material.cpp src/Mesh.cpp - src/Model.cpp - src/GeometryPass.cpp) + src/GeometryPass.cpp "include/GPUMesh.h" "include/GPUTexture.h") target_link_libraries(${PROJECT_NAME} PUBLIC diff --git a/ICE/Graphics/include/GPUMesh.h b/ICE/Graphics/include/GPUMesh.h new file mode 100644 index 00000000..f97a786d --- /dev/null +++ b/ICE/Graphics/include/GPUMesh.h @@ -0,0 +1,14 @@ +#pragma once + +#include "VertexArray.h" + +namespace ICE { +class GPUMesh { + public: + explicit GPUMesh(const std::shared_ptr &vao) : m_vao(vao) {} + const std::shared_ptr getVertexArray() const { return m_vao; } + + private: + std::shared_ptr m_vao; +}; +} // namespace ICE diff --git a/ICE/Graphics/include/GPUTexture.h b/ICE/Graphics/include/GPUTexture.h new file mode 100644 index 00000000..b928e8c4 --- /dev/null +++ b/ICE/Graphics/include/GPUTexture.h @@ -0,0 +1,11 @@ +#pragma once + +namespace ICE { +class GPUTexture { + public: + virtual void bind(uint32_t slot) const = 0; + virtual int id() const = 0; + void* ptr() const { return reinterpret_cast(static_cast(id())); } + virtual ~GPUTexture() = default; +}; +} // namespace ICE diff --git a/ICE/Graphics/include/GraphicsFactory.h b/ICE/Graphics/include/GraphicsFactory.h index dac8290b..d21c36b8 100644 --- a/ICE/Graphics/include/GraphicsFactory.h +++ b/ICE/Graphics/include/GraphicsFactory.h @@ -9,6 +9,8 @@ #include "Framebuffer.h" #include "GraphicsAPI.h" #include "Shader.h" +#include "ShaderProgram.h" +#include "GPUTexture.h" #include "Texture.h" #include "VertexArray.h" @@ -29,14 +31,10 @@ class GraphicsFactory { virtual std::shared_ptr createUniformBuffer(size_t size, size_t binding) const = 0; - virtual std::shared_ptr createShader(const std::string& vertexFile, const std::string& fragmentFile) const = 0; + virtual std::shared_ptr createShader(const Shader& shader) const = 0; - virtual std::shared_ptr createShader(const std::string& vertexFile, const std::string& geometryFile, - const std::string& fragmentFile) const = 0; + virtual std::shared_ptr createTexture2D(const Texture2D &texture) const = 0; - virtual std::shared_ptr createTexture2D(const std::string& file) const = 0; - virtual std::shared_ptr createTexture2D(const void* data, size_t w, size_t h, TextureFormat fmt) const = 0; - - virtual std::shared_ptr createTextureCube(const std::string& file) const = 0; + virtual std::shared_ptr createTextureCube(const TextureCube& texture) const = 0; }; } // namespace ICE \ No newline at end of file diff --git a/ICE/Graphics/include/RenderCommand.h b/ICE/Graphics/include/RenderCommand.h index d3b32231..7ac4e48c 100644 --- a/ICE/Graphics/include/RenderCommand.h +++ b/ICE/Graphics/include/RenderCommand.h @@ -7,20 +7,20 @@ #include #include +#include "GPUMesh.h" #include "Material.h" -#include "Mesh.h" -#include "Shader.h" #include "Model.h" +#include "ShaderProgram.h" namespace ICE { struct RenderCommand { - std::shared_ptr mesh; + std::shared_ptr mesh; std::shared_ptr material; - std::shared_ptr shader; - std::unordered_map> textures; + std::shared_ptr shader; + std::unordered_map> textures; Eigen::Matrix4f model_matrix; - std::vector bones; + std::vector bones; bool faceCulling = true; bool depthTest = true; diff --git a/ICE/Graphics/include/Renderer.h b/ICE/Graphics/include/Renderer.h index 8e45f4e1..4102be3a 100644 --- a/ICE/Graphics/include/Renderer.h +++ b/ICE/Graphics/include/Renderer.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "Camera.h" #include "Context.h" @@ -43,18 +44,18 @@ struct alignas(16) CameraUBO { }; struct Skybox { - std::shared_ptr cube_mesh; - std::shared_ptr shader; - std::unordered_map> textures; + std::shared_ptr cube_mesh; + std::shared_ptr shader; + std::unordered_map> textures; }; struct Drawable { - std::shared_ptr mesh; + std::shared_ptr mesh; std::shared_ptr material; - std::shared_ptr shader; - std::unordered_map> textures; + std::shared_ptr shader; + std::unordered_map> textures; Eigen::Matrix4f model_matrix; - Model::Skeleton skeleton; + std::vector bone_matrices; }; struct Light { @@ -70,7 +71,7 @@ class Renderer { virtual void submitSkybox(const Skybox& e) = 0; virtual void submitDrawable(const Drawable& e) = 0; virtual void submitLight(const Light& e) = 0; - virtual void prepareFrame(Camera &camera) = 0; + virtual void prepareFrame(Camera& camera) = 0; virtual std::shared_ptr render() = 0; virtual void endFrame() = 0; virtual void resize(uint32_t width, uint32_t height) = 0; diff --git a/ICE/Graphics/include/Shader.h b/ICE/Graphics/include/ShaderProgram.h similarity index 67% rename from ICE/Graphics/include/Shader.h rename to ICE/Graphics/include/ShaderProgram.h index bc839067..5d2521fc 100644 --- a/ICE/Graphics/include/Shader.h +++ b/ICE/Graphics/include/ShaderProgram.h @@ -1,17 +1,10 @@ -// -// Created by Thomas Ibanez on 20.11.20. -// - -#ifndef ICE_SHADER_H -#define ICE_SHADER_H - -#include +#pragma once #include #include namespace ICE { -class Shader : public Asset { +class ShaderProgram { public: virtual void bind() const = 0; virtual void unbind() const = 0; @@ -25,11 +18,5 @@ class Shader : public Asset { virtual void loadFloat4(const std::string &name, Eigen::Vector4f vec) = 0; virtual void loadMat4(const std::string &name, Eigen::Matrix4f mat) = 0; - - std::string getTypeName() const override { return "Shader"; }; - - AssetType getType() const override { return AssetType::EShader; }; }; -} // namespace ICE - -#endif //ICE_SHADER_H +} // namespace ICE \ No newline at end of file diff --git a/ICE/Graphics/src/ForwardRenderer.cpp b/ICE/Graphics/src/ForwardRenderer.cpp index ffefbad7..03000e6c 100644 --- a/ICE/Graphics/src/ForwardRenderer.cpp +++ b/ICE/Graphics/src/ForwardRenderer.cpp @@ -75,7 +75,7 @@ void ForwardRenderer::prepareFrame(Camera& camera) { cmd.model_matrix = drawable.model_matrix; cmd.depthTest = true; cmd.faceCulling = true; - cmd.bones = drawable.skeleton.bones; + cmd.bones = drawable.bone_matrices; m_render_commands.push_back(cmd); } diff --git a/ICE/Graphics/src/GeometryPass.cpp b/ICE/Graphics/src/GeometryPass.cpp index 4c1472ee..8c4d14e5 100644 --- a/ICE/Graphics/src/GeometryPass.cpp +++ b/ICE/Graphics/src/GeometryPass.cpp @@ -10,9 +10,9 @@ void GeometryPass::execute() { m_framebuffer->bind(); m_api->setViewport(0, 0, m_framebuffer->getFormat().width, m_framebuffer->getFormat().height); m_api->clear(); - std::shared_ptr current_shader; + std::shared_ptr current_shader; std::shared_ptr current_material; - std::shared_ptr current_mesh; + std::shared_ptr current_mesh; for (const auto& command : *m_render_queue) { auto& shader = command.shader; @@ -27,14 +27,11 @@ void GeometryPass::execute() { current_shader = shader; } - if (mesh->usesBones()) { - for (const auto& [boneID, offsetMatrix] : mesh->getSkinningData().boneOffsetMatrices) { + if (!command.bones.empty()) { + for (int i = 0; i < command.bones.size(); i++) { Eigen::Matrix4f bone_transform = Eigen::Matrix4f::Identity(); - if (boneID < command.bones.size()) { - bone_transform = command.bones[boneID].finalTransformation; - } - current_shader->loadMat4("bonesOffsetMatrices[" + std::to_string(boneID) + "]", offsetMatrix); - current_shader->loadMat4("bonesTransformMatrices[" + std::to_string(boneID) + "]", bone_transform); + bone_transform = command.bones[i]; + current_shader->loadMat4("bonesTransformMatrices[" + std::to_string(i) + "]", bone_transform); } } diff --git a/ICE/Graphics/src/Mesh.cpp b/ICE/Graphics/src/Mesh.cpp index 44f689b2..57614160 100644 --- a/ICE/Graphics/src/Mesh.cpp +++ b/ICE/Graphics/src/Mesh.cpp @@ -30,14 +30,6 @@ const std::vector &Mesh::getIndices() const { return m_data.indices; } -const std::shared_ptr Mesh::getVertexArray() const { - return vertexArray; -} - -void Mesh::setVertexArray(const std::shared_ptr &vao) { - this->vertexArray = vao; -} - const AABB &Mesh::getBoundingBox() const { return boundingBox; } diff --git a/ICE/GraphicsAPI/CMakeLists.txt b/ICE/GraphicsAPI/CMakeLists.txt index 6ad92fb7..74fdf4fb 100644 --- a/ICE/GraphicsAPI/CMakeLists.txt +++ b/ICE/GraphicsAPI/CMakeLists.txt @@ -3,7 +3,6 @@ project(graphics_api) message(STATUS "Building ${PROJECT_NAME} module") -add_subdirectory(None) add_subdirectory(OpenGL) add_library(${PROJECT_NAME} INTERFACE) @@ -12,7 +11,6 @@ target_link_libraries(${PROJECT_NAME} INTERFACE graphics graphics_api_OpenGL - graphics_api_None ) target_include_directories(${PROJECT_NAME} INTERFACE diff --git a/ICE/GraphicsAPI/None/CMakeLists.txt b/ICE/GraphicsAPI/None/CMakeLists.txt deleted file mode 100644 index a8c3579f..00000000 --- a/ICE/GraphicsAPI/None/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -cmake_minimum_required(VERSION 3.19) -project(graphics_api_None) - -message(STATUS "Building ${PROJECT_NAME} module") - -add_library(${PROJECT_NAME} INTERFACE) - -#target_link_libraries(${PROJECT_NAME}) - -target_include_directories(${PROJECT_NAME} INTERFACE - $ - $) - -enable_testing() -#add_subdirectory(test) diff --git a/ICE/GraphicsAPI/None/NoneGraphics.h b/ICE/GraphicsAPI/None/NoneGraphics.h deleted file mode 100644 index 15b74f94..00000000 --- a/ICE/GraphicsAPI/None/NoneGraphics.h +++ /dev/null @@ -1,125 +0,0 @@ -// -// Created by Thomas Ibanez on 24.02.21. -// - -#ifndef ICE_NONEGRAPHICS_H -#define ICE_NONEGRAPHICS_H - -#include - -#include - -namespace ICE { - -class NoneVertexBuffer : public VertexBuffer { - public: - void bind() const override {} - void unbind() const override {} - void putData(const void *data, uint32_t size) override {} - uint32_t getSize() const override { return 0; } -}; - -class NoneIndexBuffer : public IndexBuffer { - public: - void bind() const override {} - void unbind() const override {} - uint32_t getSize() const override { return 0; } - void putData(const void *data, uint32_t size) override {} -}; - -class NoneUniformBuffer : public UniformBuffer { - public: - void bind() const override {} - void unbind() const override {} - uint32_t getSize() const override { return 0; } - void putData(const void *data, uint32_t size, uint32_t offset) override {} -}; - -class NoneContext : public Context { - public: - void swapBuffers() override {} - void wireframeMode() override {} - void fillMode() override {} - void initialize() override {} -}; - -class NoneFramebuffer : public Framebuffer { - public: - NoneFramebuffer() : Framebuffer({0,0,0}) {} - void bind() override {} - void unbind() override {} - void resize(int width, int height) override {} - int getTexture() override { return 0; } - void bindAttachment(int slot) const override{}; - Eigen::Vector4i readPixel(int x, int y) override { return Eigen::Vector4i(); } -}; - -class NoneRendererAPI : public RendererAPI { - public: - void initialize() const override {} - void setViewport(int x, int y, int width, int height) const override {} - void setClearColor(float r, float g, float b, float a) const override {} - void clear() const override {} - void renderVertexArray(const std::shared_ptr &va) const override {} - void flush() const override {} - void finish() const override {} - void bindDefaultFramebuffer() const override {} - void setDepthTest(bool enable) const override {} - void setDepthMask(bool enable) const override {} - void setBackfaceCulling(bool enable) const override {} - void checkAndLogErrors() const override {} -}; - -class NoneShader : public Shader { - public: - void bind() const override {} - void unbind() const override {} - void loadInt(const std::string &name, int v) override {} - void loadInts(const std::string &name, int *array, uint32_t size) override {} - void loadFloat(const std::string &name, float v) override {} - void loadFloat2(const std::string &name, Eigen::Vector2f vec) override {} - void loadFloat3(const std::string &name, Eigen::Vector3f vec) override {} - void loadFloat4(const std::string &name, Eigen::Vector4f vec) override {} - void loadMat4(const std::string &name, Eigen::Matrix4f mat) override {} - virtual AssetType getType() const override { return AssetType::EShader; } - virtual std::string getTypeName() const override { return "Shader"; } -}; - -class NoneTexture2D : public Texture2D { - public: - void bind(uint32_t slot) const override {} - TextureFormat getFormat() const override { return {}; } - uint32_t getWidth() const override { return 0; } - uint32_t getHeight() const override { return 0; } - TextureWrap getWrap() const override { return {}; } - void setData(void *data, uint32_t size) override {} - void *getTexture() const override { return nullptr; } - TextureType getTextureType() const override { return TextureType::Tex2D; } -}; - -class NoneTextureCube : public TextureCube { - public: - void bind(uint32_t slot) const override {} - TextureFormat getFormat() const override { return {}; } - uint32_t getWidth() const override { return 0; } - uint32_t getHeight() const override { return 0; } - TextureWrap getWrap() const override { return {}; } - void setData(void *data, uint32_t size) override {} - void *getTexture() const override { return nullptr; } - TextureType getTextureType() const override { return TextureType::CubeMap; } -}; - -class NoneVertexArray : public VertexArray { - public: - void bind() const override {} - void unbind() const override {} - void pushVertexBuffer(const std::shared_ptr &buffer, int size) override {} - void pushVertexBuffer(const std::shared_ptr &buffer, int position, int size) override {} - void setIndexBuffer(const std::shared_ptr &buffer) override {} - int getIndexCount() const override { return 0; } - uint32_t getID() const override { return 0; } - std::shared_ptr getIndexBuffer() const override { return nullptr; } -}; -} // namespace ICE - -#endif //ICE_NONEGRAPHICS_H diff --git a/ICE/GraphicsAPI/None/NoneGraphicsFactory.h b/ICE/GraphicsAPI/None/NoneGraphicsFactory.h deleted file mode 100644 index 5dd4eb69..00000000 --- a/ICE/GraphicsAPI/None/NoneGraphicsFactory.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include - -#include "Context.h" -#include "Framebuffer.h" -#include "GraphicsAPI.h" -#include "GraphicsFactory.h" -#include "NoneGraphics.h" -#include "Shader.h" -#include "Texture.h" -#include "VertexArray.h" - -namespace ICE { -class NoneGraphicsFactory : public GraphicsFactory { - public: - std::shared_ptr createContext(const std::shared_ptr& window) const override { return std::make_shared(); } - - std::shared_ptr createFramebuffer(const FrameBufferFormat& format) const override { return std::make_shared(); } - - std::shared_ptr createRendererAPI() const override { return std::make_shared(); } - - std::shared_ptr createVertexArray() const override { return std::make_shared(); } - - std::shared_ptr createVertexBuffer() const override { return std::make_shared(); } - - std::shared_ptr createIndexBuffer() const override { return std::make_shared(); } - - std::shared_ptr createUniformBuffer(size_t size, size_t binding) const override { return std::make_shared(); } - - std::shared_ptr createShader(const std::string& vertexFile, const std::string& fragmentFile) const override { - return createShader(vertexFile, "", fragmentFile); - } - - std::shared_ptr createShader(const std::string& vertexFile, const std::string& geometryFile, - const std::string& fragmentFile) const override { - return std::make_shared(); - } - - std::shared_ptr createTexture2D(const std::string& file) const override { return std::make_shared(); } - std::shared_ptr createTexture2D(const void* data, size_t w, size_t h, TextureFormat fmt) const override { - return std::make_shared(); - } - - std::shared_ptr createTextureCube(const std::string& file) const override { return std::make_shared(); } -}; -} // namespace ICE \ No newline at end of file diff --git a/ICE/GraphicsAPI/OpenGL/include/OpenGLFactory.h b/ICE/GraphicsAPI/OpenGL/include/OpenGLFactory.h index a23d74f8..f1d65194 100644 --- a/ICE/GraphicsAPI/OpenGL/include/OpenGLFactory.h +++ b/ICE/GraphicsAPI/OpenGL/include/OpenGLFactory.h @@ -38,20 +38,10 @@ class OpenGLFactory : public GraphicsFactory { std::shared_ptr createIndexBuffer() const override { return std::make_shared(); } - std::shared_ptr createShader(const std::string& vertex_src, const std::string& fragment_src) const override { - return createShader(vertex_src, "", fragment_src); - } - - std::shared_ptr createShader(const std::string& vertex_src, const std::string& geometry_src, - const std::string& fragment_src) const override { - return std::make_shared(vertex_src, geometry_src, fragment_src); - } + std::shared_ptr createShader(const Shader& shader) const override { return std::make_shared(shader); } - std::shared_ptr createTexture2D(const std::string& file) const override { return std::make_shared(file); } - std::shared_ptr createTexture2D(const void* data, size_t w, size_t h, TextureFormat fmt) const override { - return std::make_shared(data, w, h, fmt); - } + std::shared_ptr createTexture2D(const Texture2D& texture) const override { return std::make_shared(texture); } - std::shared_ptr createTextureCube(const std::string& file) const override { return std::make_shared(file); } + std::shared_ptr createTextureCube(const TextureCube& texture) const override { return std::make_shared(texture); } }; } // namespace ICE \ No newline at end of file diff --git a/ICE/GraphicsAPI/OpenGL/include/OpenGLShader.h b/ICE/GraphicsAPI/OpenGL/include/OpenGLShader.h index 476605d0..2b68236b 100644 --- a/ICE/GraphicsAPI/OpenGL/include/OpenGLShader.h +++ b/ICE/GraphicsAPI/OpenGL/include/OpenGLShader.h @@ -8,42 +8,44 @@ #include #include #include -#include +#include + #include +#include namespace ICE { - class OpenGLShader : public Shader { - public: - void bind() const override; - - void unbind() const override; +class OpenGLShader : public ShaderProgram { + public: + explicit OpenGLShader(const Shader &shader_asset); - void loadInt(const std::string &name, int v) override; + void bind() const override; - void loadInts(const std::string &name, int *array, uint32_t size) override; + void unbind() const override; - void loadFloat(const std::string &name, float v) override; + void loadInt(const std::string &name, int v) override; - void loadFloat2(const std::string &name, Eigen::Vector2f vec) override; + void loadInts(const std::string &name, int *array, uint32_t size) override; - void loadFloat3(const std::string &name, Eigen::Vector3f vec) override; + void loadFloat(const std::string &name, float v) override; - void loadFloat4(const std::string &name, Eigen::Vector4f vec) override; + void loadFloat2(const std::string &name, Eigen::Vector2f vec) override; - void loadMat4(const std::string &name, Eigen::Matrix4f mat) override; + void loadFloat3(const std::string &name, Eigen::Vector3f vec) override; - OpenGLShader(const std::string &vertexFile, const std::string &geoFile, const std::string &fragmentFile); + void loadFloat4(const std::string &name, Eigen::Vector4f vec) override; - OpenGLShader(const std::string &vertexFile, const std::string &fragmentFile); + void loadMat4(const std::string &name, Eigen::Matrix4f mat) override; - private: + private: + GLint getLocation(const std::string &name); - GLint getLocation(const std::string &name); + void compileAndAttachStage(ShaderStage stage, const std::string &source); - uint32_t programID; - std::unordered_map locations; - }; -} + constexpr GLenum stageToGLStage(ShaderStage stage); + uint32_t m_programID; + std::unordered_map m_locations; +}; +} // namespace ICE -#endif //ICE_OPENGLSHADER_H +#endif //ICE_OPENGLSHADER_H diff --git a/ICE/GraphicsAPI/OpenGL/include/OpenGLTexture.h b/ICE/GraphicsAPI/OpenGL/include/OpenGLTexture.h index a7063c71..ba3eb877 100644 --- a/ICE/GraphicsAPI/OpenGL/include/OpenGLTexture.h +++ b/ICE/GraphicsAPI/OpenGL/include/OpenGLTexture.h @@ -6,6 +6,7 @@ #define ICE_OPENGLTEXTURE_H #include +#include #include #include @@ -63,65 +64,26 @@ constexpr int textureFormatToChannels(TextureFormat format) { } } -class OpenGLTexture2D : public Texture2D { +class OpenGLTexture2D : public GPUTexture { public: - OpenGLTexture2D(const std::string &file); - OpenGLTexture2D(const void *data, size_t w, size_t h, TextureFormat fmt); + OpenGLTexture2D(const Texture2D &tex); void bind(uint32_t slot) const override; - - TextureFormat getFormat() const override; - - uint32_t getWidth() const override; - uint32_t getHeight() const override; - - TextureWrap getWrap() const override; - - void setData(void *data, uint32_t size) override; - - void *getTexture() const override; - - TextureType getTextureType() const override; + int id() const override; private: - void loadData(const void *data, size_t w, size_t h, TextureFormat fmt); - - std::string file; - uint32_t id; - uint32_t width, height; - TextureFormat format; - TextureWrap wrap; - GLenum storageFormat; - GLenum dataFormat; + uint32_t m_id; }; -class OpenGLTextureCube : public TextureCube { +class OpenGLTextureCube : public GPUTexture { public: - OpenGLTextureCube(const std::string &file); + OpenGLTextureCube(const TextureCube &tex); void bind(uint32_t slot) const override; - - TextureFormat getFormat() const override; - - uint32_t getWidth() const override; - uint32_t getHeight() const override; - - TextureWrap getWrap() const override; - - void setData(void *data, uint32_t size) override; - - void *getTexture() const override; - - TextureType getTextureType() const override; + int id() const override; private: - std::string file; - uint32_t id; - uint32_t width, height; - TextureFormat format; - TextureWrap wrap; - GLenum storageFormat; - GLenum dataFormat; + uint32_t m_id; }; } // namespace ICE diff --git a/ICE/GraphicsAPI/OpenGL/src/OpenGLShader.cpp b/ICE/GraphicsAPI/OpenGL/src/OpenGLShader.cpp index 6e81a594..a15e73b3 100644 --- a/ICE/GraphicsAPI/OpenGL/src/OpenGLShader.cpp +++ b/ICE/GraphicsAPI/OpenGL/src/OpenGLShader.cpp @@ -10,8 +10,31 @@ #include namespace ICE { + +OpenGLShader::OpenGLShader(const Shader &shader_asset) { + m_programID = glCreateProgram(); + Logger::Log(Logger::VERBOSE, "Graphics", "Compiling shader..."); + + for (const auto& [stage, source] : shader_asset.getSources()) { + compileAndAttachStage(stage, source.second); + } + + glLinkProgram(m_programID); + GLint linkStatus = 0; + glGetProgramiv(m_programID, GL_LINK_STATUS, &linkStatus); + if (linkStatus == GL_FALSE) { + Logger::Log(Logger::FATAL, "Graphics", "Error while linking shader"); + GLint maxLength = 0; + glGetProgramiv(m_programID, GL_INFO_LOG_LENGTH, &maxLength); + + std::vector errorLog(maxLength); + glGetProgramInfoLog(m_programID, maxLength, &maxLength, &errorLog[0]); + Logger::Log(Logger::FATAL, "Graphics", "Shader linking error: %s", errorLog.data()); + } +} + void OpenGLShader::bind() const { - glUseProgram(programID); + glUseProgram(m_programID); } void OpenGLShader::unbind() const { @@ -47,11 +70,11 @@ void OpenGLShader::loadMat4(const std::string &name, Eigen::Matrix4f mat) { } GLint OpenGLShader::getLocation(const std::string &name) { - if (this->locations.find(name) == this->locations.end()) { - GLint location = glGetUniformLocation(programID, name.c_str()); - locations[name] = static_cast(location); + if (!m_locations.contains(name)) { + GLint location = glGetUniformLocation(m_programID, name.c_str()); + m_locations[name] = static_cast(location); } - return locations[name]; + return m_locations[name]; } bool compileShader(GLenum type, const std::string &source, GLint *shader) { @@ -77,48 +100,31 @@ bool compileShader(GLenum type, const std::string &source, GLint *shader) { return compileStatus == GL_TRUE; } -//TODO: Another ctor for tesselation control and evaluation shaders -OpenGLShader::OpenGLShader(const std::string &vertex_src, const std::string &geo_src, const std::string &fragment_src) { - //TODO: Better tracing in case of errors, cleanup - this->programID = glCreateProgram(); - - GLint vertexShader; - Logger::Log(Logger::VERBOSE, "Graphics", "Compiling vertex shader..."); - if (!compileShader(GL_VERTEX_SHADER, vertex_src, &vertexShader)) { - Logger::Log(Logger::FATAL, "Graphics", "Error while compiling vertex shader"); +void OpenGLShader::compileAndAttachStage(ShaderStage stage, const std::string &source) { + GLint shader; + Logger::Log(Logger::VERBOSE, "Graphics", "\t + Compiling shader stage..."); + if (!compileShader(stageToGLStage(stage), source, &shader)) { + Logger::Log(Logger::FATAL, "Graphics", "Error while compiling shader stage"); } - glAttachShader(programID, vertexShader); + glAttachShader(m_programID, shader); +} - GLint fragmentShader; - Logger::Log(Logger::VERBOSE, "Graphics", "Compiling fragment shader..."); - if (!compileShader(GL_FRAGMENT_SHADER, fragment_src, &fragmentShader)) { - Logger::Log(Logger::FATAL, "Graphics", "Error while compiling fragment shader"); - } - glAttachShader(programID, fragmentShader); - - if (!geo_src.empty()) { - GLint geoShader; - Logger::Log(Logger::VERBOSE, "Graphics", "Compiling geometry shader..."); - if (!compileShader(GL_GEOMETRY_SHADER, geo_src, &geoShader)) { - Logger::Log(Logger::FATAL, "Graphics", "Error while compiling geometry shader"); - } - glAttachShader(programID, geoShader); - } - glLinkProgram(programID); - GLint linkStatus = 0; - glGetProgramiv(programID, GL_LINK_STATUS, &linkStatus); - if (linkStatus == GL_FALSE) { - Logger::Log(Logger::FATAL, "Graphics", "Error while linking shader"); - GLint maxLength = 0; - glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &maxLength); - - std::vector errorLog(maxLength); - glGetProgramInfoLog(programID, maxLength, &maxLength, &errorLog[0]); - Logger::Log(Logger::FATAL, "Graphics", "Shader linking error: %s", errorLog.data()); +constexpr GLenum OpenGLShader::stageToGLStage(ShaderStage stage) { + switch (stage) { + case ShaderStage::Vertex: + return GL_VERTEX_SHADER; + case ShaderStage::Fragment: + return GL_FRAGMENT_SHADER; + case ShaderStage::Geometry: + return GL_GEOMETRY_SHADER; + case ShaderStage::TessControl: + return GL_TESS_CONTROL_SHADER; + case ShaderStage::TessEval: + return GL_TESS_EVALUATION_SHADER; + case ShaderStage::Compute: + return GL_COMPUTE_SHADER; } } -OpenGLShader::OpenGLShader(const std::string &vertex_src, const std::string &fragment_src) : OpenGLShader(vertex_src, "", fragment_src) { -} } // namespace ICE \ No newline at end of file diff --git a/ICE/GraphicsAPI/OpenGL/src/OpenGLTexture2D.cpp b/ICE/GraphicsAPI/OpenGL/src/OpenGLTexture2D.cpp index cb5be8e4..bded6daa 100644 --- a/ICE/GraphicsAPI/OpenGL/src/OpenGLTexture2D.cpp +++ b/ICE/GraphicsAPI/OpenGL/src/OpenGLTexture2D.cpp @@ -9,68 +9,35 @@ namespace ICE { -OpenGLTexture2D::OpenGLTexture2D(const std::string &file) : file(file) { - int channels, w, h; - void *data = Texture::getDataFromFile(file, &w, &h, &channels); - loadData(data, w, h, channels == 4 ? TextureFormat::RGBA8 : TextureFormat::RGB8); - stbi_image_free(data); -} - -OpenGLTexture2D::OpenGLTexture2D(const void *data, size_t w, size_t h, TextureFormat fmt) { - loadData(data, w, h, fmt); -} - -void OpenGLTexture2D::loadData(const void *data, size_t w, size_t h, TextureFormat fmt) { - width = w; - height = h; +OpenGLTexture2D::OpenGLTexture2D(const Texture2D &tex) { + auto width = tex.getWidth(); + auto height = tex.getHeight(); - glGenTextures(1, &id); - glBindTexture(GL_TEXTURE_2D, id); + glGenTextures(1, &m_id); + glBindTexture(GL_TEXTURE_2D, m_id); - storageFormat = textureFormatToGLInternalFormat(fmt); - dataFormat = (textureFormatToChannels(fmt) == 4) ? GL_RGBA : (textureFormatToChannels(fmt) == 3) ? GL_RGB : GL_RED; + auto fmt = tex.getFormat(); + auto storageFormat = textureFormatToGLInternalFormat(fmt); + auto dataFormat = (textureFormatToChannels(fmt) == 4) ? GL_RGBA : (textureFormatToChannels(fmt) == 3) ? GL_RGB : GL_RED; glPixelStorei(GL_UNPACK_ALIGNMENT, textureFormatToAlignment(fmt)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - wrap = TextureWrap::Repeat; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + auto wrap = tex.getWrap(); + auto glWrap = (wrap == TextureWrap::Clamp) ? GL_CLAMP_TO_EDGE : (wrap == TextureWrap::Repeat) ? GL_REPEAT : GL_REPEAT; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrap); - glTexImage2D(GL_TEXTURE_2D, 0, storageFormat, width, height, 0, dataFormat, GL_UNSIGNED_BYTE, data); + glTexImage2D(GL_TEXTURE_2D, 0, storageFormat, width, height, 0, dataFormat, GL_UNSIGNED_BYTE, tex.data()); } -void OpenGLTexture2D::setData(void *data, uint32_t size) { - glTextureSubImage2D(id, 0, 0, 0, width, height, dataFormat, GL_UNSIGNED_BYTE, data); +int OpenGLTexture2D::id() const { + return m_id; } void OpenGLTexture2D::bind(uint32_t slot) const { glActiveTexture(GL_TEXTURE0 + slot); - glBindTexture(GL_TEXTURE_2D, id); -} - -TextureWrap OpenGLTexture2D::getWrap() const { - return wrap; -} - -TextureFormat OpenGLTexture2D::getFormat() const { - return format; -} - -uint32_t OpenGLTexture2D::getWidth() const { - return width; -} - -uint32_t OpenGLTexture2D::getHeight() const { - return height; -} - -void *OpenGLTexture2D::getTexture() const { - return static_cast(0) + id; -} - -TextureType OpenGLTexture2D::getTextureType() const { - return TextureType::Tex2D; + glBindTexture(GL_TEXTURE_2D, m_id); } } // namespace ICE \ No newline at end of file diff --git a/ICE/GraphicsAPI/OpenGL/src/OpenGLTextureCube.cpp b/ICE/GraphicsAPI/OpenGL/src/OpenGLTextureCube.cpp index b7ef4a13..ee0c6fa6 100644 --- a/ICE/GraphicsAPI/OpenGL/src/OpenGLTextureCube.cpp +++ b/ICE/GraphicsAPI/OpenGL/src/OpenGLTextureCube.cpp @@ -9,16 +9,13 @@ namespace ICE { -OpenGLTextureCube::OpenGLTextureCube(const std::string &file) { - int channels, w, h; - void *data = Texture::getDataFromFile(file, &w, &h, &channels, STBI_rgb); - width = w; - height = h; +OpenGLTextureCube::OpenGLTextureCube(const TextureCube &texture_asset) { + + glGenTextures(1, &m_id); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_id); - glGenTextures(1, &id); - glBindTexture(GL_TEXTURE_CUBE_MAP, id); - - auto faces = equirectangularToCubemap((uint8_t *) data, width, height); + auto width = texture_asset.getWidth(); + auto faces = equirectangularToCubemap((uint8_t *) texture_asset.data(), width, texture_asset.getHeight()); for (int i = 0; i < 6; i++) { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width / 4, width / 4, 0, GL_RGB, GL_UNSIGNED_BYTE, faces[i]); } @@ -29,39 +26,15 @@ OpenGLTextureCube::OpenGLTextureCube(const std::string &file) { glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - stbi_image_free(data); -} - -void OpenGLTextureCube::bind(uint32_t slot) const { - glActiveTexture(GL_TEXTURE0 + slot); - glBindTexture(GL_TEXTURE_CUBE_MAP, id); -} - -TextureFormat OpenGLTextureCube::getFormat() const { - return TextureFormat::RGB8; -} - -uint32_t OpenGLTextureCube::getWidth() const { - return width; -} - -uint32_t OpenGLTextureCube::getHeight() const { - return height; -} - -TextureWrap OpenGLTextureCube::getWrap() const { - return TextureWrap::Clamp; } -void OpenGLTextureCube::setData(void *data, uint32_t size) { - //TODO -} -void *OpenGLTextureCube::getTexture() const { - return static_cast(0) + id; +int OpenGLTextureCube::id() const { + return m_id; } -TextureType OpenGLTextureCube::getTextureType() const { - return TextureType::CubeMap; +void OpenGLTextureCube::bind(uint32_t slot) const { + glActiveTexture(GL_TEXTURE0 + slot); + glBindTexture(GL_TEXTURE_CUBE_MAP, m_id); } } // namespace ICE \ No newline at end of file diff --git a/ICE/IO/CMakeLists.txt b/ICE/IO/CMakeLists.txt index f6fdb6e9..aef7310b 100644 --- a/ICE/IO/CMakeLists.txt +++ b/ICE/IO/CMakeLists.txt @@ -13,6 +13,8 @@ target_sources(${PROJECT_NAME} PRIVATE src/ModelLoader.cpp src/ShaderLoader.cpp src/MaterialLoader.cpp + src/ShaderExporter.cpp + src/MeshLoader.cpp ) target_link_libraries(${PROJECT_NAME} @@ -22,6 +24,7 @@ target_link_libraries(${PROJECT_NAME} graphics_api assimp platform + nlohmann_json ) target_include_directories(${PROJECT_NAME} PUBLIC diff --git a/ICE/IO/include/IAssetLoader.h b/ICE/IO/include/IAssetLoader.h index d9de1ac9..94039996 100644 --- a/ICE/IO/include/IAssetLoader.h +++ b/ICE/IO/include/IAssetLoader.h @@ -13,11 +13,8 @@ namespace ICE { template class IAssetLoader { public: - IAssetLoader(const std::shared_ptr &factory) : graphics_factory(factory) {} + IAssetLoader() = default; virtual std::shared_ptr load(const std::vector &files) = 0; - - protected: - std::shared_ptr graphics_factory; }; } // namespace ICE diff --git a/ICE/IO/include/MaterialLoader.h b/ICE/IO/include/MaterialLoader.h index 5e7f8303..c5a895ad 100644 --- a/ICE/IO/include/MaterialLoader.h +++ b/ICE/IO/include/MaterialLoader.h @@ -11,7 +11,7 @@ namespace ICE { class MaterialLoader : public IAssetLoader { public: - MaterialLoader() : IAssetLoader(nullptr) {} + MaterialLoader() = default; std::shared_ptr load(const std::vector &files) override; }; } // namespace ICE diff --git a/ICE/IO/include/MeshLoader.h b/ICE/IO/include/MeshLoader.h new file mode 100644 index 00000000..aa2a1b03 --- /dev/null +++ b/ICE/IO/include/MeshLoader.h @@ -0,0 +1,25 @@ +// +// Created by Thomas Ibanez on 31.07.21. +// + +#pragma once + +#include +#include + +#include + +#include "Asset.h" +#include "IAssetLoader.h" +#include "Mesh.h" + +namespace ICE { +class AssetBank; + +class MeshLoader : public IAssetLoader { + public: + MeshLoader() {} + + std::shared_ptr load(const std::vector &file) override; +}; +} // namespace ICE diff --git a/ICE/IO/include/ModelLoader.h b/ICE/IO/include/ModelLoader.h index 0b92c85c..e36a7422 100644 --- a/ICE/IO/include/ModelLoader.h +++ b/ICE/IO/include/ModelLoader.h @@ -18,19 +18,16 @@ class AssetBank; class ModelLoader : public IAssetLoader { public: - ModelLoader(const std::shared_ptr &factory, AssetBank &bank) - : ref_bank(bank), - m_graphics_factory(factory), - IAssetLoader(factory) {} + ModelLoader(AssetBank &bank) : ref_bank(bank) {} std::shared_ptr load(const std::vector &file) override; int processNode(const aiNode *node, std::vector &nodes, Model::Skeleton &skeleton, std::unordered_set &used_names, const Eigen::Matrix4f &parent_transform); - std::shared_ptr extractMesh(const aiMesh *mesh, const std::string &model_name, const aiScene *scene, Model::Skeleton &skeleton); + AssetUID extractMesh(const aiMesh *mesh, const std::string &model_name, const aiScene *scene, Model::Skeleton &skeleton); AssetUID extractMaterial(const aiMaterial *material, const std::string &model_name, const aiScene *scene); AssetUID extractTexture(const aiMaterial *material, const std::string &tex_path, const aiScene *scene, aiTextureType type); - void extractBoneData(const aiMesh *mesh, const aiScene *scene, MeshData &data, SkinningData &skinning_data, Model::Skeleton &skeleton); + void extractBoneData(const aiMesh *mesh, const aiScene *scene, MeshData &data, Model::Skeleton &skeleton); std::unordered_map extractAnimations(const aiScene *scene, Model::Skeleton &skeleton); private: @@ -42,6 +39,5 @@ class ModelLoader : public IAssetLoader { constexpr TextureFormat getTextureFormat(aiTextureType type, int channels); AssetBank &ref_bank; - std::shared_ptr m_graphics_factory; }; } // namespace ICE diff --git a/ICE/IO/include/Project.h b/ICE/IO/include/Project.h index 37d70ead..2a4bbb90 100644 --- a/ICE/IO/include/Project.h +++ b/ICE/IO/include/Project.h @@ -15,8 +15,9 @@ error "Missing the header." #endif #include #include +#include #include -#include +#include #include #include @@ -43,6 +44,7 @@ class Project { std::shared_ptr getAssetBank(); void setAssetBank(const std::shared_ptr& assetBank); + std::shared_ptr getGPURegistry(); void addScene(const Scene& scene); void setCurrentScene(const std::shared_ptr& scene); @@ -70,7 +72,7 @@ class Project { std::string source = entry; sources.push_back(m_base_directory / source); } - assetBank->addAssetWithSpecificUID(asset_path, sources, uid); + m_asset_bank->addAssetWithSpecificUID(asset_path, sources, uid); } } @@ -82,17 +84,19 @@ class Project { fs::path m_base_directory; fs::path m_scenes_directory; + fs::path m_models_directory; fs::path m_meshes_directory; fs::path m_materials_directory; fs::path m_shaders_directory; fs::path m_textures_directory; fs::path m_cubemaps_directory; - std::string name; + std::string m_name; - std::vector> scenes; + std::vector> m_scenes; std::shared_ptr m_current_scene; - std::shared_ptr assetBank; + std::shared_ptr m_asset_bank; + std::shared_ptr m_gpu_registry; Eigen::Vector3f cameraPosition, cameraRotation; }; diff --git a/ICE/IO/include/ShaderExporter.h b/ICE/IO/include/ShaderExporter.h new file mode 100644 index 00000000..05fe1ecf --- /dev/null +++ b/ICE/IO/include/ShaderExporter.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include "AssetExporter.h" + +namespace ICE { +class ShaderExporter : public AssetExporter { + public: + void writeToJson(const std::filesystem::path &path, const Shader &object) override; + void writeToBin(const std::filesystem::path &path, const Shader &object) override; + + constexpr std::string stageToString(ShaderStage stage) { + switch (stage) { + case ShaderStage::Vertex: + return "vertex"; + case ShaderStage::Fragment: + return "fragment"; + case ShaderStage::Geometry: + return "geometry"; + case ShaderStage::TessControl: + return "tess_control"; + case ShaderStage::TessEval: + return "tess_eval"; + case ShaderStage::Compute: + return "compute"; + default: + return "unknown"; + } + } +}; +} // namespace ICE diff --git a/ICE/IO/include/ShaderLoader.h b/ICE/IO/include/ShaderLoader.h index 648f96e0..408552d1 100644 --- a/ICE/IO/include/ShaderLoader.h +++ b/ICE/IO/include/ShaderLoader.h @@ -13,8 +13,9 @@ namespace ICE { class ShaderLoader : public IAssetLoader { public: - ShaderLoader(const std::shared_ptr &factory) : IAssetLoader(factory) {} + ShaderLoader() = default; std::shared_ptr load(const std::vector &file) override; std::string readAndResolveIncludes(const std::filesystem::path &file); + constexpr ShaderStage stageFromString(const std::string &str); }; } // namespace ICE diff --git a/ICE/IO/include/TextureLoader.h b/ICE/IO/include/TextureLoader.h index 267b472d..7e868d0c 100644 --- a/ICE/IO/include/TextureLoader.h +++ b/ICE/IO/include/TextureLoader.h @@ -13,12 +13,12 @@ namespace ICE { class Texture2DLoader : public IAssetLoader { public: - Texture2DLoader(const std::shared_ptr &factory) : IAssetLoader(factory) {} + Texture2DLoader() = default; std::shared_ptr load(const std::vector &file) override; }; class TextureCubeLoader : public IAssetLoader { public: - TextureCubeLoader(const std::shared_ptr &factory) : IAssetLoader(factory) {} + TextureCubeLoader() = default; std::shared_ptr load(const std::vector &file) override; }; } // namespace ICE diff --git a/ICE/IO/src/EngineConfig.cpp b/ICE/IO/src/EngineConfig.cpp index 4317f2cb..960370d3 100644 --- a/ICE/IO/src/EngineConfig.cpp +++ b/ICE/IO/src/EngineConfig.cpp @@ -5,10 +5,10 @@ #include "EngineConfig.h" #include -#include #include #include +#include #include namespace ICE { diff --git a/ICE/IO/src/MaterialExporter.cpp b/ICE/IO/src/MaterialExporter.cpp index 884fd464..0e9a6674 100644 --- a/ICE/IO/src/MaterialExporter.cpp +++ b/ICE/IO/src/MaterialExporter.cpp @@ -1,62 +1,61 @@ #include "MaterialExporter.h" -#include #include -#include +#include #include +#include using json = nlohmann::json; namespace ICE { void MaterialExporter::writeToJson(const std::filesystem::path &path, const Material &material) { - std::ofstream outstream; - outstream.open(path); - json j; - j["shader_id"] = material.getShader(); + std::ofstream outstream; + outstream.open(path); + json j; + j["shader_id"] = material.getShader(); j["transparent"] = material.isTransparent(); - std::vector uniforms; - for(const auto &[name, value] : material.getAllUniforms()) { - json uniform; - uniform["name"] = name; - if (std::holds_alternative(value)) { - auto v = std::get(value); - uniform["type"] = "float"; - uniform["value"] = v; - } else if (std::holds_alternative(value)) { - auto v = std::get(value); - uniform["type"] = "int"; - uniform["value"] = v; - } else if (std::holds_alternative(value)) { - auto v = std::get(value); - uniform["type"] = "assetUID"; - uniform["value"] = v; - } else if (std::holds_alternative(value)) { - auto v = std::get(value); - uniform["type"] = "vec3"; - uniform["value"] = {v.x(), v.y(), v.z()}; - } else if (std::holds_alternative(value)) { - auto v = std::get(value); - uniform["type"] = "vec4"; - uniform["value"] = {v.x(), v.y(), v.z(), v.w()}; - } else if (std::holds_alternative(value)) { - auto v = std::get(value); - uniform["type"] = "mat4"; - uniform["value"] = std::vector(v.data(), v.data() + 16); - } else { - throw std::runtime_error("Uniform type not implemented"); - } - uniforms.push_back(std::move(uniform)); - } - - j["uniforms"] = uniforms; - outstream << j.dump(4); - outstream.close(); - + std::vector uniforms; + for (const auto &[name, value] : material.getAllUniforms()) { + json uniform; + uniform["name"] = name; + if (std::holds_alternative(value)) { + auto v = std::get(value); + uniform["type"] = "float"; + uniform["value"] = v; + } else if (std::holds_alternative(value)) { + auto v = std::get(value); + uniform["type"] = "int"; + uniform["value"] = v; + } else if (std::holds_alternative(value)) { + auto v = std::get(value); + uniform["type"] = "assetUID"; + uniform["value"] = v; + } else if (std::holds_alternative(value)) { + auto v = std::get(value); + uniform["type"] = "vec3"; + uniform["value"] = {v.x(), v.y(), v.z()}; + } else if (std::holds_alternative(value)) { + auto v = std::get(value); + uniform["type"] = "vec4"; + uniform["value"] = {v.x(), v.y(), v.z(), v.w()}; + } else if (std::holds_alternative(value)) { + auto v = std::get(value); + uniform["type"] = "mat4"; + uniform["value"] = std::vector(v.data(), v.data() + 16); + } else { + throw std::runtime_error("Uniform type not implemented"); + } + uniforms.push_back(std::move(uniform)); + } + + j["uniforms"] = uniforms; + outstream << j.dump(4); + outstream.close(); } -void MaterialExporter::writeToBin(const std::filesystem::path &path, const Material &object){ - throw std::runtime_error("Not implemented"); +void MaterialExporter::writeToBin(const std::filesystem::path &path, const Material &object) { + throw std::runtime_error("Not implemented"); } -} \ No newline at end of file +} // namespace ICE \ No newline at end of file diff --git a/ICE/IO/src/MaterialLoader.cpp b/ICE/IO/src/MaterialLoader.cpp index c1fde64a..fc73fd2f 100644 --- a/ICE/IO/src/MaterialLoader.cpp +++ b/ICE/IO/src/MaterialLoader.cpp @@ -5,7 +5,7 @@ #include "MaterialLoader.h" #include -#include +#include #include diff --git a/ICE/IO/src/MeshLoader.cpp b/ICE/IO/src/MeshLoader.cpp new file mode 100644 index 00000000..6f6b6a79 --- /dev/null +++ b/ICE/IO/src/MeshLoader.cpp @@ -0,0 +1,61 @@ +// +// Created by Thomas Ibanez on 31.07.21. +// + +#include "MeshLoader.h" + +#include +#include +#include +#include +#include + +#include + +namespace ICE { +std::shared_ptr MeshLoader::load(const std::vector &file) { + if (file.empty()) { + return nullptr; + } + + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(file[0].string(), + aiProcess_FlipUVs | aiProcess_ValidateDataStructure | aiProcess_SortByPType | aiProcess_GenSmoothNormals + | aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_PreTransformVertices); + + if (scene->mNumMeshes < 1) { + return nullptr; + } + MeshData data; + auto mesh = scene->mMeshes[0]; + for (int i = 0; i < mesh->mNumVertices; i++) { + auto v = mesh->mVertices[i]; + auto n = mesh->HasNormals() ? mesh->mNormals[i] : aiVector3D{0, 0, 0}; + auto t = mesh->HasTangentsAndBitangents() ? mesh->mTangents[i] : aiVector3D{0, 0, 0}; + auto b = mesh->HasTangentsAndBitangents() ? mesh->mBitangents[i] : aiVector3D{0, 0, 0}; + Eigen::Vector2f uv(0, 0); + if (mesh->mTextureCoords[0] != nullptr) { + auto uv_file = mesh->mTextureCoords[0][i]; + uv.x() = uv_file.x; + uv.y() = uv_file.y; + } + data.vertices.emplace_back(v.x, v.y, v.z); + data.normals.emplace_back(n.x, n.y, n.z); + data.uvCoords.push_back(uv); + data.tangents.emplace_back(t.x, t.y, t.z); + data.bitangents.emplace_back(b.x, b.y, b.z); + data.boneIDs.emplace_back(Eigen::Vector4i::Constant(-1)); + data.boneWeights.emplace_back(Eigen::Vector4f::Zero()); + } + for (int i = 0; i < mesh->mNumFaces; i++) { + auto f = mesh->mFaces[i]; + assert(f.mNumIndices == 3); + data.indices.emplace_back(f.mIndices[0], f.mIndices[1], f.mIndices[2]); + } + + auto mesh_ = std::make_shared(data); + mesh_->setSources(file); + return mesh_; +} + +} // namespace ICE diff --git a/ICE/IO/src/ModelLoader.cpp b/ICE/IO/src/ModelLoader.cpp index 5320c7f6..e825b34f 100644 --- a/ICE/IO/src/ModelLoader.cpp +++ b/ICE/IO/src/ModelLoader.cpp @@ -23,7 +23,7 @@ std::shared_ptr ModelLoader::load(const std::vector> meshes; + std::vector meshes; std::vector materials; std::vector nodes; Model::Skeleton skeleton; @@ -34,7 +34,6 @@ std::shared_ptr ModelLoader::load(const std::vectorsetSources(file); } std::unordered_set used_node_names; processNode(scene->mRootNode, nodes, skeleton, used_node_names, Eigen::Matrix4f::Identity()); @@ -72,7 +71,7 @@ int ModelLoader::processNode(const aiNode *ainode, std::vector &nod if (skeleton.boneMapping.contains(name)) { int boneID = skeleton.boneMapping.at(name); - skeleton.bones[boneID].finalTransformation = skeleton.globalInverseTransform * node.animatedTransform; + skeleton.bones[boneID].finalTransform = skeleton.globalInverseTransform * node.animatedTransform; } nodes.push_back(node); @@ -85,7 +84,7 @@ int ModelLoader::processNode(const aiNode *ainode, std::vector &nod return insert_pos; } -std::shared_ptr ModelLoader::extractMesh(const aiMesh *mesh, const std::string &model_name, const aiScene *scene, Model::Skeleton &skeleton) { +AssetUID ModelLoader::extractMesh(const aiMesh *mesh, const std::string &model_name, const aiScene *scene, Model::Skeleton &skeleton) { MeshData data; for (int i = 0; i < mesh->mNumVertices; i++) { @@ -113,47 +112,22 @@ std::shared_ptr ModelLoader::extractMesh(const aiMesh *mesh, const std::st data.indices.emplace_back(f.mIndices[0], f.mIndices[1], f.mIndices[2]); } - SkinningData skinning_data; if (mesh->HasBones()) { - extractBoneData(mesh, scene, data, skinning_data, skeleton); + extractBoneData(mesh, scene, data, skeleton); } auto mesh_ = std::make_shared(data); - if (skinning_data.boneOffsetMatrices.size() > 0) { - mesh_->setSkinningData(skinning_data); + AssetUID mesh_id = 0; + AssetPath mesh_path = AssetPath::WithTypePrefix(model_name + "/" + mesh->mName.C_Str()); + if (mesh_id = ref_bank.getUID(mesh_path); mesh_id != 0) { + ref_bank.removeAsset(mesh_path); + ref_bank.addAssetWithSpecificUID(mesh_path, mesh_, mesh_id); + } else { + ref_bank.addAsset(mesh_path, mesh_); + mesh_id = ref_bank.getUID(mesh_path); } - auto vertexArray = graphics_factory->createVertexArray(); - - auto vertexBuffer = graphics_factory->createVertexBuffer(); - auto normalsBuffer = graphics_factory->createVertexBuffer(); - auto uvBuffer = graphics_factory->createVertexBuffer(); - auto tangentBuffer = graphics_factory->createVertexBuffer(); - auto biTangentBuffer = graphics_factory->createVertexBuffer(); - auto boneIDBuffer = graphics_factory->createVertexBuffer(); - auto boneWeightBuffer = graphics_factory->createVertexBuffer(); - auto indexBuffer = graphics_factory->createIndexBuffer(); - - vertexBuffer->putData(BufferUtils::CreateFloatBuffer(data.vertices), 3 * data.vertices.size() * sizeof(float)); - normalsBuffer->putData(BufferUtils::CreateFloatBuffer(data.normals), 3 * data.normals.size() * sizeof(float)); - tangentBuffer->putData(BufferUtils::CreateFloatBuffer(data.tangents), 3 * data.tangents.size() * sizeof(float)); - biTangentBuffer->putData(BufferUtils::CreateFloatBuffer(data.bitangents), 3 * data.bitangents.size() * sizeof(float)); - boneIDBuffer->putData(BufferUtils::CreateIntBuffer(data.boneIDs), 4 * data.boneIDs.size() * sizeof(int)); - boneWeightBuffer->putData(BufferUtils::CreateFloatBuffer(data.boneWeights), 4 * data.boneWeights.size() * sizeof(float)); - uvBuffer->putData(BufferUtils::CreateFloatBuffer(data.uvCoords), 2 * data.uvCoords.size() * sizeof(float)); - indexBuffer->putData(BufferUtils::CreateIntBuffer(data.indices), 3 * data.indices.size() * sizeof(int)); - - vertexArray->pushVertexBuffer(vertexBuffer, 0, 3); - vertexArray->pushVertexBuffer(normalsBuffer, 1, 3); - vertexArray->pushVertexBuffer(uvBuffer, 2, 2); - vertexArray->pushVertexBuffer(tangentBuffer, 3, 3); - vertexArray->pushVertexBuffer(biTangentBuffer, 4, 3); - vertexArray->pushVertexBuffer(boneIDBuffer, 5, 4); - vertexArray->pushVertexBuffer(boneWeightBuffer, 6, 4); - vertexArray->setIndexBuffer(indexBuffer); - - mesh_->setVertexArray(vertexArray); - return mesh_; + return mesh_id; } AssetUID ModelLoader::extractMaterial(const aiMaterial *material, const std::string &model_name, const aiScene *scene) { @@ -241,7 +215,7 @@ AssetUID ModelLoader::extractTexture(const aiMaterial *material, const std::stri } else { data2 = data; } - auto texture_ice = m_graphics_factory->createTexture2D(data2, width, height, getTextureFormat(type, channels)); + auto texture_ice = std::make_shared(data2, width, height, getTextureFormat(type, channels)); if (tex_id = ref_bank.getUID(AssetPath::WithTypePrefix(tex_path)); tex_id != 0) { ref_bank.removeAsset(AssetPath::WithTypePrefix(tex_path)); ref_bank.addAssetWithSpecificUID(AssetPath::WithTypePrefix(tex_path), texture_ice, tex_id); @@ -257,7 +231,7 @@ AssetUID ModelLoader::extractTexture(const aiMaterial *material, const std::stri return tex_id; } -void ModelLoader::extractBoneData(const aiMesh *mesh, const aiScene *scene, MeshData &data, SkinningData &skinning_data, Model::Skeleton &skeleton) { +void ModelLoader::extractBoneData(const aiMesh *mesh, const aiScene *scene, MeshData &data, Model::Skeleton &skeleton) { for (unsigned int boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex) { std::string boneName = mesh->mBones[boneIndex]->mName.C_Str(); int boneID = -1; @@ -265,15 +239,14 @@ void ModelLoader::extractBoneData(const aiMesh *mesh, const aiScene *scene, Mesh if (!skeleton.boneMapping.contains(boneName)) { boneID = skeleton.boneMapping.size(); skeleton.boneMapping[boneName] = boneID; - Model::BoneInfo newBoneInfo = {.finalTransformation = Eigen::Matrix4f::Identity()}; + Model::BoneInfo newBoneInfo = {.finalTransform = Eigen::Matrix4f::Identity()}; skeleton.bones.push_back(newBoneInfo); + skeleton.inverseBindMatrices.push_back(aiMat4ToEigen(mesh->mBones[boneIndex]->mOffsetMatrix)); } else { //Bone Already Exists boneID = skeleton.boneMapping.at(boneName); } - skinning_data.boneOffsetMatrices.try_emplace(boneID, aiMat4ToEigen(mesh->mBones[boneIndex]->mOffsetMatrix)); - aiVertexWeight *weights = mesh->mBones[boneIndex]->mWeights; unsigned int numWeights = mesh->mBones[boneIndex]->mNumWeights; @@ -322,7 +295,7 @@ std::unordered_map ModelLoader::extractAnimations(const a.tracks[boneName] = std::move(track); } std::string anim_name = anim->mName.C_Str(); - + out.try_emplace(anim_name.substr(anim_name.find_first_of('|') + 1), std::move(a)); } return out; diff --git a/ICE/IO/src/Project.cpp b/ICE/IO/src/Project.cpp index dce19fe6..b4f18367 100644 --- a/ICE/IO/src/Project.cpp +++ b/ICE/IO/src/Project.cpp @@ -16,12 +16,14 @@ #include #include "MaterialExporter.h" +#include "ShaderExporter.h" namespace ICE { -Project::Project(const fs::path &base_directory, const std::string &name) - : m_base_directory(base_directory / name), - name(name), - assetBank(std::make_shared(std::make_shared())) { +Project::Project(const fs::path &base_directory, const std::string &m_name) + : m_base_directory(base_directory / m_name), + m_name(m_name), + m_asset_bank(std::make_shared()), + m_gpu_registry(std::make_shared(std::make_shared(), m_asset_bank)) { cameraPosition.setZero(); cameraRotation.setZero(); constexpr std::string_view assets_folder = "Assets"; @@ -29,7 +31,8 @@ Project::Project(const fs::path &base_directory, const std::string &name) m_shaders_directory = m_base_directory / assets_folder / "Shaders"; m_textures_directory = m_base_directory / assets_folder / "Textures"; m_cubemaps_directory = m_base_directory / assets_folder / "Cubemaps"; - m_meshes_directory = m_base_directory / assets_folder / "Models"; + m_models_directory = m_base_directory / assets_folder / "Models"; + m_meshes_directory = m_base_directory / assets_folder / "Meshes"; m_scenes_directory = m_base_directory / "Scenes"; } @@ -40,22 +43,22 @@ bool Project::CreateDirectories() { } catch (std::filesystem::filesystem_error &e) { Logger::Log(Logger::FATAL, "IO", "Could not copy default assets: %s", e.what()); } - assetBank->addAsset("solid", {m_shaders_directory / "skinning.vs", m_shaders_directory / "solid.fs"}); - assetBank->addAsset("phong", {m_shaders_directory / "skinning.vs", m_shaders_directory / "phong.fs"}); - assetBank->addAsset("normal", {m_shaders_directory / "skinning.vs", m_shaders_directory / "normal.fs"}); - assetBank->addAsset("pbr", {m_shaders_directory / "skinning.vs", m_shaders_directory / "pbr.fs"}); - assetBank->addAsset("lastpass", {m_shaders_directory / "lastpass.vs", m_shaders_directory / "lastpass.fs"}); - assetBank->addAsset("__ice__picking_shader", {m_shaders_directory / "skinning.vs", m_shaders_directory / "picking.fs"}); + m_asset_bank->addAsset("solid", {m_shaders_directory / "solid.shader.json"}); + m_asset_bank->addAsset("phong", {m_shaders_directory / "phong.shader.json"}); + m_asset_bank->addAsset("normal", {m_shaders_directory / "normal.shader.json"}); + m_asset_bank->addAsset("pbr", {m_shaders_directory / "pbr.shader.json"}); + m_asset_bank->addAsset("lastpass", {m_shaders_directory / "lastpass.shader.json"}); + m_asset_bank->addAsset("__ice__picking_shader", {m_shaders_directory / "picking.shader.json"}); - assetBank->addAsset("base_mat", {m_materials_directory / "base_mat.icm"}); + m_asset_bank->addAsset("base_mat", {m_materials_directory / "base_mat.material.json"}); - assetBank->addAsset("cube", {m_meshes_directory / "cube.obj"}); - assetBank->addAsset("sphere", {m_meshes_directory / "sphere.obj"}); + m_asset_bank->addAsset("cube", {m_meshes_directory / "cube.obj"}); + m_asset_bank->addAsset("sphere", {m_meshes_directory / "sphere.obj"}); - assetBank->addAsset("Editor/folder", {m_textures_directory / "Editor" / "folder.png"}); - assetBank->addAsset("Editor/shader", {m_textures_directory / "Editor" / "shader.png"}); + m_asset_bank->addAsset("Editor/folder", {m_textures_directory / "Editor" / "folder.png"}); + m_asset_bank->addAsset("Editor/shader", {m_textures_directory / "Editor" / "shader.png"}); - scenes.push_back(std::make_shared("MainScene")); + m_scenes.push_back(std::make_shared("MainScene")); setCurrentScene(getScenes()[0]); return true; } @@ -65,34 +68,40 @@ fs::path Project::getBaseDirectory() const { } std::string Project::getName() const { - return name; + return m_name; } void Project::writeToFile(const std::shared_ptr &editorCamera) { std::ofstream outstream; - outstream.open(m_base_directory / (name + ".ice")); + outstream.open(m_base_directory / (m_name + ".ice")); json j; j["camera_position"] = dumpVec3(editorCamera->getPosition()); j["camera_rotation"] = dumpVec3(editorCamera->getRotation()); std::vector vec; - for (const auto &s : scenes) { + for (const auto &s : m_scenes) { vec.push_back(s->getName()); } j["scenes"] = vec; vec.clear(); - for (const auto &[asset_id, mesh] : assetBank->getAll()) { + for (const auto &[asset_id, mesh] : m_asset_bank->getAll()) { vec.push_back(dumpAsset(asset_id, mesh)); } j["models"] = vec; vec.clear(); - for (const auto &[asset_id, material] : assetBank->getAll()) { - auto mtlName = assetBank->getName(asset_id).getName(); + for (const auto &[asset_id, mesh] : m_asset_bank->getAll()) { + vec.push_back(dumpAsset(asset_id, mesh)); + } + j["meshes"] = vec; + vec.clear(); - fs::path path = m_materials_directory.parent_path() / (assetBank->getName(asset_id).prefix() + mtlName + ".icm"); + for (const auto &[asset_id, material] : m_asset_bank->getAll()) { + auto mtlName = m_asset_bank->getName(asset_id).getName(); + + fs::path path = m_materials_directory.parent_path() / (m_asset_bank->getName(asset_id).prefix() + mtlName + ".material.json"); fs::create_directories(path.parent_path()); MaterialExporter().writeToJson(path, *material); @@ -103,19 +112,27 @@ void Project::writeToFile(const std::shared_ptr &editorCamera) { j["materials"] = vec; vec.clear(); - for (const auto &[asset_id, shader] : assetBank->getAll()) { + for (const auto &[asset_id, shader] : m_asset_bank->getAll()) { + auto mtlName = m_asset_bank->getName(asset_id).getName(); + + fs::path path = m_shaders_directory.parent_path() / (m_asset_bank->getName(asset_id).prefix() + mtlName + ".shader.json"); + fs::create_directories(path.parent_path()); + ShaderExporter().writeToJson(path, *shader); + + shader->setSources({path}); + vec.push_back(dumpAsset(asset_id, shader)); } j["shaders"] = vec; vec.clear(); - for (const auto &[asset_id, texture] : assetBank->getAll()) { + for (const auto &[asset_id, texture] : m_asset_bank->getAll()) { vec.push_back(dumpAsset(asset_id, texture)); } j["textures2D"] = vec; vec.clear(); - for (const auto &[asset_id, texture] : assetBank->getAll()) { + for (const auto &[asset_id, texture] : m_asset_bank->getAll()) { vec.push_back(dumpAsset(asset_id, texture)); } j["cubeMaps"] = vec; @@ -123,29 +140,30 @@ void Project::writeToFile(const std::shared_ptr &editorCamera) { outstream << j.dump(4); outstream.close(); - for (const auto &s : scenes) { + for (const auto &s : m_scenes) { outstream.open(m_scenes_directory / (s->getName() + ".ics")); j.clear(); - j["name"] = s->getName(); + j["m_name"] = s->getName(); json entities = json::array(); for (auto e : s->getRegistry()->getEntities()) { json entity; entity["id"] = e; - entity["name"] = s->getAlias(e); + entity["m_name"] = s->getAlias(e); entity["parent"] = s->getGraph()->getParentID(e); if (s->getRegistry()->entityHasComponent(e)) { RenderComponent rc = *s->getRegistry()->getComponent(e); json renderjson; - renderjson["model"] = rc.model; + renderjson["mesh"] = rc.mesh; + renderjson["material"] = rc.material; entity["renderComponent"] = renderjson; } if (s->getRegistry()->entityHasComponent(e)) { TransformComponent tc = *s->getRegistry()->getComponent(e); json transformjson; transformjson["position"] = dumpVec3(tc.getPosition()); - transformjson["rotation"] = dumpVec3(tc.getRotation()); + transformjson["rotation"] = dumpVec3(tc.getRotationEulerDeg()); transformjson["scale"] = dumpVec3(tc.getScale()); entity["transformComponent"] = transformjson; } @@ -165,7 +183,7 @@ void Project::writeToFile(const std::shared_ptr &editorCamera) { } json Project::dumpAsset(AssetUID uid, const std::shared_ptr &asset) { - auto asset_path = assetBank->getName(uid); + auto asset_path = m_asset_bank->getName(uid); json tmp; auto paths = asset->getSources(); std::vector sources(paths.size()); @@ -180,13 +198,14 @@ json Project::dumpAsset(AssetUID uid, const std::shared_ptr &asset) { } void Project::loadFromFile() { - std::ifstream infile = std::ifstream(m_base_directory / (name + ".ice")); + std::ifstream infile = std::ifstream(m_base_directory / (m_name + ".ice")); json j; infile >> j; infile.close(); std::vector sceneNames = j["scenes"]; - json meshes = j["models"]; + json models = j["models"]; + json meshes = j["meshes"]; json material = j["materials"]; json shader = j["shaders"]; json texture = j["textures2D"]; @@ -199,7 +218,8 @@ void Project::loadFromFile() { loadAssetsOfType(texture); loadAssetsOfType(cubeMap); loadAssetsOfType(material); - loadAssetsOfType(meshes); + loadAssetsOfType(meshes); + loadAssetsOfType(models); for (const auto &s : sceneNames) { infile = std::ifstream(m_scenes_directory / (s + ".ics")); @@ -207,12 +227,12 @@ void Project::loadFromFile() { infile >> scenejson; infile.close(); - Scene scene = Scene(scenejson["name"]); + Scene scene = Scene(scenejson["m_name"]); for (json jentity : scenejson["entities"]) { Entity e = jentity["id"]; Entity parent = jentity["parent"]; - std::string alias = jentity["name"]; + std::string alias = jentity["m_name"]; scene.addEntity(e, alias, 0); @@ -224,7 +244,7 @@ void Project::loadFromFile() { } if (!jentity["renderComponent"].is_null()) { json rj = jentity["renderComponent"]; - RenderComponent rc(rj["model"]); + RenderComponent rc(rj["mesh"], rj["material"]); scene.getRegistry()->addComponent(e, rc); } if (!jentity["lightComponent"].is_null()) { @@ -236,7 +256,7 @@ void Project::loadFromFile() { for (json jentity : scenejson["entities"]) { Entity e = jentity["id"]; Entity parent = jentity["parent"]; - scene.getGraph()->setParent(e, parent, true); + scene.getGraph()->setParent(e, parent); } addScene(scene); //TODO: it would be better to save the current scene index @@ -262,7 +282,7 @@ bool Project::renameAsset(const AssetPath &oldName, const AssetPath &newName) { if (newName.getName() == "" || newName.prefix() != oldName.prefix()) { return false; } - if (assetBank->renameAsset(oldName, newName)) { + if (m_asset_bank->renameAsset(oldName, newName)) { auto path = m_base_directory / "Assets"; for (const auto &file : getFilesInDir(path / oldName.prefix())) { if (file.substr(0, file.find_last_of(".")) == oldName.getName()) { @@ -288,23 +308,27 @@ std::vector Project::getFilesInDir(const fs::path &folder) { } std::vector> Project::getScenes() { - return scenes; + return m_scenes; } void Project::setScenes(const std::vector> &scenes) { - Project::scenes = scenes; + m_scenes = scenes; +} + +std::shared_ptr Project::getGPURegistry() { + return m_gpu_registry; } std::shared_ptr Project::getAssetBank() { - return assetBank; + return m_asset_bank; } -void Project::setAssetBank(const std::shared_ptr &assetBank) { - Project::assetBank = assetBank; +void Project::setAssetBank(const std::shared_ptr &asset_bank) { + m_asset_bank = asset_bank; } void Project::addScene(const Scene &scene) { - scenes.push_back(std::make_shared(scene)); + m_scenes.push_back(std::make_shared(scene)); } void Project::setCurrentScene(const std::shared_ptr &scene) { diff --git a/ICE/IO/src/ShaderExporter.cpp b/ICE/IO/src/ShaderExporter.cpp new file mode 100644 index 00000000..d6205cdc --- /dev/null +++ b/ICE/IO/src/ShaderExporter.cpp @@ -0,0 +1,28 @@ +#include "ShaderExporter.h" + +#include +#include +#include +#include + +using json = nlohmann::json; + +namespace ICE { + +void ShaderExporter::writeToJson(const std::filesystem::path &path, const Shader &shader) { + std::ofstream outstream; + outstream.open(path); + json j = json::array(); + for (const auto& [stage, source] : shader.getSources()) { + j.push_back({ + {"stage", stageToString(stage)}, + {"source", source.first}}); + } + outstream << j.dump(4); + outstream.close(); +} + +void ShaderExporter::writeToBin(const std::filesystem::path &path, const Shader &object) { + throw std::runtime_error("Not implemented"); +} +} // namespace ICE \ No newline at end of file diff --git a/ICE/IO/src/ShaderLoader.cpp b/ICE/IO/src/ShaderLoader.cpp index 8668c50d..c8f1ab36 100644 --- a/ICE/IO/src/ShaderLoader.cpp +++ b/ICE/IO/src/ShaderLoader.cpp @@ -8,27 +8,53 @@ #include #include +#include #include namespace ICE { std::shared_ptr ShaderLoader::load(const std::vector &files) { - if (files.size() < 2) { - throw ICEException("Shaders must have at least 2 files"); + if (files.empty()) { + throw ICEException("No files provided for shader"); } - std::shared_ptr shader; - if (files.size() == 2) { - shader = graphics_factory->createShader(readAndResolveIncludes(files[0]), readAndResolveIncludes(files[1])); - } else if (files.size() == 3) { - shader = graphics_factory->createShader(readAndResolveIncludes(files[0]), readAndResolveIncludes(files[1]), readAndResolveIncludes(files[2])); - } else { - throw ICEException("Too many files for shader"); + nlohmann::json json; + std::ifstream infile = std::ifstream(files[0]); + infile >> json; + infile.close(); + + ShaderSource shader_sources; + for (const auto &stage_source : json) { + auto stage = stageFromString(stage_source["stage"]); + auto file = stage_source["source"].get(); + auto file_path = (files[0].parent_path() / file).string(); + auto source_code = readAndResolveIncludes(file_path); + shader_sources[stage] = {file, source_code}; } + auto shader = std::make_shared(shader_sources); + shader->setSources(files); return shader; } +constexpr ShaderStage ShaderLoader::stageFromString(const std::string &str) { + if (str == "vertex") { + return ShaderStage::Vertex; + } else if (str == "fragment") { + return ShaderStage::Fragment; + } else if (str == "geometry") { + return ShaderStage::Geometry; + } else if (str == "tess_control") { + return ShaderStage::TessControl; + } else if (str == "tess_eval") { + return ShaderStage::TessEval; + } else if (str == "compute") { + return ShaderStage::Compute; + } else { + throw ICEException("Unknown shader stage: " + str); + } +} + std::string ShaderLoader::readAndResolveIncludes(const std::filesystem::path &file_path) { std::ifstream file(file_path); if (!file.is_open()) { diff --git a/ICE/IO/src/TextureLoader.cpp b/ICE/IO/src/TextureLoader.cpp index c8296322..e24a0b76 100644 --- a/ICE/IO/src/TextureLoader.cpp +++ b/ICE/IO/src/TextureLoader.cpp @@ -13,14 +13,14 @@ std::shared_ptr Texture2DLoader::load(const std::vectorcreateTexture2D(file[0].string()); + auto texture = std::make_shared(file[0].string()); texture->setSources(file); return texture; } std::shared_ptr TextureCubeLoader::load(const std::vector &file) { Logger::Log(Logger::VERBOSE, "IO", "Loading cubemap..."); - auto texture = graphics_factory->createTextureCube(file[0].string()); + auto texture = std::make_shared(file[0].string()); texture->setSources(file); return texture; } diff --git a/ICE/IO/test/ModelLoaderTest.cpp b/ICE/IO/test/ModelLoaderTest.cpp index 6316aa42..34df65b1 100644 --- a/ICE/IO/test/ModelLoaderTest.cpp +++ b/ICE/IO/test/ModelLoaderTest.cpp @@ -1,7 +1,6 @@ #define STB_IMAGE_IMPLEMENTATION #include -#include #include #include "ModelLoader.h" @@ -9,9 +8,8 @@ using namespace ICE; TEST(ModelLoaderTest, LoadFromObj) { - auto gr_f = std::make_shared(); - AssetBank bank(gr_f); - auto mesh = ModelLoader(gr_f, bank).load({"cube.obj"}); + AssetBank bank; + auto mesh = ModelLoader(bank).load({"cube.obj"}); EXPECT_EQ(mesh->getMeshes().at(0)->getVertices().size(), 36); EXPECT_EQ(mesh->getMeshes().at(0)->getIndices().size(), 12); } \ No newline at end of file diff --git a/ICE/Math/src/AABB.cpp b/ICE/Math/src/AABB.cpp index c2c93f3e..03547ed2 100644 --- a/ICE/Math/src/AABB.cpp +++ b/ICE/Math/src/AABB.cpp @@ -9,7 +9,7 @@ namespace ICE { AABB::AABB(const Eigen::Vector3f &min, const Eigen::Vector3f &max) : min(min), max(max) { } AABB::AABB(const std::vector &points) : AABB(points[0], points[0]) { - for (auto v : points) { + for (const auto &v : points) { min = min.cwiseMin(v); max = max.cwiseMax(v); } diff --git a/ICE/Scene/include/Scene.h b/ICE/Scene/include/Scene.h index d1a0d3ac..ef2b6735 100644 --- a/ICE/Scene/include/Scene.h +++ b/ICE/Scene/include/Scene.h @@ -28,6 +28,8 @@ class Scene { std::shared_ptr getRegistry() const; Entity createEntity(); + Entity spawnTree(AssetUID model_id, const std::shared_ptr& bank); + void addEntity(Entity e, const std::string& alias, Entity parent); void removeEntity(Entity e); bool hasEntity(Entity e); diff --git a/ICE/Scene/include/SceneGraph.h b/ICE/Scene/include/SceneGraph.h index a4a1bc51..a51c44df 100644 --- a/ICE/Scene/include/SceneGraph.h +++ b/ICE/Scene/include/SceneGraph.h @@ -1,8 +1,10 @@ #pragma once - #include +#include #include +#include +#include namespace ICE { @@ -11,80 +13,92 @@ class SceneGraph { struct SceneNode { Entity entity{0}; std::vector> children{}; + + // Use weak_ptr to avoid cyclic references (Parent owns Child, Child observes Parent) + std::weak_ptr parent; }; SceneGraph() : root(std::make_shared()) { idToNode.try_emplace(0, root); } void addEntity(Entity e) { - auto sn = createSceneNode(e); + // Prevent adding duplicate entities + if (idToNode.find(e) != idToNode.end()) + return; + + auto sn = std::make_shared(); + sn->entity = e; + sn->parent = root; // Default parent is root + root->children.push_back(sn); - idToNode.insert({e, sn}); + idToNode[e] = sn; } void removeEntity(Entity e) { + if (e == 0 || idToNode.find(e) == idToNode.end()) + return; + auto sn = idToNode[e]; - auto parent = findParent(e, root); - auto it = std::find(parent->children.begin(), parent->children.end(), idToNode[e]); - parent->children.erase(it); - for (size_t i = 0; i < sn->children.size(); i++) { - parent->children.push_back(sn->children[i]); + auto parentPtr = sn->parent.lock(); + + if (parentPtr) { + // Remove 'sn' from its parent's list + auto& siblings = parentPtr->children; + siblings.erase(std::remove(siblings.begin(), siblings.end(), sn), siblings.end()); + + // Orphan handling: Reparent children to their grandparent + for (auto& child : sn->children) { + child->parent = parentPtr; // Update child's parent pointer + parentPtr->children.push_back(child); + } } - sn->children.clear(); + idToNode.erase(e); } - void setParent(Entity e, Entity newParent, bool recurse) { - auto parent = findParent(e, root); + void setParent(Entity e, Entity newParentID) { + if (idToNode.find(e) == idToNode.end() || idToNode.find(newParentID) == idToNode.end()) + return; + if (e == newParentID) + return; // Can't parent to self + auto sn = idToNode[e]; - auto newparent_node = idToNode[newParent]; - auto it = std::find(parent->children.begin(), parent->children.end(), sn); - parent->children.erase(it); - newparent_node->children.push_back(sn); - if (!recurse) { - for (size_t i = 0; i < sn->children.size(); i++) { - parent->children.push_back(sn->children[i]); - } + auto newParent = idToNode[newParentID]; + auto oldParent = sn->parent.lock(); + + if (oldParent) { + auto& siblings = oldParent->children; + siblings.erase(std::remove(siblings.begin(), siblings.end(), sn), siblings.end()); } + + sn->parent = newParent; + newParent->children.push_back(sn); } Entity getParentID(Entity e) { - auto it = std::find(root->children.begin(), root->children.end(), idToNode[e]); - if (it != root->children.end()) { - return root->entity; - } - for (size_t i = 0; i < root->children.size(); i++) { - auto subtreeSearch = findParent(e, root->children[i]); - if (subtreeSearch != nullptr) { - return subtreeSearch->entity; - } + if (idToNode.find(e) == idToNode.end()) + return 0; + + auto parentPtr = idToNode[e]->parent.lock(); + if (parentPtr) { + return parentPtr->entity; } return 0; } - std::shared_ptr root; - - private: - std::shared_ptr findParent(Entity e, const std::shared_ptr &root) { - auto it = std::find(root->children.begin(), root->children.end(), idToNode[e]); - if (it != root->children.end()) { - return root; - } - for (size_t i = 0; i < root->children.size(); i++) { - auto subtreeSearch = findParent(e, root->children[i]); - if (subtreeSearch != nullptr) { - return subtreeSearch; + const std::vector getChildren(Entity e) { + std::vector childrenIDs; + if (idToNode.find(e) != idToNode.end()) { + for (auto& child : idToNode[e]->children) { + childrenIDs.push_back(child->entity); } } - return nullptr; + return childrenIDs; } - std::shared_ptr createSceneNode(Entity e) { - auto sn = std::make_shared(); - sn->entity = e; - return sn; - } + std::shared_ptr getRoot() const { return root; } - std::unordered_map m_entity_names; + private: + std::shared_ptr root; std::unordered_map> idToNode; }; } // namespace ICE \ No newline at end of file diff --git a/ICE/Scene/src/Scene.cpp b/ICE/Scene/src/Scene.cpp index 7e8c5d3f..eac053b2 100644 --- a/ICE/Scene/src/Scene.cpp +++ b/ICE/Scene/src/Scene.cpp @@ -45,9 +45,55 @@ Entity Scene::createEntity() { return e; } +Entity Scene::spawnTree(AssetUID model_id, const std::shared_ptr &bank) { + auto model = bank->getAsset(model_id); + auto nodes = model->getNodes(); + auto meshes = model->getMeshes(); + auto materialIDs = model->getMaterialsIDs(); + + std::function spawnNode = [&](int nodeIndex, Entity parent, Entity skeleton) -> Entity { + auto &node = nodes[nodeIndex]; + + Entity nodeEntity = createEntity(); + if (skeleton == -1) { + skeleton = nodeEntity; + } + setAlias(nodeEntity, node.name); + m_graph->setParent(nodeEntity, parent); + registry->addComponent(nodeEntity, TransformComponent(node.localTransform)); + + for (int meshIdx : node.meshIndices) { + Entity meshEntity = createEntity(); + setAlias(meshEntity, node.name + "_mesh_" + std::to_string(meshIdx)); + + m_graph->setParent(meshEntity, nodeEntity); + registry->addComponent(meshEntity, TransformComponent(Eigen::Matrix4f::Identity().eval())); + registry->addComponent(meshEntity, SkinningComponent{.skeleton_entity = skeleton}); + registry->addComponent(meshEntity, RenderComponent(meshes[meshIdx], materialIDs[meshIdx])); + } + + for (int childIndex : node.children) { + spawnNode(childIndex, nodeEntity, skeleton); + } + + return nodeEntity; + }; + + auto root = spawnNode(0, 0, -1); + + if (model->getSkeleton().bones.size() > 0) { + registry->addComponent(root, + SkeletonPoseComponent{.skeletonModel = model_id, + .final_bone_matrices = std::vector( + model->getSkeleton().bones.size(), Eigen::Matrix4f::Identity())}); + } + + return root; +} + void Scene::addEntity(Entity e, const std::string &alias, Entity parent) { m_graph->addEntity(e); - m_graph->setParent(e, parent, false); + m_graph->setParent(e, parent); registry->addEntity(e); aliases.try_emplace(e, alias); } diff --git a/ICE/Storage/CMakeLists.txt b/ICE/Storage/CMakeLists.txt index 8788d22d..46fb5335 100644 --- a/ICE/Storage/CMakeLists.txt +++ b/ICE/Storage/CMakeLists.txt @@ -9,7 +9,9 @@ target_sources(${PROJECT_NAME} PRIVATE src/Filesystem.cpp ) -#target_link_libraries(${PROJECT_NAME}) +target_link_libraries(${PROJECT_NAME} PUBLIC + nlohmann_json +) target_include_directories(${PROJECT_NAME} PUBLIC $ diff --git a/ICE/Storage/include/JsonParser.h b/ICE/Storage/include/JsonParser.h index 459112ec..ce57a361 100644 --- a/ICE/Storage/include/JsonParser.h +++ b/ICE/Storage/include/JsonParser.h @@ -7,7 +7,7 @@ #include -#include +#include using json = nlohmann::json; namespace ICE { diff --git a/ICE/System/CMakeLists.txt b/ICE/System/CMakeLists.txt index fe990d96..635a5a86 100644 --- a/ICE/System/CMakeLists.txt +++ b/ICE/System/CMakeLists.txt @@ -7,7 +7,9 @@ add_library(${PROJECT_NAME} STATIC) target_sources(${PROJECT_NAME} PRIVATE src/RenderSystem.cpp - src/AnimationSystem.cpp) + src/AnimationSystem.cpp + src/SceneGraphSystem.cpp +) target_link_libraries(${PROJECT_NAME} PUBLIC diff --git a/ICE/System/include/AnimationSystem.h b/ICE/System/include/AnimationSystem.h index ecd7d381..9a02bfec 100644 --- a/ICE/System/include/AnimationSystem.h +++ b/ICE/System/include/AnimationSystem.h @@ -15,7 +15,7 @@ class AnimationSystem : public System { std::vector getSignatures(const ComponentManager& comp_manager) const override { Signature signature; signature.set(comp_manager.getComponentType()); - signature.set(comp_manager.getComponentType()); + signature.set(comp_manager.getComponentType()); return {signature}; } @@ -30,7 +30,7 @@ class AnimationSystem : public System { return keys.size() - 1; } - void updateSkeleton(const std::shared_ptr& model, double time, const Animation& anim); + void updateSkeleton(const std::shared_ptr& model, double time, SkeletonPoseComponent* pose, const Animation& anim); Eigen::Matrix4f interpolatePosition(double timeInTicks, const BoneAnimation& track); @@ -38,8 +38,8 @@ class AnimationSystem : public System { Eigen::Matrix4f interpolateRotation(double time, const BoneAnimation& track); - void applyTransforms(Model::Node* node, const Eigen::Matrix4f& parentTransform, Model::Skeleton& skeleton, double time, const Animation& anim, - std::vector& allModelNodes); + void applyTransforms(const Model::Node* node, const Eigen::Matrix4f& parentTransform, const Model::Skeleton& skeleton, double time, + SkeletonPoseComponent* pose, const Animation& anim, const std::vector& allModelNodes); std::shared_ptr m_registry; std::shared_ptr m_asset_bank; diff --git a/ICE/System/include/Registry.h b/ICE/System/include/Registry.h index 45e28287..4d923d7e 100644 --- a/ICE/System/include/Registry.h +++ b/ICE/System/include/Registry.h @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -28,6 +30,8 @@ class Registry { componentManager.registerComponent(); componentManager.registerComponent(); componentManager.registerComponent(); + componentManager.registerComponent(); + componentManager.registerComponent(); } ~Registry() = default; diff --git a/ICE/System/include/RenderSystem.h b/ICE/System/include/RenderSystem.h index de8301e8..4bdcf4a4 100644 --- a/ICE/System/include/RenderSystem.h +++ b/ICE/System/include/RenderSystem.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace ICE { class Scene; @@ -19,7 +20,7 @@ class Registry; class RenderSystem : public System { public: RenderSystem(const std::shared_ptr &api, const std::shared_ptr &factory, const std::shared_ptr ®, - const std::shared_ptr &bank); + const std::shared_ptr &bank); void onEntityAdded(Entity e) override; void onEntityRemoved(Entity e) override; @@ -59,7 +60,7 @@ class RenderSystem : public System { std::shared_ptr m_api; std::shared_ptr m_factory; std::shared_ptr m_registry; - std::shared_ptr m_asset_bank; + std::shared_ptr m_asset_bank; std::shared_ptr m_quad_vao; }; diff --git a/ICE/System/include/SceneGraphSystem.h b/ICE/System/include/SceneGraphSystem.h new file mode 100644 index 00000000..7ea85425 --- /dev/null +++ b/ICE/System/include/SceneGraphSystem.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include "System.h" + +namespace ICE { + +class SceneGraphSystem : public System { + public: + SceneGraphSystem(const std::shared_ptr &scene); + + void onEntityAdded(Entity e) override; + void onEntityRemoved(Entity e) override; + void update(double delta) override; + + std::vector getSignatures(const ComponentManager &comp_manager) const override { + Signature signature0; + signature0.set(comp_manager.getComponentType()); + return {signature0}; + } + + private: + std::shared_ptr m_scene; +}; +} // namespace ICE diff --git a/ICE/System/src/AnimationSystem.cpp b/ICE/System/src/AnimationSystem.cpp index bb435d0c..248abf3a 100644 --- a/ICE/System/src/AnimationSystem.cpp +++ b/ICE/System/src/AnimationSystem.cpp @@ -9,13 +9,13 @@ AnimationSystem::AnimationSystem(const std::shared_ptr& reg, const std void AnimationSystem::update(double dt) { for (auto e : entities) { auto anim = m_registry->getComponent(e); - auto rc = m_registry->getComponent(e); + auto pose = m_registry->getComponent(e); if (!anim->playing) continue; anim->currentTime += dt * anim->speed; - auto model = m_asset_bank->getAsset(rc->model); + auto model = m_asset_bank->getAsset(pose->skeletonModel); auto animation = model->getAnimations().at(anim->currentAnimation); if (anim->currentTime > animation.duration) { @@ -26,17 +26,17 @@ void AnimationSystem::update(double dt) { anim->playing = false; } } - updateSkeleton(model, anim->currentTime, animation); + updateSkeleton(model, anim->currentTime, pose, animation); } } -void AnimationSystem::updateSkeleton(const std::shared_ptr& model, double time, const Animation& anim) { +void AnimationSystem::updateSkeleton(const std::shared_ptr& model, double time, SkeletonPoseComponent* pose, const Animation& anim) { auto& all_nodes = model->getNodes(); - applyTransforms(&all_nodes[0], Eigen::Matrix4f::Identity(), model->getSkeleton(), time, anim, all_nodes); + applyTransforms(&all_nodes[0], Eigen::Matrix4f::Identity(), model->getSkeleton(), time, pose, anim, all_nodes); } -void AnimationSystem::applyTransforms(Model::Node* node, const Eigen::Matrix4f& parentTransform, Model::Skeleton& skeleton, double time, - const Animation& anim, std::vector& allModelNodes) { +void AnimationSystem::applyTransforms(const Model::Node* node, const Eigen::Matrix4f& parentTransform, const Model::Skeleton& skeleton, double time, + SkeletonPoseComponent* pose, const Animation& anim, const std::vector& allModelNodes) { Eigen::Matrix4f nodeLocalTransform = node->localTransform; std::string nodeName = node->name; Eigen::Matrix4f globalTransform; @@ -51,15 +51,15 @@ void AnimationSystem::applyTransforms(Model::Node* node, const Eigen::Matrix4f& } globalTransform = parentTransform * nodeLocalTransform; - node->animatedTransform = globalTransform; + //node->animatedTransform = globalTransform; if (skeleton.boneMapping.contains(nodeName)) { int boneID = skeleton.boneMapping.at(nodeName); - skeleton.bones[boneID].finalTransformation = skeleton.globalInverseTransform * globalTransform; + pose->final_bone_matrices[boneID] = skeleton.globalInverseTransform * globalTransform * skeleton.inverseBindMatrices[boneID]; } for (int childIndex : node->children) { - applyTransforms(&allModelNodes[childIndex], globalTransform, skeleton, time, anim, allModelNodes); + applyTransforms(&allModelNodes[childIndex], globalTransform, skeleton, time, pose, anim, allModelNodes); } } diff --git a/ICE/System/src/RenderSystem.cpp b/ICE/System/src/RenderSystem.cpp index 825d0cf9..ef780b7d 100644 --- a/ICE/System/src/RenderSystem.cpp +++ b/ICE/System/src/RenderSystem.cpp @@ -9,7 +9,7 @@ namespace ICE { RenderSystem::RenderSystem(const std::shared_ptr &api, const std::shared_ptr &factory, - const std::shared_ptr ®, const std::shared_ptr &bank) + const std::shared_ptr ®, const std::shared_ptr &bank) : m_api(api), m_factory(factory), m_registry(reg), @@ -32,10 +32,10 @@ void RenderSystem::update(double delta) { auto proj_mat = m_camera->getProjection(); if (m_skybox != NO_ASSET_ID) { - auto shader = m_asset_bank->getAsset("__ice_skybox_shader"); + auto shader = m_asset_bank->getShader(AssetPath::WithTypePrefix("__ice_skybox_shader")); auto skybox = m_registry->getComponent(m_skybox); - auto mesh = m_asset_bank->getAsset("cube")->getMeshes().at(0); - auto tex = m_asset_bank->getAsset(skybox->texture); + auto mesh = m_asset_bank->getMesh(AssetPath::WithTypePrefix("cube")); + auto tex = m_asset_bank->getCubemap(skybox->texture); m_renderer->submitSkybox(Skybox{ .cube_mesh = mesh, .shader = shader, @@ -47,19 +47,45 @@ void RenderSystem::update(double delta) { for (const auto &e : m_render_queue) { auto rc = m_registry->getComponent(e); auto tc = m_registry->getComponent(e); - auto model = m_asset_bank->getAsset(rc->model); - if (!model) + auto mesh = m_asset_bank->getMesh(rc->mesh); + auto material = m_asset_bank->getMaterial(rc->material); + auto shader = m_asset_bank->getShader(material->getShader()); + if (!mesh || !material || !shader) continue; - auto aabb = model->getBoundingBox(); - Eigen::Vector3f min = (tc->getModelMatrix() * Eigen::Vector4f(aabb.getMin().x(), aabb.getMin().y(), aabb.getMin().z(), 1.0)).head<3>(); - Eigen::Vector3f max = (tc->getModelMatrix() * Eigen::Vector4f(aabb.getMax().x(), aabb.getMax().y(), aabb.getMax().z(), 1.0)).head<3>(); + auto model_mat = tc->getWorldMatrix(); + + auto aabb = m_asset_bank->getMeshAABB(rc->mesh); + Eigen::Vector3f min = (model_mat * Eigen::Vector4f(aabb.getMin().x(), aabb.getMin().y(), aabb.getMin().z(), 1.0)).head<3>(); + Eigen::Vector3f max = (model_mat * Eigen::Vector4f(aabb.getMax().x(), aabb.getMax().y(), aabb.getMax().z(), 1.0)).head<3>(); aabb = AABB(std::vector{min, max}); if (!isAABBInFrustum(frustum, aabb)) { continue; } - submitModel(model, tc->getModelMatrix()); + std::vector bone_matrices; + if (m_registry->entityHasComponent(e)) { + auto skeleton_entity = m_registry->getComponent(e)->skeleton_entity; + auto pose = m_registry->getComponent(skeleton_entity); + bone_matrices = pose->final_bone_matrices; + model_mat = m_registry->getComponent(e)->getModelMatrix(); + } + + std::unordered_map> texs; + for (const auto &[name, value] : material->getAllUniforms()) { + if (std::holds_alternative(value)) { + auto v = std::get(value); + if (auto tex = m_asset_bank->getTexture2D(v); tex) { + texs.try_emplace(v, tex); + } + } + } + m_renderer->submitDrawable(Drawable{.mesh = mesh, + .material = material, + .shader = shader, + .textures = texs, + .model_matrix = model_mat, + .bone_matrices = bone_matrices}); } for (int i = 0; i < m_lights.size(); i++) { @@ -70,7 +96,7 @@ void RenderSystem::update(double delta) { auto tc = m_registry->getComponent(light); m_renderer->submitLight(Light{.position = tc->getPosition(), - .rotation = tc->getRotation(), + .rotation = tc->getRotationEulerDeg(), .color = lc->color, .distance_dropoff = lc->distance_dropoff, .type = lc->type}); @@ -88,7 +114,7 @@ void RenderSystem::update(double delta) { } m_api->clear(); - auto shader = m_asset_bank->getAsset(AssetPath::WithTypePrefix("lastpass")); + auto shader = m_asset_bank->getShader(AssetPath::WithTypePrefix("lastpass")); shader->bind(); rendered_fb->bindAttachment(0); @@ -98,49 +124,6 @@ void RenderSystem::update(double delta) { m_api->renderVertexArray(m_quad_vao); } -void RenderSystem::submitModel(const std::shared_ptr &model, const Eigen::Matrix4f &model_matrix) { - - std::vector> meshes; - std::vector materials; - std::vector transforms; - - model->traverse(meshes, materials, transforms, model_matrix); - - for (int i = 0; i < meshes.size(); i++) { - auto mtl_id = materials.at(i); - auto mesh = meshes.at(i); - auto material = m_asset_bank->getAsset(mtl_id); - if (!material) { - continue; - } - auto shader = m_asset_bank->getAsset(material->getShader()); - if (!shader) { - continue; - } - - if (!mesh) { - continue; - } - - std::unordered_map> texs; - for (const auto &[name, value] : material->getAllUniforms()) { - if (std::holds_alternative(value)) { - auto v = std::get(value); - if (auto tex = m_asset_bank->getAsset(v); tex) { - texs.try_emplace(v, tex); - } - } - } - - m_renderer->submitDrawable(Drawable{.mesh = mesh, - .material = material, - .shader = shader, - .textures = texs, - .model_matrix = transforms[i], - .skeleton = model->getSkeleton()}); - } -} - void RenderSystem::onEntityAdded(Entity e) { onEntityRemoved(e); if (m_registry->entityHasComponent(e)) { diff --git a/ICE/System/src/SceneGraphSystem.cpp b/ICE/System/src/SceneGraphSystem.cpp new file mode 100644 index 00000000..618b5d09 --- /dev/null +++ b/ICE/System/src/SceneGraphSystem.cpp @@ -0,0 +1,29 @@ +#include "SceneGraphSystem.h" + +namespace ICE { +SceneGraphSystem::SceneGraphSystem(const std::shared_ptr &scene) : m_scene(scene) { + +} + +void SceneGraphSystem::onEntityAdded(Entity e) { +} +void SceneGraphSystem::onEntityRemoved(Entity e) { +} +void SceneGraphSystem::update(double delta) { + auto root = m_scene->getGraph()->getRoot(); + std::function &, const Eigen::Matrix4f &)> updateNode; + updateNode = [this, &updateNode](const std::shared_ptr &node, const Eigen::Matrix4f &parentMatrix) { + Eigen::Matrix4f newParentMatrix = parentMatrix; + if (node->entity != 0 && m_scene->getRegistry()->entityHasComponent(node->entity)) { + auto tc = m_scene->getRegistry()->getComponent(node->entity); + tc->updateParentMatrix(parentMatrix); + newParentMatrix = tc->getWorldMatrix(); + } + for (const auto &child : node->children) { + updateNode(child, newParentMatrix); + } + }; + updateNode(root, Eigen::Matrix4f::Identity()); +} + +} // namespace ICE \ No newline at end of file diff --git a/ICEBERG/CMakeLists.txt b/ICEBERG/CMakeLists.txt index b20a739a..802f7387 100644 --- a/ICEBERG/CMakeLists.txt +++ b/ICEBERG/CMakeLists.txt @@ -14,6 +14,7 @@ add_executable(${PROJECT_NAME} src/AssetsRenderer.cpp src/Dialog.cpp src/MaterialEditor.cpp + src/ShaderEditor.cpp ${IMGUI_SRC} ${IMGUIZMO_SRC} ${GL3W_SRC} diff --git a/ICEBERG/UI/AddComponentPopup.h b/ICEBERG/UI/AddComponentPopup.h index 2f8be0e8..ed383c67 100644 --- a/ICEBERG/UI/AddComponentPopup.h +++ b/ICEBERG/UI/AddComponentPopup.h @@ -38,7 +38,7 @@ class AddComponentPopup { m_components_combo.render(); if (ImGui::Button("Add")) { if(m_components_combo.getSelectedItem() == "Render Component") - m_registry->addComponent(m_entity, ICE::RenderComponent(0)); + m_registry->addComponent(m_entity, ICE::RenderComponent(0, 0)); if(m_components_combo.getSelectedItem() == "Light Component") m_registry->addComponent(m_entity, ICE::LightComponent(ICE::PointLight, Eigen::Vector3f(1, 1, 1))); diff --git a/ICEBERG/UI/InspectorWidget.h b/ICEBERG/UI/InspectorWidget.h index 058486f5..905579bf 100644 --- a/ICEBERG/UI/InspectorWidget.h +++ b/ICEBERG/UI/InspectorWidget.h @@ -46,8 +46,9 @@ class InspectorWidget : public Widget { void setAnimationComponent(ICE::AnimationComponent* ac, const std::unordered_map& animations) { m_ac_widget.setAnimationComponent(ac, animations); } - void setRenderComponent(ICE::RenderComponent* rc, const std::vector& meshes_paths, const std::vector& meshes_ids) { - m_rc_widget.setRenderComponent(rc, meshes_paths, meshes_ids); + void setRenderComponent(ICE::RenderComponent* rc, const std::vector& meshes_paths, const std::vector& meshes_ids, + const std::vector& material_paths, const std::vector& material_ids) { + m_rc_widget.setRenderComponent(rc, meshes_paths, meshes_ids, material_paths, material_ids); } private: diff --git a/ICEBERG/UI/LightComponentWidget.h b/ICEBERG/UI/LightComponentWidget.h index 9b359ec4..8555a081 100644 --- a/ICEBERG/UI/LightComponentWidget.h +++ b/ICEBERG/UI/LightComponentWidget.h @@ -23,11 +23,11 @@ class LightComponentWidget : public Widget, ImXML::XMLEventHandler { if (node.arg("id") == "light_type_combo") { node.args["preview_value"] = m_light_types[light_type_id]; } else if (node.arg("id") == "point_light") { - node.args["selected"] = light_type_id == 0 ? "true" : false; + node.args["selected"] = light_type_id == 0 ? "true" : "false"; } else if (node.arg("id") == "directional_light") { - node.args["selected"] = light_type_id == 1 ? "true" : false; + node.args["selected"] = light_type_id == 1 ? "true" : "false"; } else if (node.arg("id") == "spot_light") { - node.args["selected"] = light_type_id == 2 ? "true" : false; + node.args["selected"] = light_type_id == 2 ? "true" : "false"; } } void onNodeEnd(ImXML::XMLNode& node) override {} diff --git a/ICEBERG/UI/RenderComponentWidget.h b/ICEBERG/UI/RenderComponentWidget.h index 69a86dcf..f5328019 100644 --- a/ICEBERG/UI/RenderComponentWidget.h +++ b/ICEBERG/UI/RenderComponentWidget.h @@ -19,6 +19,8 @@ class RenderComponentWidget : public Widget, ImXML::XMLEventHandler { void onNodeBegin(ImXML::XMLNode& node) override { if (node.arg("id") == "models_combo") { m_models_combo.render(); + } else if (node.arg("id") == "materials_combo") { + m_material_combo.render(); } } void onNodeEnd(ImXML::XMLNode& node) override {} @@ -30,18 +32,24 @@ class RenderComponentWidget : public Widget, ImXML::XMLEventHandler { } } - void setRenderComponent(ICE::RenderComponent* rc, const std::vector& meshes_paths, const std::vector& meshes_ids) { + void setRenderComponent(ICE::RenderComponent* rc, const std::vector& meshes_paths, const std::vector& meshes_ids, + const std::vector& materials_paths, const std::vector& materials_ids) { m_rc = rc; if (m_rc) { - m_models_combo.setValue(rc->model); + m_models_combo.setValue(rc->mesh); m_models_combo.setAssetComboList(meshes_paths, meshes_ids); - m_models_combo.onValueChanged([this](const ICE::UniformValue& v) { m_rc->model = std::get(v); }); + m_models_combo.onValueChanged([this](const ICE::UniformValue& v) { m_rc->mesh = std::get(v); }); + + m_material_combo.setValue(rc->material); + m_material_combo.setAssetComboList(materials_paths, materials_ids); + m_material_combo.onValueChanged([this](const ICE::UniformValue& v) { m_rc->material = std::get(v); }); } } private: ICE::RenderComponent* m_rc = nullptr; UniformInputs m_models_combo{"##models_combo", 0}; + UniformInputs m_material_combo{"##materials_combo", 0}; ImXML::XMLTree m_xml_tree; ImXML::XMLRenderer m_xml_renderer; diff --git a/ICEBERG/UI/ShaderEditDialog.h b/ICEBERG/UI/ShaderEditDialog.h new file mode 100644 index 00000000..106530d6 --- /dev/null +++ b/ICEBERG/UI/ShaderEditDialog.h @@ -0,0 +1,62 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "Components/ComboBox.h" +#include "Components/InputText.h" +#include "Components/UniformInputs.h" +#include "Dialog.h" + +class ShaderEditDialog : public Dialog, ImXML::XMLEventHandler { + public: + ShaderEditDialog() : m_xml_tree(ImXML::XMLReader().read("XML/MaterialEditPopup.xml")) { + m_xml_renderer.addDynamicBind("str_shader_name", {m_shader_name, 512, ImXML::Chars}); + } + + std::string getName() const { return std::string(m_shader_name); } + + void render() override { + ImGui::PushID(m_dialog_id); + if (isOpenRequested()) + ImGui::OpenPopup("Material Editor"); + //m_xml_renderer.render(m_xml_tree, *this); + if (ImGui::BeginTabBar("test", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) { + if (ImGui::BeginTabItem("Vertex Stage")) { + ImGui::Text("Vertex Shader Code Editor Here"); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Fragment Stage")) { + ImGui::Text("Fragment Shader Code Editor Here"); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); + } + ImGui::PopID(); + } + + void onNodeBegin(ImXML::XMLNode& node) override {} + void onNodeEnd(ImXML::XMLNode& node) override {} + void onEvent(ImXML::XMLNode& node) override { + if (node.arg("id") == "btn_apply") { + ImGui::CloseCurrentPopup(); + done(DialogResult::Ok); + } else if (node.arg("id") == "btn_cancel") { + ImGui::CloseCurrentPopup(); + done(DialogResult::Cancel); + } + } + + private: + char m_shader_name[512] = {0}; + + ImXML::XMLTree m_xml_tree; + ImXML::XMLRenderer m_xml_renderer; +}; diff --git a/ICEBERG/UI/TransformComponentWidget.h b/ICEBERG/UI/TransformComponentWidget.h index 3ae14297..dba3a504 100644 --- a/ICEBERG/UI/TransformComponentWidget.h +++ b/ICEBERG/UI/TransformComponentWidget.h @@ -43,8 +43,8 @@ class TransformComponentWidget : public Widget, ImXML::XMLEventHandler { if (tc) { m_transform_input.setValue(tc->getPosition()); m_transform_input.onValueChanged([this](const ICE::UniformValue& v) { m_tc->setPosition(std::get(v)); }); - m_rotation_input.setValue(tc->getRotation()); - m_rotation_input.onValueChanged([this](const ICE::UniformValue& v) { m_tc->setRotation(std::get(v)); }); + m_rotation_input.setValue(tc->getRotationEulerDeg()); + m_rotation_input.onValueChanged([this](const ICE::UniformValue& v) { m_tc->setRotationEulerDeg(std::get(v)); }); m_scale_input.setValue(tc->getScale()); m_scale_input.onValueChanged([this](const ICE::UniformValue& v) { m_tc->setScale(std::get(v)); }); } diff --git a/ICEBERG/XML/RenderComponentWidget.xml b/ICEBERG/XML/RenderComponentWidget.xml index d3ffacd8..c352064a 100644 --- a/ICEBERG/XML/RenderComponentWidget.xml +++ b/ICEBERG/XML/RenderComponentWidget.xml @@ -8,11 +8,19 @@ - + + + + + + + + +