Animation serialization progress

This commit is contained in:
Antoine Pilote
2023-09-06 20:05:10 -04:00
parent 10c92feaa3
commit 1628214370
10 changed files with 170 additions and 26 deletions

View File

@@ -119,8 +119,9 @@ public:
ImGui::TableNextColumn();
}
if(model->GetCurrentAnimation())
{
ImGui::Text("Type");
ImGui::Text("Animation");
ImGui::TableNextColumn();
uint32_t animIndex = model->GetCurrentAnimationIndex();
@@ -131,7 +132,14 @@ public:
for (int n = 0; n < model->GetAnimationsCount(); n++)
{
bool is_selected = (animIndex == n);
if (ImGui::Selectable(animations[n]->GetName().c_str(), is_selected))
std::string animName = animations[n]->GetName();
if (animName.empty())
{
animName = "Empty";
}
if (ImGui::Selectable(animName.c_str(), is_selected))
{
animIndex = n;
}

View File

@@ -145,6 +145,12 @@ namespace Nuake
v["Bitangent"]["y"] = m_Vertices[i].bitangent.y;
v["Bitangent"]["z"] = m_Vertices[i].bitangent.z;
for (uint32_t b = 0; b < MAX_BONE_INFLUENCE; b++)
{
v["Weight"][b] = m_Vertices[i].weights[b];
v["BoneIDs"][b] = m_Vertices[i].boneIDs[b];
}
j["Vertices"][i] = v;
}
@@ -177,10 +183,17 @@ namespace Nuake
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);
DESERIALIZE_VEC3(v["Normal"], vertex.normal)
DESERIALIZE_VEC3(v["Tangent"], vertex.tangent)
DESERIALIZE_VEC3(v["Bitangent"], vertex.bitangent)
for (uint32_t i = 0; i < MAX_BONE_INFLUENCE; i++)
{
vertex.weights[i] = v["Weight"][i];
vertex.boneIDs[i] = v["boneIDs"][i];
}
vertices.push_back(vertex);
}
}
);
@@ -190,9 +203,4 @@ namespace Nuake
SetupMesh();
return true;
}
void SkinnedMesh::SetSkeletalAnimation(Ref<SkeletalAnimation> skeletalAnimation)
{
m_SkeletalAnimation = skeletalAnimation;
}
}

View File

@@ -26,7 +26,6 @@ namespace Nuake
void AddSurface(std::vector<SkinnedVertex> vertices, std::vector<uint32_t> indices, std::vector<Bone> bones);
std::vector<SkinnedVertex>& GetVertices();
std::vector<uint32_t>& GetIndices();
std::vector<Bone>& GetBones();
Ref<Material> GetMaterial() inline const;
void SetMaterial(Ref<Material> material);
@@ -40,12 +39,7 @@ namespace Nuake
json Serialize() override;
bool Deserialize(const json& j) override;
void SetSkeletalAnimation(Ref<SkeletalAnimation> animation);
Ref<SkeletalAnimation> GetSkeletalAnimation() const { return m_SkeletalAnimation; }
private:
Ref<SkeletalAnimation> m_SkeletalAnimation;
Ref<Material> m_Material = nullptr;
std::vector<uint32_t> m_Indices;
std::vector<SkinnedVertex> m_Vertices;

View File

@@ -67,7 +67,8 @@ namespace Nuake
aiProcess_Triangulate |
aiProcess_GenSmoothNormals |
aiProcess_FixInfacingNormals |
aiProcess_CalcTangentSpace;
aiProcess_CalcTangentSpace |
aiProcess_OptimizeGraph;
modelDir = absolute ? path + "/../" : FileSystem::Root + path + "/../";
const std::string filePath = absolute ? path : FileSystem::Root + path;

View File

