1#include "AnimatorComponent.h"
2#include "../../Object/SGameObjectFromSPrefab.h"
11AnimatorComponent::~AnimatorComponent() =
default;
13void AnimatorComponent::Init() {
17void AnimatorComponent::Tick(
float elapsedTime) {
18 if (m_currentAnimation ==
nullptr)
return;
20 if (m_startTime == 0) {
21 m_startTime = elapsedTime;
23 UpdateAnimationTime(elapsedTime);
25 std::vector<mat4> currentPose = calculateCurrentAnimationPose();
26 applyPoseToJoints(currentPose, m_rootJoint, mat4::Identity());
31void AnimatorComponent::Exterminate() {
42void AnimatorComponent::PlayAnimation(
Animation* animation) {
43 m_currentAnimation = animation;
44 m_animationTime = m_startTime = 0;
47void AnimatorComponent::UpdateAnimationTime(
float elapsedTime) {
48 m_animationTime += (elapsedTime - m_startTime) / 1000.f;
49 float length = m_currentAnimation->GetLength();
51 if (m_animationTime > length) {
52 m_animationTime -= (m_animationTime / length) * length;
55 m_startTime = elapsedTime;
59std::vector<mat4> AnimatorComponent::calculateCurrentAnimationPose()
const {
60 std::vector<KeyFrame*> frames = getPreviousAndNextFrames();
61 const float progression = CalculateProgression(frames[0], frames[1]);
62 return InterpolatePoses(frames[0], frames[1], progression);
65void AnimatorComponent::applyPoseToJoints(std::vector<mat4>& currentPose,
JointComponent* joint,
66 const mat4& parentTransform) {
67 const auto&
object = joint->GetGameObject();
68 const int jointId = joint->GetAnimationJointId();
69 const mat4& currentLocalTransform = currentPose[jointId];
70 mat4&& currentTransform = currentLocalTransform * parentTransform;
71 auto children =
object->GetChildren();
72 for (
const auto& child : children) {
73 const auto& joint_component = child->GetComponent<
JointComponent>();
74 if (joint_component !=
nullptr)
75 applyPoseToJoints(currentPose, joint_component, currentTransform);
77 currentTransform = joint->GetInverseTransformMatrix() * currentTransform;
78 joint->SetAnimationMatrix(std::move(currentTransform));
81std::vector<KeyFrame*> AnimatorComponent::getPreviousAndNextFrames()
const {
82 auto allFrames = m_currentAnimation->GetKeyFrames();
83 KeyFrame* previousFrame = allFrames.front();
84 KeyFrame* nextFrame = allFrames.front();
87 for (
auto it = std::next(allFrames.begin()); it != allFrames.end(); ++it) {
89 if (nextFrame->GetTimeStamp() > m_animationTime) {
92 previousFrame = nextFrame;
95 std::vector<KeyFrame*> result;
97 result.push_back(previousFrame);
98 result.push_back(nextFrame);
102float AnimatorComponent::CalculateProgression(
KeyFrame* previous,
KeyFrame* next)
const {
103 float totalTime = next->GetTimeStamp() - previous->GetTimeStamp();
104 float currentTime = m_animationTime - previous->GetTimeStamp();
105 return currentTime / totalTime;
108std::vector<mat4> AnimatorComponent::InterpolatePoses(
KeyFrame* previousFrame,
KeyFrame* nextFrame,
float t) {
109 const auto& jointKeyFrames_prev = previousFrame->GetJointKeyFrames();
110 const auto& jointKeyFrames_next = nextFrame->GetJointKeyFrames();
111 const auto jointSize = jointKeyFrames_prev.size();
112 std::vector<mat4> currentPose;
113 currentPose.reserve(jointSize);
115 for (
unsigned short i = 0; i < jointSize; ++i) {
116 const auto& prevTransform = jointKeyFrames_prev[i];
117 const auto& nextTransform = jointKeyFrames_next[i];
118 JointTransform&& currentTransform = JointTransform::Interpolate(t, *prevTransform, *nextTransform);
119 currentPose.emplace_back(std::move(currentTransform).GetLocalMatrix());
127 clone->m_animationTime = m_animationTime;
128 clone->m_startTime = m_startTime;
129 clone->m_currentAnimation = m_currentAnimation;
134void AnimatorComponent::CopyReference(
SComponent* src, std::map<SGameObject*, SGameObject*> lists_obj,
135 std::map<SComponent*, SComponent*> lists_comp) {
136 if (src ==
nullptr)
return;
144void AnimatorComponent::SetValue(std::string name_str, Arguments value) {
145 if (name_str ==
"m_animationTime") {
146 m_animationTime = std::stof(value[0]);
147 }
else if (name_str ==
"m_startTime") {
148 m_startTime = std::stof(value[0]);
149 }
else if (name_str ==
"m_currentAnimation") {
150 m_currentAnimation = SResource::Create<Animation>(value[0]);
151 }
else if (name_str ==
"m_rootJoint") {
156std::string AnimatorComponent::PrintValue()
const {
158 PRINT_START(
"component");
160 PRINT_VALUE(m_animationTime, m_animationTime);
161 PRINT_VALUE(m_startTime, m_startTime);
162 PRINT_VALUE(m_currentAnimation, ConvertSpaceStr(m_currentAnimation->GetHash()));
163 PRINT_VALUE_SPREFAB_REF(m_rootJoint);
166 PRINT_END(
"component");