mirror of
https://github.com/antopilo/Nuake.git
synced 2026-09-09 20:08:57 +03:00
Now properly serialize and deserialize rigged models
This commit is contained in:
@@ -34,6 +34,27 @@ p = j[#p]; \
|
||||
#define DESERIALIZE_VEC2(v, p) \
|
||||
p = Vector2(v["x"], v["y"]);
|
||||
|
||||
#define SERIALIZE_MAT4(lbl, m) \
|
||||
{ \
|
||||
int i = 0; \
|
||||
for (int l = 0; l < 4; l++) { \
|
||||
for (int k = 0; k < 4; k++) { \
|
||||
j[lbl][i] = m[l][k]; \
|
||||
i++; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DESERIALIZE_MAT4(lbl, m) \
|
||||
{ \
|
||||
int i = 0; \
|
||||
for(int l = 0; l < 4; l++) { \
|
||||
for(int k = 0; k < 4; k++) { \
|
||||
m[l][k] = j[lbl][i];\
|
||||
i++; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SERIALIZE_OBJECT(v) j[#v] = v->Serialize();
|
||||
#define SERIALIZE_OBJECT_REF(v) j[#v] = v.Serialize();
|
||||
|
||||
@@ -11,6 +11,11 @@ namespace Nuake
|
||||
m_PositionTimestamps = std::vector<float>();
|
||||
m_RotationTimestamps = std::vector<float>();
|
||||
m_ScaleTimestamps = std::vector<float>();
|
||||
|
||||
m_PositionTransform = Matrix4(1.0f);
|
||||
m_RotationTransform = Matrix4(1.0f);
|
||||
m_ScaleTransform = Matrix4(1.0f);
|
||||
m_FinalTransform = Matrix4(1.0f);
|
||||
}
|
||||
|
||||
float BoneTransformTrack::GetScaleFactor(float lastTime, float nextTime, float animationTime)
|
||||
@@ -22,7 +27,7 @@ namespace Nuake
|
||||
return scaleFactor;
|
||||
}
|
||||
|
||||
Nuake::Matrix4 BoneTransformTrack::InterpolatePosition(float time)
|
||||
Matrix4 BoneTransformTrack::InterpolatePosition(float time)
|
||||
{
|
||||
if (m_Positions.size() == 0)
|
||||
{
|
||||
@@ -34,14 +39,20 @@ namespace Nuake
|
||||
return glm::translate(Matrix4(1.0f), m_Positions[0]);
|
||||
}
|
||||
|
||||
// This returns the last position when we are at the last keyframe
|
||||
int p0Index = GetPositionIndex(time);
|
||||
if (p0Index == m_Positions.size() - 1)
|
||||
{
|
||||
return glm::translate(Matrix4(1.0f), m_Positions[p0Index]);
|
||||
}
|
||||
|
||||
int p1Index = p0Index + 1;
|
||||
float scaleFactor = GetScaleFactor(m_PositionTimestamps[p0Index], m_PositionTimestamps[p1Index], time);
|
||||
glm::vec3 finalPosition = glm::mix(m_Positions[p0Index], m_Positions[p1Index], scaleFactor);
|
||||
Vector3 finalPosition = glm::mix(m_Positions[p0Index], m_Positions[p1Index], scaleFactor);
|
||||
return glm::translate(Matrix4(1.0f), finalPosition);
|
||||
}
|
||||
|
||||
Nuake::Matrix4 BoneTransformTrack::InterpolateRotation(float time)
|
||||
Matrix4 BoneTransformTrack::InterpolateRotation(float time)
|
||||
{
|
||||
if (m_Rotations.size() == 0)
|
||||
{
|
||||
@@ -54,17 +65,21 @@ namespace Nuake
|
||||
return glm::toMat4(rotation);
|
||||
}
|
||||
|
||||
// This returns the last rotation when we are at the last keyframe
|
||||
int p0Index = GetRotationIndex(time);
|
||||
if (p0Index == m_Rotations.size() - 1)
|
||||
{
|
||||
return glm::toMat4(m_Rotations[p0Index]);
|
||||
}
|
||||
|
||||
int p1Index = p0Index + 1;
|
||||
float scaleFactor = GetScaleFactor(m_RotationTimestamps[p0Index],
|
||||
m_RotationTimestamps[p1Index], time);
|
||||
glm::quat finalRotation = glm::slerp(m_Rotations[p0Index],
|
||||
m_Rotations[p1Index], scaleFactor);
|
||||
float scaleFactor = GetScaleFactor(m_RotationTimestamps[p0Index], m_RotationTimestamps[p1Index], time);
|
||||
Quat finalRotation = glm::slerp(m_Rotations[p0Index],m_Rotations[p1Index], scaleFactor);
|
||||
finalRotation = glm::normalize(finalRotation);
|
||||
return glm::toMat4(finalRotation);
|
||||
}
|
||||
|
||||
Nuake::Matrix4 BoneTransformTrack::InterpolateScale(float time)
|
||||
Matrix4 BoneTransformTrack::InterpolateScale(float time)
|
||||
{
|
||||
if (m_Scales.size() == 0)
|
||||
{
|
||||
@@ -72,14 +87,21 @@ namespace Nuake
|
||||
}
|
||||
|
||||
if (1 == m_Scales.size())
|
||||
{
|
||||
return glm::scale(glm::mat4(1.0f), m_Scales[0]);
|
||||
}
|
||||
|
||||
// This returns the last rotation when we are at the last keyframe
|
||||
int p0Index = GetScaleIndex(time);
|
||||
if (p0Index == m_Scales.size() - 1)
|
||||
{
|
||||
return glm::scale(Matrix4(1.0f), m_Scales[p0Index]);
|
||||
}
|
||||
|
||||
int p1Index = p0Index + 1;
|
||||
float scaleFactor = GetScaleFactor(m_ScaleTimestamps[p0Index],
|
||||
m_ScaleTimestamps[p1Index], time);
|
||||
glm::vec3 finalScale = glm::mix(m_Scales[p0Index], m_Scales[p1Index], scaleFactor);
|
||||
return glm::scale(glm::mat4(1.0f), finalScale);
|
||||
float scaleFactor = GetScaleFactor(m_ScaleTimestamps[p0Index], m_ScaleTimestamps[p1Index], time);
|
||||
Vector3 finalScale = glm::mix(m_Scales[p0Index], m_Scales[p1Index], scaleFactor);
|
||||
return glm::scale(Matrix4(1.0f), finalScale);
|
||||
}
|
||||
|
||||
json BoneTransformTrack::Serialize()
|
||||
|
||||
@@ -59,25 +59,11 @@ namespace Nuake
|
||||
m_Scales.push_back(scale);
|
||||
}
|
||||
|
||||
int GetPositionIndex(float animationTime)
|
||||
{
|
||||
if (m_Positions.size() == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int index = 0; index < m_Positions.size() - 1; index++)
|
||||
{
|
||||
if (animationTime < m_PositionTimestamps[index + 1])
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void Update(float time)
|
||||
{
|
||||
// We cannot use const reference here because we would compare the reference to previous pos
|
||||
// to the m_PositionTransform and previous pos always equale.
|
||||
// Making the hasChanged always false. We would end up comparing the same values always.
|
||||
const Matrix4 previousPos = m_PositionTransform;
|
||||
const Matrix4 previousRot = m_RotationTransform;
|
||||
const Matrix4 previousSca = m_ScaleTransform;
|
||||
@@ -97,6 +83,24 @@ namespace Nuake
|
||||
return m_FinalTransform;
|
||||
}
|
||||
|
||||
int GetPositionIndex(float animationTime)
|
||||
{
|
||||
if (m_Positions.size() == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int index = 0; index < m_Positions.size() - 1; index++)
|
||||
{
|
||||
if (animationTime < m_PositionTimestamps[index + 1])
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<int>(m_Positions.size()) - 1;
|
||||
}
|
||||
|
||||
/* Gets the current index on mKeyRotations to interpolate to based on the
|
||||
current animation time*/
|
||||
int GetRotationIndex(float animationTime)
|
||||
@@ -108,7 +112,8 @@ namespace Nuake
|
||||
return index;
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
|
||||
return static_cast<int>(m_Rotations.size()) - 1;
|
||||
}
|
||||
|
||||
/* Gets the current index on mKeyScalings to interpolate to based on the
|
||||
@@ -122,7 +127,8 @@ namespace Nuake
|
||||
return index;
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
|
||||
return static_cast<int>(m_Scales.size()) - 1;
|
||||
}
|
||||
|
||||
float GetScaleFactor(float lastTime, float nextTime, float animationTime);
|
||||
@@ -158,7 +164,7 @@ namespace Nuake
|
||||
}
|
||||
else
|
||||
{
|
||||
m_CurrentTime = time;
|
||||
m_CurrentTime = std::max(time, m_Duration);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Core/Maths.h"
|
||||
#include "src/Resource/Serializable.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
@@ -14,5 +15,47 @@ namespace Nuake
|
||||
Matrix4 FinalTransform = Matrix4(1.0f);
|
||||
int32_t Id = -1;
|
||||
int32_t EntityHandle = 0;
|
||||
|
||||
json Serialize()
|
||||
{
|
||||
BEGIN_SERIALIZE();
|
||||
SERIALIZE_MAT4("Transform", Transform);
|
||||
SERIALIZE_MAT4("Offset", Offset);
|
||||
SERIALIZE_VAL(Name);
|
||||
SERIALIZE_VAL(ChildrenCount);
|
||||
SERIALIZE_VAL(Id);
|
||||
SERIALIZE_VAL(EntityHandle);
|
||||
|
||||
uint32_t i = 0;
|
||||
for (auto& c : Children)
|
||||
{
|
||||
j["Children"][i] = c.Serialize();
|
||||
i++;
|
||||
}
|
||||
|
||||
END_SERIALIZE();
|
||||
}
|
||||
|
||||
bool Deserialize(json j)
|
||||
{
|
||||
DESERIALIZE_MAT4("Transform", Transform);
|
||||
DESERIALIZE_MAT4("Offset", Offset);
|
||||
DESERIALIZE_VAL(Name);
|
||||
DESERIALIZE_VAL(ChildrenCount);
|
||||
DESERIALIZE_VAL(Id);
|
||||
DESERIALIZE_VAL(EntityHandle);
|
||||
|
||||
if (j.contains("Children"))
|
||||
{
|
||||
for (uint32_t i = 0; i < ChildrenCount; i++)
|
||||
{
|
||||
SkeletonNode newChildren;
|
||||
newChildren.Deserialize(j["Children"][i]);
|
||||
Children.push_back(std::move(newChildren));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -71,6 +71,7 @@ namespace Nuake
|
||||
if (this->Path != "")
|
||||
{
|
||||
j["Path"] = this->Path;
|
||||
j["SkeletonNode"] = m_SkeletonRoot.Serialize();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -86,10 +87,9 @@ namespace Nuake
|
||||
for (auto& animation : m_Animations)
|
||||
{
|
||||
j["m_Animations"][a] = animation->Serialize();
|
||||
a++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
END_SERIALIZE();
|
||||
}
|
||||
@@ -108,6 +108,13 @@ namespace Nuake
|
||||
m_NumAnimation = m_Animations.size();
|
||||
m_CurrentAnimation = 0;
|
||||
|
||||
if (j.contains("SkeletonNode"))
|
||||
{
|
||||
SkeletonNode skeletonNode;
|
||||
skeletonNode.Deserialize(j["SkeletonNode"]);
|
||||
m_SkeletonRoot = std::move(skeletonNode);
|
||||
}
|
||||
|
||||
this->Path = j["Path"];
|
||||
}
|
||||
else
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace Nuake
|
||||
bool Deserialize(const json& j)
|
||||
{
|
||||
ModelPath = j["ModelPath"];
|
||||
|
||||
ModelResource = CreateRef<SkinnedModel>();
|
||||
|
||||
if (j.contains("ModelResource"))
|
||||
|
||||
@@ -47,17 +47,18 @@ namespace Nuake
|
||||
{
|
||||
const std::string& boneName = bone.Name;
|
||||
|
||||
auto& animationTrack = animation->GetTrack(boneName);
|
||||
auto animationTrack = animation->GetTrack(boneName);
|
||||
|
||||
Entity& boneEntity = m_Scene->GetEntity(boneName);
|
||||
Entity& boneEnt = m_Scene->GetEntityByID(bone.EntityHandle);
|
||||
///assert(boneEnt.GetHandle() == boneEntity.GetHandle());
|
||||
|
||||
if (boneEnt.IsValid())
|
||||
{
|
||||
auto& transformComponent = boneEnt.GetComponent<TransformComponent>();
|
||||
bone.FinalTransform = transformComponent.GetGlobalTransform() * bone.Offset;
|
||||
|
||||
//if (!animationTrack.IsEmpty())
|
||||
if (!animationTrack.IsEmpty())
|
||||
{
|
||||
// Get Update transform
|
||||
animationTrack.Update(time);
|
||||
@@ -76,7 +77,12 @@ namespace Nuake
|
||||
transformComponent.Dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// Find bone
|
||||
|
||||
}
|
||||
|
||||
for (auto& childBone : bone.Children)
|
||||
{
|
||||
UpdateBonePositionTraversal(childBone, animation, time);
|
||||
|
||||
Reference in New Issue
Block a user