From 0caf28943faeb164031d7c16a9757a4e6429e5e4 Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Sat, 12 Aug 2023 21:47:26 -0400 Subject: [PATCH] Added new component and panel + model loader --- .../src/ComponentsPanel/SkinnedModelPanel.h | 79 +++++++ Editor/src/Windows/EditorSelectionPanel.cpp | 2 + Editor/src/Windows/EditorSelectionPanel.h | 2 + Nuake/src/Rendering/AABB.h | 9 + Nuake/src/Rendering/Mesh/SkinnedMesh.cpp | 197 ++++++++++++++++++ Nuake/src/Rendering/Mesh/SkinnedMesh.h | 67 ++++++ Nuake/src/Rendering/Vertex.h | 14 ++ Nuake/src/Resource/ModelLoader.cpp | 173 ++++++++++++++- Nuake/src/Resource/ModelLoader.h | 13 ++ Nuake/src/Resource/SkinnedModel.cpp | 73 +++++++ Nuake/src/Resource/SkinnedModel.h | 26 +++ .../Components/SkinnedModelComponent.cpp | 16 ++ .../Scene/Components/SkinnedModelComponent.h | 45 ++++ 13 files changed, 712 insertions(+), 4 deletions(-) create mode 100644 Editor/src/ComponentsPanel/SkinnedModelPanel.h create mode 100644 Nuake/src/Rendering/Mesh/SkinnedMesh.cpp create mode 100644 Nuake/src/Rendering/Mesh/SkinnedMesh.h create mode 100644 Nuake/src/Resource/SkinnedModel.cpp create mode 100644 Nuake/src/Resource/SkinnedModel.h create mode 100644 Nuake/src/Scene/Components/SkinnedModelComponent.cpp create mode 100644 Nuake/src/Scene/Components/SkinnedModelComponent.h diff --git a/Editor/src/ComponentsPanel/SkinnedModelPanel.h b/Editor/src/ComponentsPanel/SkinnedModelPanel.h new file mode 100644 index 00000000..9bebded1 --- /dev/null +++ b/Editor/src/ComponentsPanel/SkinnedModelPanel.h @@ -0,0 +1,79 @@ +#pragma once +#include +#include "ComponentPanel.h" +#include "ModelResourceInspector.h" + +#include +#include + +#include +#include + +class SkinnedModelPanel : ComponentPanel +{ +private: + Scope _modelInspector; + bool _expanded = false; + +public: + SkinnedModelPanel() + { + CreateScope(); + } + + void Draw(Nuake::Entity entity) override + { + using namespace Nuake; + if (!entity.HasComponent()) + return; + + SkinnedModelComponent& component = entity.GetComponent(); + BeginComponentTable(SKINNED MESH, SkinnedModelComponent); + { + ImGui::Text("Model"); + ImGui::TableNextColumn(); + + std::string label = "None"; + + const bool isModelNone = component.ModelResource == nullptr; + if (!isModelNone) + { + label = std::to_string(component.ModelResource->ID); + } + + if (ImGui::Button(label.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0))) + { + } + + if (_expanded) + { + _modelInspector->Draw(); + } + + if (ImGui::BeginDragDropTarget()) + { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Model")) + { + char* file = (char*)payload->Data; + std::string fullPath = std::string(file, 256); + fullPath = Nuake::FileSystem::AbsoluteToRelative(fullPath); + + if (Nuake::String::EndsWith(fullPath, ".model")) + { + + } + else + { + component.ModelPath = fullPath; + component.LoadModel(); + } + } + ImGui::EndDragDropTarget(); + } + + ImGui::TableNextColumn(); + ComponentTableReset(component.ModelPath, ""); + } + EndComponentTable(); + } +}; \ No newline at end of file diff --git a/Editor/src/Windows/EditorSelectionPanel.cpp b/Editor/src/Windows/EditorSelectionPanel.cpp index f9ac502a..bb77a732 100644 --- a/Editor/src/Windows/EditorSelectionPanel.cpp +++ b/Editor/src/Windows/EditorSelectionPanel.cpp @@ -103,6 +103,7 @@ void EditorSelectionPanel::DrawEntity(Nuake::Entity entity) mParticleEmitterPanel.Draw(entity); mSpritePanel.Draw(entity); mMeshPanel.Draw(entity); + mSkinnedModelPanel.Draw(entity); mQuakeMapPanel.Draw(entity); mCameraPanel.Draw(entity); mRigidbodyPanel.Draw(entity); @@ -131,6 +132,7 @@ void EditorSelectionPanel::DrawAddComponentMenu(Nuake::Entity entity) MenuItemComponent("Camera", Nuake::CameraComponent) MenuItemComponent("Light", Nuake::LightComponent) MenuItemComponent("Model", Nuake::ModelComponent) + MenuItemComponent("Skinned Model", Nuake::SkinnedModelComponent) MenuItemComponent("Sprite", Nuake::SpriteComponent) MenuItemComponent("Particle Emitter", Nuake::ParticleEmitterComponent) ImGui::Separator(); diff --git a/Editor/src/Windows/EditorSelectionPanel.h b/Editor/src/Windows/EditorSelectionPanel.h index 703e59bf..03f71bc2 100644 --- a/Editor/src/Windows/EditorSelectionPanel.h +++ b/Editor/src/Windows/EditorSelectionPanel.h @@ -20,6 +20,7 @@ #include "../ComponentsPanel/CharacterControllerPanel.h" #include "../ComponentsPanel/SpritePanel.h" #include "../ComponentsPanel/ParticleEmitterPanel.h" +#include "../ComponentsPanel/SkinnedModelPanel.h" class EditorSelectionPanel @@ -29,6 +30,7 @@ private: LightPanel mLightPanel; ScriptPanel mScriptPanel; MeshPanel mMeshPanel; + SkinnedModelPanel mSkinnedModelPanel; QuakeMapPanel mQuakeMapPanel; CameraPanel mCameraPanel; RigidbodyPanel mRigidbodyPanel; diff --git a/Nuake/src/Rendering/AABB.h b/Nuake/src/Rendering/AABB.h index 90fdbb7a..6987ab90 100644 --- a/Nuake/src/Rendering/AABB.h +++ b/Nuake/src/Rendering/AABB.h @@ -8,6 +8,15 @@ namespace Nuake { Vector3 Min; Vector3 Max; + AABB() = default; + ~AABB() = default; + + AABB(const Vector3& min, const Vector3& max) + { + Min = min; + Max = max; + } + // Transforms the bounding box and recalculate an axis aligned box void Transform(Matrix4 transform) { diff --git a/Nuake/src/Rendering/Mesh/SkinnedMesh.cpp b/Nuake/src/Rendering/Mesh/SkinnedMesh.cpp new file mode 100644 index 00000000..3874e67c --- /dev/null +++ b/Nuake/src/Rendering/Mesh/SkinnedMesh.cpp @@ -0,0 +1,197 @@ +#include "SkinnedMesh.h" + +#include "src/Core/Maths.h" +#include "src/Rendering/Textures/Material.h" +#include "src/Rendering/Textures/MaterialManager.h" +#include "src/Rendering/Renderer.h" +#include "src/Rendering/Shaders/Shader.h" + +#include "src/Rendering/Vertex.h" +#include "src/Rendering/Buffers/VertexBuffer.h" +#include "src/Rendering/Buffers/VertexArray.h" +#include "src/Rendering/Buffers/VertexBufferLayout.h" + +#include + +namespace Nuake +{ + void SkinnedMesh::AddSurface(std::vector vertices, std::vector indices, std::vector bones) + { + m_Vertices = vertices; + m_Indices = indices; + m_Bones = bones; + + SetupMesh(); + CalculateAABB(); + + if (m_Material == nullptr) + { + m_Material = MaterialManager::Get()->GetMaterial("default"); + } + } + + std::vector& SkinnedMesh::GetVertices() + { + return m_Vertices; + } + + std::vector& SkinnedMesh::GetIndices() + { + return m_Indices; + } + + Ref SkinnedMesh::GetMaterial() inline const + { + return m_Material; + } + + void SkinnedMesh::SetMaterial(Ref material) + { + m_Material = material; + MaterialManager::Get()->RegisterMaterial(material); + } + + void SkinnedMesh::CalculateAABB() + { + float minX = 0.0f; + float minY = 0.0f; + float minZ = 0.0f; + float maxX = 0.0f; + float maxY = 0.0f; + float maxZ = 0.0f; + + for (const SkinnedVertex& v : m_Vertices) + { + minX = v.position.x < minX ? v.position.x : minX; + minY = v.position.y < minY ? v.position.y : minY; + minZ = v.position.z < minZ ? v.position.z : minZ; + maxX = v.position.x > maxX ? v.position.x : maxX; + maxY = v.position.y > maxY ? v.position.y : maxY; + maxZ = v.position.z > maxZ ? v.position.z : maxZ; + } + + m_AABB = AABB(Vector3(minX, minY, minZ), Vector3(maxX, maxY, maxZ)); + } + + void SkinnedMesh::SetupMesh() + { + m_VertexArray = CreateScope(); + m_VertexArray->Bind(); + m_VertexBuffer = CreateScope(m_Vertices.data(), m_Vertices.size() * sizeof(Vertex)); + m_ElementBuffer = CreateScope(m_Indices.data(), m_Indices.size() * sizeof(unsigned int), RendererEnum::ELEMENT_ARRAY_BUFFER); + + VertexBufferLayout bufferLayout = VertexBufferLayout(); + bufferLayout.Push(3); // Position + bufferLayout.Push(2); // UV + bufferLayout.Push(3); // Normal + bufferLayout.Push(3); // Tangent + bufferLayout.Push(3); // Bitangent + bufferLayout.Push(4); // BoneIds + bufferLayout.Push(4); // Weights + + m_VertexArray->AddBuffer(*m_VertexBuffer, bufferLayout); + m_VertexArray->Unbind(); + } + + void SkinnedMesh::Bind() const + { + m_VertexArray->Bind(); + } + + void SkinnedMesh::Draw(Shader* shader, bool bindMaterial) + { + if (bindMaterial) + m_Material->Bind(shader); + + m_VertexArray->Bind(); + RenderCommand::DrawElements(RendererEnum::TRIANGLES, (int)m_Indices.size(), RendererEnum::UINT, 0); + } + + void SkinnedMesh::DebugDraw() + { + Renderer::m_DebugShader->Bind(); + Renderer::m_DebugShader->SetUniform4f("u_Color", 1.0f, 0.0f, 0.0f, 1.f); + + m_VertexArray->Bind(); + RenderCommand::DrawElements(RendererEnum::TRIANGLES, (int)m_Indices.size(), RendererEnum::UINT, 0); + } + + json SkinnedMesh::Serialize() + { + BEGIN_SERIALIZE(); + + j["Material"] = m_Material->Serialize(); + j["Indices"] = m_Indices; + + for (uint32_t i = 0; i < m_Bones.size(); i++) + { + //j["Bones"][i] = m_Bones[i]; + } + json v; + for (uint32_t i = 0; i < m_Vertices.size(); i++) + { + v["Position"]["x"] = m_Vertices[i].position.x; + v["Position"]["y"] = m_Vertices[i].position.y; + v["Position"]["z"] = m_Vertices[i].position.z; + + v["UV"]["x"] = m_Vertices[i].uv.x; + v["UV"]["y"] = m_Vertices[i].uv.y; + + v["Normal"]["x"] = m_Vertices[i].normal.x; + v["Normal"]["y"] = m_Vertices[i].normal.y; + v["Normal"]["z"] = m_Vertices[i].normal.z; + + v["Tangent"]["x"] = m_Vertices[i].tangent.x; + v["Tangent"]["y"] = m_Vertices[i].tangent.y; + v["Tangent"]["z"] = m_Vertices[i].tangent.z; + + v["Bitangent"]["x"] = m_Vertices[i].bitangent.x; + v["Bitangent"]["y"] = m_Vertices[i].bitangent.y; + v["Bitangent"]["z"] = m_Vertices[i].bitangent.z; + + j["Vertices"][i] = v; + } + + + END_SERIALIZE(); + } + + bool SkinnedMesh::Deserialize(const json& j) + { + m_Material = CreateRef(); + m_Material->Deserialize(j["Material"]); + + m_Indices.reserve(j["Indices"].size()); + for (auto& i : j["Indices"]) + { + m_Indices.push_back(i); + } + + std::vector vertices; + + std::async(std::launch::async, [&]() + { + for (auto& v : j["Vertices"]) + { + SkinnedVertex vertex; + try { + DESERIALIZE_VEC2(v["UV"], vertex.uv) + } + catch (std::exception& e) { + vertex.uv = { 0.0, 0.0 }; + } + DESERIALIZE_VEC3(v["Position"], vertex.position) + DESERIALIZE_VEC3(v["Normal"], vertex.normal) + DESERIALIZE_VEC3(v["Tangent"], vertex.tangent) + DESERIALIZE_VEC3(v["Bitangent"], vertex.bitangent) + vertices.push_back(vertex); + } + } + ); + + m_Vertices = vertices; + + SetupMesh(); + return true; + } +} diff --git a/Nuake/src/Rendering/Mesh/SkinnedMesh.h b/Nuake/src/Rendering/Mesh/SkinnedMesh.h new file mode 100644 index 00000000..55de6bce --- /dev/null +++ b/Nuake/src/Rendering/Mesh/SkinnedMesh.h @@ -0,0 +1,67 @@ +#pragma once +#include "src/Core/Core.h" +#include "src/Rendering/AABB.h" +#include "src/Resource/Resource.h" +#include "src/Resource/Serializable.h" +#include "src/Rendering/Vertex.h" + +namespace Nuake +{ + class VertexBuffer; + class VertexArray; + class Material; + struct Vertex; + class Shader; + + struct BoneVertexWeight + { + uint32_t VertexID; + float Weight; + }; + + struct Bone + { + std::string Name; + Matrix4 Offset; + std::vector VertexWeights; + }; + + class SkinnedMesh : ISerializable, Resource + { + public: + SkinnedMesh() = default; + ~SkinnedMesh() = default; + + void AddSurface(std::vector vertices, std::vector indices, std::vector bones); + std::vector& GetVertices(); + std::vector& GetIndices(); + std::vector& GetBones(); + + Ref GetMaterial() inline const; + void SetMaterial(Ref material); + + void Bind() const; + void Draw(Shader* shader, bool bindMaterial = true); + void DebugDraw(); + + inline AABB GetAABB() const { return m_AABB; } + + json Serialize() override; + bool Deserialize(const json& j) override; + + private: + Ref m_Material = nullptr; + std::vector m_Indices; + std::vector m_Vertices; + std::vector m_Bones; + + Scope m_VertexBuffer; + Scope m_VertexArray; + Scope m_ElementBuffer; + + void SetupMesh(); + + AABB m_AABB; + void CalculateAABB(); + }; +} \ No newline at end of file diff --git a/Nuake/src/Rendering/Vertex.h b/Nuake/src/Rendering/Vertex.h index af1cff9e..ef5aca9a 100644 --- a/Nuake/src/Rendering/Vertex.h +++ b/Nuake/src/Rendering/Vertex.h @@ -12,6 +12,20 @@ namespace Nuake Vector3 bitangent; }; + const uint32_t MAX_BONE_INFLUENCE = 4; + struct SkinnedVertex + { + Vector3 position; + Vector2 uv; + Vector3 normal; + Vector3 tangent; + Vector3 bitangent; + + int boneIDs[MAX_BONE_INFLUENCE]; + //weights from each bone + float weights[MAX_BONE_INFLUENCE]; + }; + struct LineVertex { Vector3 position; diff --git a/Nuake/src/Resource/ModelLoader.cpp b/Nuake/src/Resource/ModelLoader.cpp index 1f39eab3..9737f782 100644 --- a/Nuake/src/Resource/ModelLoader.cpp +++ b/Nuake/src/Resource/ModelLoader.cpp @@ -5,6 +5,7 @@ #include "src/Core/String.h" +#include "src/Resource/SkinnedModel.h" #include "src/Resource/Model.h" @@ -18,8 +19,8 @@ namespace Nuake m_Meshes.clear(); Ref model = CreateRef(path); - Assimp::Importer import; - import.SetPropertyFloat("PP_GSN_MAX_SMOOTHING_ANGLE", 90); + Assimp::Importer importer; + importer.SetPropertyFloat("PP_GSN_MAX_SMOOTHING_ANGLE", 90); auto importFlags = aiProcess_Triangulate | @@ -29,10 +30,10 @@ namespace Nuake modelDir = absolute ? path + "/../" : FileSystem::Root + path + "/../"; const std::string filePath = absolute ? path : FileSystem::Root + path; - const aiScene* scene = import.ReadFile(filePath, importFlags); + const aiScene* scene = importer.ReadFile(filePath, importFlags); if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { - std::string assimpErrorMsg = std::string(import.GetErrorString()); + std::string assimpErrorMsg = std::string(importer.GetErrorString()); std::string logMsg = "[Failed to load model] - " + assimpErrorMsg; Logger::Log(logMsg, "model", WARNING); @@ -49,6 +50,42 @@ namespace Nuake return model; } + Ref ModelLoader::LoadSkinnedModel(const std::string& path, bool absolute) + { + m_Meshes.clear(); + Ref model = CreateRef(path); + + Assimp::Importer importer; + importer.SetPropertyFloat("PP_GSN_MAX_SMOOTHING_ANGLE", 90); + + auto importFlags = + aiProcess_Triangulate | + aiProcess_GenSmoothNormals | + aiProcess_FixInfacingNormals | + aiProcess_CalcTangentSpace; + + modelDir = absolute ? path + "/../" : FileSystem::Root + path + "/../"; + const std::string filePath = absolute ? path : FileSystem::Root + path; + const aiScene* scene = importer.ReadFile(filePath, importFlags); + if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) + { + std::string assimpErrorMsg = std::string(importer.GetErrorString()); + std::string logMsg = "[Failed to load model] - " + assimpErrorMsg; + Logger::Log(logMsg, "model", WARNING); + + return model; + } + + ProcessNode(scene->mRootNode, scene); + + for (const auto& mesh : m_SkinnedMeshes) + { + model->AddMesh(mesh); + } + + return model; + } + void ModelLoader::ProcessNode(aiNode* node, const aiScene* scene) { for (uint32_t i = 0; i < node->mNumMeshes; i++) @@ -63,12 +100,84 @@ namespace Nuake } } + void ModelLoader::ProcessSkinnedNode(aiNode* node, const aiScene* scene) + { + for (uint32_t i = 0; i < node->mNumMeshes; i++) + { + aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; + m_SkinnedMeshes.push_back(ProcessSkinnedMesh(mesh, scene)); + } + + for (uint32_t i = 0; i < node->mNumChildren; i++) + { + ProcessSkinnedNode(node->mChildren[i], scene); + } + } + + Ref ModelLoader::ProcessSkinnedMesh(aiMesh* node, const aiScene* scene) + { + auto vertices = ProcessSkinnedVertices(node); + auto indices = ProcessIndices(node); + auto material = ProcessMaterials(scene, node); + auto bones = std::vector(); + if (node->HasBones()) + { + for (uint32_t i = 0; i < node->mNumBones; i++) + { + aiBone* bone = node->mBones[i]; + const std::string& boneName = bone->mName.C_Str(); + const auto& boneMatrix = bone->mOffsetMatrix; + + for (uint32_t j = 0; j < bone->mNumWeights; j++) + { + aiVertexWeight vertexWeight = bone->mWeights[j]; + + const float weigth = vertexWeight.mWeight; + uint32_t vertexId = vertexWeight.mVertexId; + + vertices[vertexId].boneIDs[j] = i; + } + } + } + else + { + Logger::Log("Using skinned mesh imported while the model has no bones!", "model loader", WARNING); + } + + // Fill in the bones in the vertices + + + Ref mesh = CreateRef(); + mesh->AddSurface(vertices, indices, bones); + mesh->SetMaterial(material); + + return mesh; + } + Ref ModelLoader::ProcessMesh(aiMesh* node, const aiScene* scene) { auto vertices = ProcessVertices(node); auto indices = ProcessIndices(node); auto material = ProcessMaterials(scene, node); + if (node->HasBones()) + { + for (uint32_t i = 0; i < node->mNumBones; i++) + { + aiBone* bone = node->mBones[i]; + const std::string& boneName = bone->mName.C_Str(); + const auto& boneMatrix = bone->mOffsetMatrix; + + for (uint32_t j = 0; j < bone->mNumWeights; j++) + { + aiVertexWeight vertexWeight = bone->mWeights[j]; + + const float weigth = vertexWeight.mWeight; + uint32_t vertexId = vertexWeight.mVertexId; + } + } + } + Ref mesh = CreateRef(); mesh->AddSurface(vertices, indices); mesh->SetMaterial(material); @@ -130,6 +239,62 @@ namespace Nuake return vertices; } + std::vector ModelLoader::ProcessSkinnedVertices(aiMesh* mesh) + { + auto vertices = std::vector(); + for (uint32_t i = 0; i < mesh->mNumVertices; i++) + { + SkinnedVertex vertex; + + Vector3 current; + + // Position + current.x = mesh->mVertices[i].x; + current.y = mesh->mVertices[i].y; + current.z = mesh->mVertices[i].z; + vertex.position = current; + + // Normals + current.x = mesh->mNormals[i].x; + current.y = mesh->mNormals[i].y; + current.z = mesh->mNormals[i].z; + vertex.normal = current; + + // Tangents + if (mesh->mTangents) + { + current.x = mesh->mTangents[i].x; + current.y = mesh->mTangents[i].y; + current.z = mesh->mTangents[i].z; + vertex.tangent = current; + } + + if (mesh->mBitangents) + { + current.x = mesh->mBitangents[i].x; + current.y = mesh->mBitangents[i].y; + current.z = mesh->mBitangents[i].z; + vertex.bitangent = current; + } + + vertex.uv = glm::vec2(0.0f, 0.0f); + + // Does it contain UVs? + if (mesh->mTextureCoords[0]) + { + float u = mesh->mTextureCoords[0][i].x; + float v = mesh->mTextureCoords[0][i].y; + vertex.uv = Vector2(u, v); + } + + // We are filling the bones later. + + vertices.push_back(vertex); + } + + return vertices; + } + std::vector ModelLoader::ProcessIndices(aiMesh* mesh) { auto indices = std::vector(); diff --git a/Nuake/src/Resource/ModelLoader.h b/Nuake/src/Resource/ModelLoader.h index a6127832..888c63f7 100644 --- a/Nuake/src/Resource/ModelLoader.h +++ b/Nuake/src/Resource/ModelLoader.h @@ -1,6 +1,7 @@ #pragma once #include "src/Core/Core.h" +#include "src/Rendering/Mesh/SkinnedMesh.h" #include "src/Rendering/Mesh/Mesh.h" #include "src/Rendering/Textures/Material.h" #include "src/Rendering/Textures/Texture.h" @@ -11,9 +12,13 @@ #include #include +#include "src/Rendering/Buffers/VertexArray.h" + namespace Nuake { class Model; + class SkinnedModel; + class ModelLoader { public: @@ -21,9 +26,12 @@ namespace Nuake ~ModelLoader(); Ref LoadModel(const std::string& path, bool absolute = false); + Ref LoadSkinnedModel(const std::string& path, bool absolute = false); + private: std::string modelDir; std::vector> m_Meshes; + std::vector> m_SkinnedMeshes; void ProcessNode(aiNode* node, const aiScene* scene); Ref ProcessMesh(aiMesh* node, const aiScene* scene); @@ -32,5 +40,10 @@ namespace Nuake std::vector ProcessIndices(aiMesh* mesh); Ref ProcessMaterials(const aiScene* scene, aiMesh* mesh); Ref ProcessTextures(const aiScene* scene, const std::string& path); + + // Skinned + void ProcessSkinnedNode(aiNode* node, const aiScene* scene); + Ref ProcessSkinnedMesh(aiMesh* node, const aiScene* scene); + std::vector ProcessSkinnedVertices(aiMesh* mesh); }; } \ No newline at end of file diff --git a/Nuake/src/Resource/SkinnedModel.cpp b/Nuake/src/Resource/SkinnedModel.cpp new file mode 100644 index 00000000..a638fa91 --- /dev/null +++ b/Nuake/src/Resource/SkinnedModel.cpp @@ -0,0 +1,73 @@ +#include "src/Resource/ModelLoader.h" + +#include "src/Resource/SkinnedModel.h" +#include "src/Core/FileSystem.h" +#include "src/Core/Logger.h" + + +namespace Nuake +{ + SkinnedModel::SkinnedModel(const std::string path) : m_Meshes(std::vector>()) + { + this->Path = path; + } + + SkinnedModel::SkinnedModel() : m_Meshes(std::vector>()) + {} + + SkinnedModel::~SkinnedModel() {} + + void SkinnedModel::AddMesh(Ref mesh) + { + m_Meshes.push_back(mesh); + } + + std::vector>& SkinnedModel::GetMeshes() + { + return m_Meshes; + } + + json SkinnedModel::Serialize() + { + BEGIN_SERIALIZE(); + + if (this->Path != "") + { + j["Path"] = this->Path; + } + else + { + for (uint32_t i = 0; i < std::size(m_Meshes); i++) + { + j["Meshes"][i] = m_Meshes[i]->Serialize(); + } + } + END_SERIALIZE(); + } + + bool SkinnedModel::Deserialize(const json& j) + { + if (j.contains("Path")) + { + this->IsEmbedded = true; + + ModelLoader loader; + auto otherModel = loader.LoadSkinnedModel(j["Path"], false); + m_Meshes = otherModel->GetMeshes(); + + this->Path = j["Path"]; + } + else + { + for (auto& m : j["Meshes"]) + { + auto mesh = CreateRef(); + mesh->Deserialize(m); + + m_Meshes.push_back(mesh); + } + } + + return true; + } +} \ No newline at end of file diff --git a/Nuake/src/Resource/SkinnedModel.h b/Nuake/src/Resource/SkinnedModel.h new file mode 100644 index 00000000..96278d72 --- /dev/null +++ b/Nuake/src/Resource/SkinnedModel.h @@ -0,0 +1,26 @@ +#pragma once +#include "src/Core/Core.h" +#include "src/Rendering/Mesh/SkinnedMesh.h" +#include "src/Resource/Resource.h" +#include "src/Resource/Serializable.h" + + +namespace Nuake +{ + class SkinnedModel : public Resource, ISerializable + { + private: + std::vector> m_Meshes; + + public: + SkinnedModel(); + SkinnedModel(const std::string path); + ~SkinnedModel(); + + void AddMesh(Ref mesh); + std::vector>& GetMeshes(); + + json Serialize() override; + bool Deserialize(const json& j) override; + }; +} \ No newline at end of file diff --git a/Nuake/src/Scene/Components/SkinnedModelComponent.cpp b/Nuake/src/Scene/Components/SkinnedModelComponent.cpp new file mode 100644 index 00000000..0dcee3f3 --- /dev/null +++ b/Nuake/src/Scene/Components/SkinnedModelComponent.cpp @@ -0,0 +1,16 @@ +#include "SkinnedModelComponent.h" +#include "src/Resource/ModelLoader.h" + +namespace Nuake +{ + SkinnedModelComponent::SkinnedModelComponent() + { + + } + + void SkinnedModelComponent::LoadModel() + { + auto loader = ModelLoader(); + this->ModelResource = loader.LoadSkinnedModel(ModelPath); + } +} \ No newline at end of file diff --git a/Nuake/src/Scene/Components/SkinnedModelComponent.h b/Nuake/src/Scene/Components/SkinnedModelComponent.h new file mode 100644 index 00000000..e536275f --- /dev/null +++ b/Nuake/src/Scene/Components/SkinnedModelComponent.h @@ -0,0 +1,45 @@ +#pragma once +#include + +#include "src/Resource/Serializable.h" +#include "src/Resource/SkinnedModel.h" + +#include + + +namespace Nuake +{ + struct SkinnedModelComponent + { + Ref ModelResource; + std::string ModelPath; + + SkinnedModelComponent(); + + void LoadModel(); + + std::string directory; + + json Serialize() + { + BEGIN_SERIALIZE(); + SERIALIZE_VAL(ModelPath); + SERIALIZE_OBJECT(ModelResource); + END_SERIALIZE(); + } + + bool Deserialize(const json& j) + { + ModelPath = j["ModelPath"]; + ModelResource = CreateRef(); + + if (j.contains("ModelResource")) + { + auto& res = j["ModelResource"]; + ModelResource->Deserialize(res); + } + + return true; + } + }; +}