Added support for edge cases in transforms interpolation for animation clips

This commit is contained in:
Kah Wei 2023-01-10 11:46:37 +08:00
parent e9624977cd
commit 5c14a0829a
3 changed files with 92 additions and 60 deletions

View File

@ -3,7 +3,8 @@
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Nov 20, 2022
\brief Contains the definition of functions of the SHRenderable Component class.
\brief Contains the definition of functions of the SHAnimatorComponent Component
class.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
@ -150,60 +151,6 @@ namespace SHADE
}
}
}
SHVec3 SHAnimatorComponent::getInterpolatedValue(const std::vector<SHAnimationKeyFrame<SHVec3>>& keyframes, int closestFrameIndex, float poseTime)
{
// Find the key frames that surround the current frame index
auto firstKeyFrame = keyframes.end();
auto nextKeyFrame = keyframes.end();
for (auto iter = keyframes.begin(); iter != keyframes.end(); ++iter)
{
const auto& KEYFRAME = *iter;
if (KEYFRAME.FrameIndex <= closestFrameIndex)
{
firstKeyFrame = iter;
}
else if (KEYFRAME.FrameIndex > closestFrameIndex)
{
nextKeyFrame = iter;
break;
}
}
// Get interpolated vector
const float PREV_FRAME_TIME = firstKeyFrame->FrameIndex * secsPerTick;
const float NEXT_FRAME_TIME = nextKeyFrame->FrameIndex * secsPerTick;
const float T = (poseTime - PREV_FRAME_TIME) / (NEXT_FRAME_TIME - PREV_FRAME_TIME);
return SHVec3::Lerp(firstKeyFrame->Data, nextKeyFrame->Data, T);
}
SHQuaternion SHAnimatorComponent::getInterpolatedValue(const std::vector<SHAnimationKeyFrame<SHQuaternion>>& keyframes, int closestFrameIndex, float poseTime)
{
// Find the key frames that surround the current frame index
auto firstKeyFrame = keyframes.end();
auto nextKeyFrame = keyframes.end();
for (auto iter = keyframes.begin(); iter != keyframes.end(); ++iter)
{
const auto& KEYFRAME = *iter;
if (KEYFRAME.FrameIndex <= closestFrameIndex)
{
firstKeyFrame = iter;
}
else if (KEYFRAME.FrameIndex > closestFrameIndex)
{
nextKeyFrame = iter;
break;
}
}
// Get interpolated vector
const float PREV_FRAME_TIME = firstKeyFrame->FrameIndex * secsPerTick;
const float NEXT_FRAME_TIME = nextKeyFrame->FrameIndex * secsPerTick;
const float T = (poseTime - PREV_FRAME_TIME) / (NEXT_FRAME_TIME - PREV_FRAME_TIME);
return SHQuaternion::Slerp(firstKeyFrame->Data, nextKeyFrame->Data, T);
}
}
/*-------------------------------------------------------------------------------------*/

View File

@ -3,7 +3,8 @@
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Nov 20, 2022
\brief Contains the definition of the SHAnimationSystem class and related types.
\brief Contains the definition of the SHAnimatorComponent class and related
types.
Copyright (C) 2022 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
@ -131,8 +132,8 @@ namespace SHADE
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
void updatePoseWithClip(float poseTime);
SHVec3 getInterpolatedValue(const std::vector<SHAnimationKeyFrame<SHVec3>>& keyframes, int closestFrameIndex, float poseTime);
SHQuaternion getInterpolatedValue(const std::vector<SHAnimationKeyFrame<SHQuaternion>>& keyframes, int closestFrameIndex, float poseTime);
template<typename T>
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime);
/*---------------------------------------------------------------------------------*/
/* RTTR */
@ -140,3 +141,5 @@ namespace SHADE
RTTR_ENABLE()
};
}
#include "SHAnimatorComponent.hpp"

View File

@ -0,0 +1,82 @@
/************************************************************************************//*!
\file SHAnimatorComponent.hpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Jan 10, 2023
\brief Contains the definition of function templates of the SHAnimatorComponent
Component class.
Copyright (C) 2023 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/
// Primary Include
#include "SHAnimatorComponent.h"
// Project Includes
#include "SHRig.h"
#include "Math/SHMatrix.h"
#include "SHAnimationClip.h"
#include "Graphics/SHVkUtil.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "ECS_Base/Managers/SHSystemManager.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------------*/
template<typename T>
T SHAnimatorComponent::getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime)
{
// Only allow SHVec3 and SHQuaternion
static_assert(std::is_same_v<T, SHVec3> || std::is_same_v<T, SHQuaternion>, "Only interpolation for SHVec3 and SHQuaternion is allowed.");
// Find the key frames that surround the current frame index
auto firstKeyFrame = keyframes.end();
auto nextKeyFrame = keyframes.end();
for (auto iter = keyframes.begin(); iter != keyframes.end(); ++iter)
{
const auto& KEYFRAME = *iter;
if (KEYFRAME.FrameIndex <= closestFrameIndex)
{
firstKeyFrame = iter;
}
else if (KEYFRAME.FrameIndex > closestFrameIndex)
{
nextKeyFrame = iter;
break;
}
}
// Edge Cases
if (firstKeyFrame == keyframes.end())
{
// No keyframes at all, means no changes
if (nextKeyFrame == keyframes.end())
return T();
// At the back, so no keyframes will follow
else
return firstKeyFrame->Data;
}
// At the front, so no prior key frames
else if (nextKeyFrame != keyframes.end())
{
return nextKeyFrame->Data;
}
// Get interpolated vector
const float PREV_FRAME_TIME = firstKeyFrame->FrameIndex * secsPerTick;
const float NEXT_FRAME_TIME = nextKeyFrame->FrameIndex * secsPerTick;
const float NORMALISED_TIME = (poseTime - PREV_FRAME_TIME) / (NEXT_FRAME_TIME - PREV_FRAME_TIME);
if constexpr (std::is_same_v<T, SHQuaternion>)
{
return SHQuaternion::Slerp(firstKeyFrame->Data, nextKeyFrame->Data, NORMALISED_TIME);
}
else if constexpr (std::is_same_v<T, SHVec3>)
{
return SHVec3::Lerp(firstKeyFrame->Data, nextKeyFrame->Data, NORMALISED_TIME);
}
}
}