Modified SHAnimationComponent to handle interpolation of separate position, rotation and scale keyframes
This commit is contained in:
parent
7bf0c26052
commit
e9624977cd
|
@ -20,8 +20,8 @@ namespace SHADE
|
||||||
/* Constructors */
|
/* Constructors */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
SHAnimationClip::SHAnimationClip(const SHAnimAsset& asset)
|
SHAnimationClip::SHAnimationClip(const SHAnimAsset& asset)
|
||||||
: ticksPerSecond { asset.ticksPerSecond }
|
: ticksPerSecond { static_cast<int>(asset.ticksPerSecond) }
|
||||||
, totalTime { asset.duration }
|
, totalTime { static_cast<float>(asset.duration) }
|
||||||
{
|
{
|
||||||
// Populate keyframes
|
// Populate keyframes
|
||||||
for (const auto& channel : asset.nodeChannels)
|
for (const auto& channel : asset.nodeChannels)
|
||||||
|
@ -47,6 +47,8 @@ namespace SHADE
|
||||||
newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ static_cast<int>(scaleKey.time), scaleKey.value});
|
newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ static_cast<int>(scaleKey.time), scaleKey.value});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newChannel.MaxFrames = std::max({ newChannel.PositionKeyFrames.size(), newChannel.RotationKeyFrames.size(), newChannel.ScaleKeyFrames.size() });
|
||||||
|
|
||||||
// Insert the channel
|
// Insert the channel
|
||||||
channels.emplace_back(std::move(newChannel));
|
channels.emplace_back(std::move(newChannel));
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ namespace SHADE
|
||||||
std::vector<SHAnimationKeyFrame<SHVec3>> PositionKeyFrames;
|
std::vector<SHAnimationKeyFrame<SHVec3>> PositionKeyFrames;
|
||||||
std::vector<SHAnimationKeyFrame<SHQuaternion>> RotationKeyFrames;
|
std::vector<SHAnimationKeyFrame<SHQuaternion>> RotationKeyFrames;
|
||||||
std::vector<SHAnimationKeyFrame<SHVec3>> ScaleKeyFrames;
|
std::vector<SHAnimationKeyFrame<SHVec3>> ScaleKeyFrames;
|
||||||
|
int MaxFrames;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -83,6 +83,7 @@ namespace SHADE
|
||||||
return;
|
return;
|
||||||
|
|
||||||
currClip = newClip;
|
currClip = newClip;
|
||||||
|
secsPerTick = 1.0f / currClip->GetTicksPerSecond();
|
||||||
updatePoseWithClip(0.0f);
|
updatePoseWithClip(0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,36 +136,74 @@ namespace SHADE
|
||||||
bones.push(child);
|
bones.push(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get interpolated frame
|
// Get closest frame index
|
||||||
auto firstKeyFrame = channel.KeyFrames.end();
|
const int CLOSEST_FRAME_IDX = static_cast<int>(std::floorf(poseTime * currClip->GetTicksPerSecond()));
|
||||||
auto nextKeyFrame = channel.KeyFrames.end();
|
|
||||||
for (auto iter = channel.KeyFrames.begin(); iter != channel.KeyFrames.end(); ++iter)
|
|
||||||
{
|
|
||||||
const auto& KEYFRAME = *iter;
|
|
||||||
|
|
||||||
if(KEYFRAME.TimeStamp <= poseTime)
|
// Calculate the matrix from interpolated values
|
||||||
{
|
|
||||||
firstKeyFrame = iter;
|
|
||||||
}
|
|
||||||
else if (KEYFRAME.TimeStamp > poseTime)
|
|
||||||
{
|
|
||||||
nextKeyFrame = iter;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Calculate the matrix
|
|
||||||
const int BONE_MTX_IDX = rig->GetNodeIndex(bone);
|
const int BONE_MTX_IDX = rig->GetNodeIndex(bone);
|
||||||
const float T = (poseTime - firstKeyFrame->TimeStamp) / (nextKeyFrame->TimeStamp - firstKeyFrame->TimeStamp);
|
|
||||||
boneMatrices[BONE_MTX_IDX] = boneMatrices[BONE_MTX_IDX] * SHMatrix::Transform
|
boneMatrices[BONE_MTX_IDX] = boneMatrices[BONE_MTX_IDX] * SHMatrix::Transform
|
||||||
(
|
(
|
||||||
SHVec3::Lerp(firstKeyFrame->Position, nextKeyFrame->Position, T),
|
getInterpolatedValue(channel.PositionKeyFrames, CLOSEST_FRAME_IDX, poseTime),
|
||||||
SHQuaternion::Slerp(firstKeyFrame->Orientation, nextKeyFrame->Orientation, T),
|
getInterpolatedValue(channel.RotationKeyFrames, CLOSEST_FRAME_IDX, poseTime),
|
||||||
SHVec3::Lerp(firstKeyFrame->Scale, nextKeyFrame->Scale, T)
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -19,6 +19,9 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "ECS_Base/Components/SHComponent.h"
|
#include "ECS_Base/Components/SHComponent.h"
|
||||||
#include "Resource/SHHandle.h"
|
#include "Resource/SHHandle.h"
|
||||||
#include "Math/SHMatrix.h"
|
#include "Math/SHMatrix.h"
|
||||||
|
#include "Math/Vector/SHVec3.h"
|
||||||
|
#include "Math/SHQuaternion.h"
|
||||||
|
#include "SHAnimationClip.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -119,6 +122,8 @@ namespace SHADE
|
||||||
// Playback Tracking
|
// Playback Tracking
|
||||||
float currPlaybackTime = 0.0f;
|
float currPlaybackTime = 0.0f;
|
||||||
bool isPlaying = false;
|
bool isPlaying = false;
|
||||||
|
// Useful Cached Data
|
||||||
|
float secsPerTick = 0.0f;
|
||||||
// Buffer
|
// Buffer
|
||||||
std::vector<SHMatrix> boneMatrices;
|
std::vector<SHMatrix> boneMatrices;
|
||||||
|
|
||||||
|
@ -126,6 +131,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);
|
||||||
|
SHQuaternion getInterpolatedValue(const std::vector<SHAnimationKeyFrame<SHQuaternion>>& keyframes, int closestFrameIndex, float poseTime);
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* RTTR */
|
/* RTTR */
|
||||||
|
|
Loading…
Reference in New Issue