Modified SHAnimationClip and SHAnimatorComponent to use frame timestamps instead of indices

This commit is contained in:
Kah Wei 2023-03-06 18:59:04 +08:00
parent f861304f5e
commit 43fd04dd5e
6 changed files with 19 additions and 21 deletions

View File

@ -36,15 +36,15 @@ namespace SHADE
// Populate Keyframes
for (const auto& posKey : channel.positionKeys)
{
newChannel.PositionKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ static_cast<int>(posKey.time), posKey.value});
newChannel.PositionKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ posKey.time, posKey.value});
}
for (const auto& rotKey : channel.rotationKeys)
{
newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame<SHQuaternion>{ static_cast<int>(rotKey.time), rotKey.value});
newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame<SHQuaternion>{ rotKey.time, rotKey.value});
}
for (const auto& scaleKey : channel.scaleKeys)
{
newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ static_cast<int>(scaleKey.time), scaleKey.value});
newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ scaleKey.time, scaleKey.value });
}
newChannel.MaxFrames = std::max({ newChannel.PositionKeyFrames.size(), newChannel.RotationKeyFrames.size(), newChannel.ScaleKeyFrames.size() });

View File

@ -27,7 +27,7 @@ namespace SHADE
template<typename T>
struct SHAnimationKeyFrame
{
int FrameIndex;
float TimeStamp;
T Data;
};

View File

@ -124,12 +124,10 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
void SHAnimatorComponent::updatePoseWithClip(float poseTime)
{
// Get closest frame index
const int CLOSEST_FRAME_IDX = static_cast<int>(std::floorf(poseTime * currClip->GetTicksPerSecond()));
updatePoseWithClip(CLOSEST_FRAME_IDX, poseTime, rig->GetRootNode(), SHMatrix::Identity);
updatePoseWithClip(poseTime, rig->GetRootNode(), SHMatrix::Identity);
}
void SHAnimatorComponent::updatePoseWithClip(int closestFrameIndex, float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix)
void SHAnimatorComponent::updatePoseWithClip(float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix)
{
// Check if there is a channel for this node
SHMatrix transformMatrix = node->TransformMatrix;
@ -140,9 +138,9 @@ namespace SHADE
const auto& CHANNEL = CHANNELS[BONE_IDX];
transformMatrix = SHMatrix::Transform
(
getInterpolatedValue(CHANNEL.PositionKeyFrames, closestFrameIndex, poseTime),
getInterpolatedValue(CHANNEL.RotationKeyFrames, closestFrameIndex, poseTime),
getInterpolatedValue(CHANNEL.ScaleKeyFrames, closestFrameIndex, poseTime)
getInterpolatedValue(CHANNEL.PositionKeyFrames, poseTime),
getInterpolatedValue(CHANNEL.RotationKeyFrames, poseTime),
getInterpolatedValue(CHANNEL.ScaleKeyFrames, poseTime)
);
}
@ -160,7 +158,7 @@ namespace SHADE
// Apply pose to children
for (auto& child : node->Children)
{
updatePoseWithClip(closestFrameIndex, poseTime, child, transformMatrix);
updatePoseWithClip(poseTime, child, transformMatrix);
}
}
}

View File

@ -139,9 +139,9 @@ namespace SHADE
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
void updatePoseWithClip(float poseTime);
void updatePoseWithClip(int closestFrameIndex, float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix);
void updatePoseWithClip(float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix);
template<typename T>
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime);
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, float poseTime);
/*---------------------------------------------------------------------------------*/
/* RTTR */

View File

@ -26,7 +26,7 @@ namespace SHADE
/* Helper Functions */
/*-----------------------------------------------------------------------------------*/
template<typename T>
T SHAnimatorComponent::getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime)
T SHAnimatorComponent::getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, 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.");
@ -38,11 +38,11 @@ namespace SHADE
{
const auto& KEYFRAME = *iter;
if (KEYFRAME.FrameIndex <= closestFrameIndex)
if (KEYFRAME.TimeStamp <= poseTime)
{
firstKeyFrame = iter;
}
else // KEYFRAME.FrameIndex > closestFrameIndex
else // KEYFRAME.FrameIndex > poseTime
{
nextKeyFrame = iter;
break;
@ -66,8 +66,8 @@ namespace SHADE
}
// Get interpolated vector
const float PREV_FRAME_TIME = firstKeyFrame->FrameIndex * secsPerTick;
const float NEXT_FRAME_TIME = nextKeyFrame->FrameIndex * secsPerTick;
const float PREV_FRAME_TIME = firstKeyFrame->TimeStamp;
const float NEXT_FRAME_TIME = nextKeyFrame->TimeStamp;
const float NORMALISED_TIME = (poseTime - PREV_FRAME_TIME) / (NEXT_FRAME_TIME - PREV_FRAME_TIME);
if constexpr (std::is_same_v<T, SHQuaternion>)

View File

@ -71,7 +71,7 @@ namespace SHADE
//! of the texture library would mean the recreation of the desc set that also
//! involves the generic data, which is bad bad bad. Solution is to separate the
//! 2 desc sets.
static constexpr uint32_t DEFAULT_MAX_TEXTURES = 2000;
static constexpr uint32_t DEFAULT_MAX_TEXTURES = 1000;
/*-----------------------------------------------------------------------------*/
/* Usage Functions */