@@ -82,6 +82,47 @@ namespace Nuake
return glm::scale(glm::mat4(1.0f), finalScale);
}
json BoneTransformTrack::Serialize()
{
BEGIN_SERIALIZE();
for (uint32_t i = 0; i < m_PositionTimestamps.size(); i++)
{
j["m_PositionTimestamps"][i] = m_PositionTimestamps[i];
}
for (uint32_t i = 0; i < m_Positions.size(); i++)
{
j["m_Positions"][i] = SERIALIZE_VEC3(m_Positions[i]);
}
for (uint32_t i = 0; i < m_RotationTimestamps.size(); i++)
{
j["m_RotationTimestamps"][i] = m_RotationTimestamps[i];
}
for (uint32_t i = 0; i < m_Rotations.size(); i++)
{
j["m_Rotations"][i] = SERIALIZE_VEC4(m_Rotations[i]);
}
for (uint32_t i = 0; i < m_ScaleTimestamps.size(); i++)
{
j["m_ScaleTimestamps"][i] = m_ScaleTimestamps[i];
}
for (uint32_t i = 0; i < m_Scales.size(); i++)
{
j["m_Scales"][i] = SERIALIZE_VEC3(m_Scales[i]);
}
END_SERIALIZE();
}
bool BoneTransformTrack::Deserialize(const json& j)
{
return true;
}
SkeletalAnimation::SkeletalAnimation(const std::string& name, float duration, float ticksPerSecond)
{
m_Name = name;
@@ -101,4 +142,39 @@ namespace Nuake
m_Tracks[name] = BoneTransformTrack();
return m_Tracks[name];
}
json SkeletalAnimation::Serialize()
{
BEGIN_SERIALIZE();
SERIALIZE_VAL(m_Name);
SERIALIZE_VAL(m_Duration);
SERIALIZE_VAL(m_TicksPerSecond);
SERIALIZE_VAL(m_CurrentTime);
SERIALIZE_VAL(m_Loop);
for (auto& t : m_Tracks)
{
j["Tracks"][t.first] = t.second.Serialize();
}
return json();
}
bool SkeletalAnimation::Deserialize(const json& j)
{
m_Name = j["m_Name"];
m_Duration = j["m_Duration"];
m_TicksPerSecond = j["m_TicksPerSecond"];
m_CurrentTime = j["m_CurrentTime"];
m_Loop = j["m_Loop"];
for (auto& [trackName, trackData]: j["Tracks"].items())
{
BoneTransformTrack track;
track.Deserialize(j["Tracks"][trackName]);
m_Tracks[trackName] = std::move(track);
}
return true;
}
}

View File

@@ -2,6 +2,9 @@
#include "src/Core/Core.h"
#include <src/Rendering/Mesh/Bone.h>
#include "src/Resource/Serializable.h"
#include "src/Resource/Resource.h"
namespace Nuake
{
struct SkeletonAnimationBoneAnimation
@@ -94,9 +97,12 @@ namespace Nuake
Matrix4 InterpolatePosition(float time);
Matrix4 InterpolateRotation(float time);
Matrix4 InterpolateScale(float time);
json Serialize();
bool Deserialize(const json& j);
};
class SkeletalAnimation
class SkeletalAnimation : public Resource, ISerializable
{
private:
std::unordered_map<std::string, BoneTransformTrack> m_Tracks;
@@ -104,7 +110,7 @@ namespace Nuake
float m_Duration;
float m_TicksPerSecond;
std::string m_Name;
bool m_Loop;
bool m_Loop = false;
public:
SkeletalAnimation() = default;
@@ -114,7 +120,14 @@ namespace Nuake
void SetCurrentTime(float time)
{
m_CurrentTime = fmod(time, m_Duration);
if (m_Loop)
{
m_CurrentTime = fmod(time, m_Duration);
}
else
{
m_CurrentTime = time;
}
}
float GetCurrentTime() const { return m_CurrentTime; }
@@ -126,5 +139,8 @@ namespace Nuake
const std::string& GetName() const { return m_Name; }
BoneTransformTrack& GetTrack(const std::string& name);
std::unordered_map<std::string, BoneTransformTrack>& GetTracks() { return m_Tracks; }
json Serialize() override;
bool Deserialize(const json& j) override;
};
}

