diff --git a/Nuake/src/Rendering/Mesh/Animation.cpp b/Nuake/src/Rendering/Mesh/Animation.cpp new file mode 100644 index 00000000..1bbab93e --- /dev/null +++ b/Nuake/src/Rendering/Mesh/Animation.cpp @@ -0,0 +1,10 @@ +#include + +namespace Nuake +{ + class Animation + { + Animation() = default; + + }; +} \ No newline at end of file diff --git a/Nuake/src/Resource/ModelLoader.cpp b/Nuake/src/Resource/ModelLoader.cpp index d7b26160..199b2b73 100644 --- a/Nuake/src/Resource/ModelLoader.cpp +++ b/Nuake/src/Resource/ModelLoader.cpp @@ -7,7 +7,7 @@ #include "src/Resource/SkinnedModel.h" #include "src/Resource/Model.h" - +#include "src/Resource/SkeletalAnimation.h" namespace Nuake { @@ -70,7 +70,7 @@ namespace Nuake 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; + std::string logMsg = "Failed to load model: " + assimpErrorMsg; Logger::Log(logMsg, "model", WARNING); return model; @@ -78,6 +78,24 @@ namespace Nuake ProcessSkinnedNode(scene->mRootNode, scene); + if (scene->HasAnimations()) + { + SkeletalAnimation animation; + + for (uint32_t i = 0; i < scene->mNumAnimations; i++) + { + aiAnimation* aiAnim = scene->mAnimations[i]; + const float duration = aiAnim->mDuration; + const float ticksPerSecond = aiAnim->mTicksPerSecond; + + // Read data + SkeletonNode rootSkeletonNode; + ProcessAnimationNode(rootSkeletonNode, scene->mRootNode); + + model->SetSkeletonRootNode(rootSkeletonNode); + } + } + for (const auto& mesh : m_SkinnedMeshes) { model->AddMesh(mesh); @@ -177,7 +195,6 @@ namespace Nuake Ref mesh = CreateRef(); mesh->AddSurface(vertices, indices, bones); mesh->SetMaterial(material); - return mesh; } @@ -320,6 +337,22 @@ namespace Nuake } } + void ModelLoader::ProcessAnimationNode(SkeletonNode& dest, const aiNode* src) + { + assert(src); + + dest.Name = src->mName.data; + dest.Transform = ConvertMatrixToGLMFormat(src->mTransformation); + dest.ChildrenCount = src->mNumChildren; + + for (uint32_t i = 0; i < dest.ChildrenCount; i++) + { + SkeletonNode newNode; + ProcessAnimationNode(newNode, src->mChildren[i]); + dest.Children.push_back(std::move(newNode)); + } + } + 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 32340eb6..a0a8e092 100644 --- a/Nuake/src/Resource/ModelLoader.h +++ b/Nuake/src/Resource/ModelLoader.h @@ -7,6 +7,7 @@ #include "src/Rendering/Textures/Texture.h" #include "src/Rendering/Vertex.h" +#include "src/Resource/SkeletonNode.h" #include "assimp/Importer.hpp" #include @@ -46,6 +47,7 @@ namespace Nuake Ref ProcessSkinnedMesh(aiMesh* node, const aiScene* scene); std::vector ProcessSkinnedVertices(aiMesh* mesh); void SetVertexBoneData(SkinnedVertex& vertex, int boneId, float weight); + void ProcessAnimationNode(SkeletonNode& dest, const aiNode* src); static inline Matrix4 ConvertMatrixToGLMFormat(const aiMatrix4x4& from) { diff --git a/Nuake/src/Resource/SkeletalAnimation.h b/Nuake/src/Resource/SkeletalAnimation.h index af3109f8..668495be 100644 --- a/Nuake/src/Resource/SkeletalAnimation.h +++ b/Nuake/src/Resource/SkeletalAnimation.h @@ -3,16 +3,25 @@ namespace Nuake { - class Animation + struct SkeletonAnimationBoneAnimation + { + std::string Name; + Vector3 Positions; + Quat Rotations; + Vector3 Scalings; + }; + + class SkeletalAnimation { private: float m_Duration; int m_TicksPerSecond; + std::vector m_Bones; - //std::map m_BoneInfoMap; + public: - Animation() = default; - Animation(); + SkeletalAnimation() = default; + ~SkeletalAnimation() = default; Bone& FindBone(const std::string& boneName); diff --git a/Nuake/src/Resource/SkeletonNode.h b/Nuake/src/Resource/SkeletonNode.h new file mode 100644 index 00000000..7c8e2277 --- /dev/null +++ b/Nuake/src/Resource/SkeletonNode.h @@ -0,0 +1,14 @@ +#pragma once +#include "src/Core/Core.h" +#include "src/Core/Maths.h" + +namespace Nuake +{ + struct SkeletonNode + { + Matrix4 Transform; + std::string Name; + int ChildrenCount; + std::vector Children; + }; +} \ No newline at end of file diff --git a/Nuake/src/Resource/SkinnedModel.h b/Nuake/src/Resource/SkinnedModel.h index 96278d72..fa4cc819 100644 --- a/Nuake/src/Resource/SkinnedModel.h +++ b/Nuake/src/Resource/SkinnedModel.h @@ -3,6 +3,7 @@ #include "src/Rendering/Mesh/SkinnedMesh.h" #include "src/Resource/Resource.h" #include "src/Resource/Serializable.h" +#include "src/Resource/SkeletonNode.h" namespace Nuake @@ -12,11 +13,18 @@ namespace Nuake private: std::vector> m_Meshes; + SkeletonNode m_SkeletonRoot; + public: SkinnedModel(); SkinnedModel(const std::string path); ~SkinnedModel(); + void SetSkeletonRootNode(SkeletonNode& root) + { + m_SkeletonRoot = std::move(root); + } + void AddMesh(Ref mesh); std::vector>& GetMeshes(); diff --git a/Nuake/src/Scene/Scene.cpp b/Nuake/src/Scene/Scene.cpp index 2a8d575c..e65b6ff3 100644 --- a/Nuake/src/Scene/Scene.cpp +++ b/Nuake/src/Scene/Scene.cpp @@ -31,6 +31,7 @@ #include #include #include "src/Core/OS.h" +#include "Components/BoneComponent.h" namespace Nuake { @@ -213,7 +214,7 @@ namespace Nuake std::string Scene::GetUniqueEntityName(const std::string& name) { std::string entityName; - if (GetEntity(name) == Entity()) + if (!EntityExists(name)) { return name; } @@ -289,6 +290,11 @@ namespace Nuake m_Registry.shrink_to_fit(); } + bool Scene::EntityExists(const std::string& name) + { + return GetEntity(name).GetHandle() != -1; + } + Ref Scene::GetCurrentCamera() { if (Engine::IsPlayMode()) @@ -463,17 +469,31 @@ namespace Nuake SkinnedModelComponent& component = entity.GetComponent(); for (Ref& model : component.ModelResource->GetMeshes()) { - auto& bones = model->GetBones(); - if (bones.size() > 0) + for (auto& bone : model->GetBones()) { - for (auto& bone : bones) - { - auto& parentComponent = entity.GetComponent(); + auto& parentComponent = entity.GetComponent(); + Logger::Log("bone found:" + bone.Name, "debug", VERBOSE); + if (EntityExists(bone.Name) == false) + { Entity boneEntity = CreateEntity(bone.Name); + boneEntity.AddComponent(); + + Vector3 position; + Quat rotation; + Vector3 scale; + Decompose(bone.Offset, position, rotation, scale); + + auto& transformComponent = entity.GetComponent(); + transformComponent.SetLocalPosition(position); + transformComponent.SetLocalRotation(rotation); + transformComponent.SetLocalScale(scale); + transformComponent.SetLocalTransform(bone.Offset); + entity.AddChild(boneEntity); } } } } + } diff --git a/Nuake/src/Scene/Scene.h b/Nuake/src/Scene/Scene.h index 2d2cf74b..09a09128 100644 --- a/Nuake/src/Scene/Scene.h +++ b/Nuake/src/Scene/Scene.h @@ -65,6 +65,7 @@ namespace Nuake Entity CreateEntity(const std::string& name); Entity CreateEntity(const std::string& name, int id); void DestroyEntity(Entity entity); + bool EntityExists(const std::string& name); std::vector GetAllEntities(); Entity GetEntity(const std::string& name);