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 // Populate Keyframes
for (const auto& posKey : channel.positionKeys) 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) 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) 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() }); newChannel.MaxFrames = std::max({ newChannel.PositionKeyFrames.size(), newChannel.RotationKeyFrames.size(), newChannel.ScaleKeyFrames.size() });

View File

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

View File

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

View File

@ -26,7 +26,7 @@ namespace SHADE
/* Helper Functions */ /* Helper Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
template<typename T> 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 // 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."); 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; const auto& KEYFRAME = *iter;
if (KEYFRAME.FrameIndex <= closestFrameIndex) if (KEYFRAME.TimeStamp <= poseTime)
{ {
firstKeyFrame = iter; firstKeyFrame = iter;
} }
else // KEYFRAME.FrameIndex > closestFrameIndex else // KEYFRAME.FrameIndex > poseTime
{ {
nextKeyFrame = iter; nextKeyFrame = iter;
break; break;
@ -66,8 +66,8 @@ namespace SHADE
} }
// Get interpolated vector // Get interpolated vector
const float PREV_FRAME_TIME = firstKeyFrame->FrameIndex * secsPerTick; const float PREV_FRAME_TIME = firstKeyFrame->TimeStamp;
const float NEXT_FRAME_TIME = nextKeyFrame->FrameIndex * secsPerTick; const float NEXT_FRAME_TIME = nextKeyFrame->TimeStamp;
const float NORMALISED_TIME = (poseTime - PREV_FRAME_TIME) / (NEXT_FRAME_TIME - PREV_FRAME_TIME); const float NORMALISED_TIME = (poseTime - PREV_FRAME_TIME) / (NEXT_FRAME_TIME - PREV_FRAME_TIME);
if constexpr (std::is_same_v<T, SHQuaternion>) 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 //! 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 //! involves the generic data, which is bad bad bad. Solution is to separate the
//! 2 desc sets. //! 2 desc sets.
static constexpr uint32_t DEFAULT_MAX_TEXTURES = 2000; static constexpr uint32_t DEFAULT_MAX_TEXTURES = 1000;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Usage Functions */ /* Usage Functions */