View File

@@ -78,7 +78,19 @@ namespace Nuake
{
j["Meshes"][i] = m_Meshes[i]->Serialize();
}
j["m_CurrentAnimation"] = m_CurrentAnimation;
j["m_NumAnimation"] = m_NumAnimation;
uint32_t a = 0;
for (auto& animation : m_Animations)
{
j["m_Animations"][a] = animation->Serialize();
}
}
END_SERIALIZE();
}
@@ -91,6 +103,10 @@ namespace Nuake
ModelLoader loader;
auto otherModel = loader.LoadSkinnedModel(j["Path"], false);
m_Meshes = otherModel->GetMeshes();
m_Animations = otherModel->GetAnimations();
m_SkeletonRoot = otherModel->GetSkeletonRootNode();
m_NumAnimation = m_Animations.size();
m_CurrentAnimation = 0;
this->Path = j["Path"];
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "src/Core/Core.h"
#include "src/Resource/Serializable.h"
namespace Nuake
@@ -11,5 +12,19 @@ namespace Nuake
~BoneComponent() = default;
std::string Name;
json Serialize()
{
BEGIN_SERIALIZE();
SERIALIZE_VAL(Name);
END_SERIALIZE();
}
bool Deserialize(const json& j)
{
Name = j["Name"];
return true;
}
};
}

View File

@@ -16,6 +16,8 @@
#include "src/Scene/Components/CapsuleColliderComponent.h"
#include "src/Scene/Components/SpriteComponent.h"
#include "src/Scene/Components/ParticleEmitterComponent.h"
#include "src/Scene/Components/BoneComponent.h"
#include "src/Scene/Components/SkinnedModelComponent.h"
namespace Nuake
{
@@ -69,7 +71,10 @@ namespace Nuake
SERIALIZE_OBJECT_REF_LBL("QuakeMapComponent", GetComponent<QuakeMapComponent>())
if (HasComponent<RigidBodyComponent>())
SERIALIZE_OBJECT_REF_LBL("RigidBodyComponent", GetComponent<RigidBodyComponent>())
if (HasComponent<SkinnedModelComponent>())
SERIALIZE_OBJECT_REF_LBL("SkinnedModelComponent", GetComponent<SkinnedModelComponent>())
if (HasComponent<BoneComponent>())
SERIALIZE_OBJECT_REF_LBL("BoneComponent", GetComponent<BoneComponent>())
END_SERIALIZE();
}
@@ -98,6 +103,8 @@ namespace Nuake
DESERIALIZE_COMPONENT(SphereColliderComponent)
DESERIALIZE_COMPONENT(RigidBodyComponent)
DESERIALIZE_COMPONENT(BSPBrushComponent)
DESERIALIZE_COMPONENT(BoneComponent)
DESERIALIZE_COMPONENT(SkinnedModelComponent)
return true;
}

View File

@@ -30,11 +30,14 @@ namespace Nuake
}
Ref<SkeletalAnimation> animation = model->GetCurrentAnimation();
float newAnimationTime = animation->GetCurrentTime() + (ts * animation->GetTicksPerSecond());
animation->SetCurrentTime(newAnimationTime);
if (animation && model->IsPlaying)
{
float newAnimationTime = animation->GetCurrentTime() + (ts * animation->GetTicksPerSecond());
animation->SetCurrentTime(newAnimationTime);
auto& rootBone = model->GetSkeletonRootNode();
UpdateBonePositionTraversal(rootBone, animation, animation->GetCurrentTime());
auto& rootBone = model->GetSkeletonRootNode();
UpdateBonePositionTraversal(rootBone, animation, animation->GetCurrentTime());
}
}
}