Added support for edge cases in transforms interpolation for animation clips
This commit is contained in:
parent
e9624977cd
commit
5c14a0829a
|
@ -3,7 +3,8 @@
|
||||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
\par email: kahwei.tng\@digipen.edu
|
\par email: kahwei.tng\@digipen.edu
|
||||||
\date Nov 20, 2022
|
\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.
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
@ -145,65 +146,11 @@ namespace SHADE
|
||||||
(
|
(
|
||||||
getInterpolatedValue(channel.PositionKeyFrames, CLOSEST_FRAME_IDX, poseTime),
|
getInterpolatedValue(channel.PositionKeyFrames, CLOSEST_FRAME_IDX, poseTime),
|
||||||
getInterpolatedValue(channel.RotationKeyFrames, CLOSEST_FRAME_IDX, poseTime),
|
getInterpolatedValue(channel.RotationKeyFrames, CLOSEST_FRAME_IDX, poseTime),
|
||||||
getInterpolatedValue(channel.ScaleKeyFrames, CLOSEST_FRAME_IDX, poseTime)
|
getInterpolatedValue(channel.ScaleKeyFrames , CLOSEST_FRAME_IDX, poseTime)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
\par email: kahwei.tng\@digipen.edu
|
\par email: kahwei.tng\@digipen.edu
|
||||||
\date Nov 20, 2022
|
\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.
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
@ -131,8 +132,8 @@ namespace SHADE
|
||||||
/* Helper Functions */
|
/* Helper Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
void updatePoseWithClip(float poseTime);
|
void updatePoseWithClip(float poseTime);
|
||||||
SHVec3 getInterpolatedValue(const std::vector<SHAnimationKeyFrame<SHVec3>>& keyframes, int closestFrameIndex, float poseTime);
|
template<typename T>
|
||||||
SHQuaternion getInterpolatedValue(const std::vector<SHAnimationKeyFrame<SHQuaternion>>& keyframes, int closestFrameIndex, float poseTime);
|
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime);
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* RTTR */
|
/* RTTR */
|
||||||
|
@ -140,3 +141,5 @@ namespace SHADE
|
||||||
RTTR_ENABLE()
|
RTTR_ENABLE()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "SHAnimatorComponent.hpp"
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue