From 5c14a0829af6fecdf2f206c9ccf6adaba4cce75c Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 10 Jan 2023 11:46:37 +0800 Subject: [PATCH] Added support for edge cases in transforms interpolation for animation clips --- .../src/Animation/SHAnimatorComponent.cpp | 59 +------------ .../src/Animation/SHAnimatorComponent.h | 11 ++- .../src/Animation/SHAnimatorComponent.hpp | 82 +++++++++++++++++++ 3 files changed, 92 insertions(+), 60 deletions(-) create mode 100644 SHADE_Engine/src/Animation/SHAnimatorComponent.hpp diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp index 4b2ca166..493833d0 100644 --- a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp +++ b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp @@ -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 @@ -145,65 +146,11 @@ namespace SHADE ( getInterpolatedValue(channel.PositionKeyFrames, 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>& 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>& 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); - } } /*-------------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.h b/SHADE_Engine/src/Animation/SHAnimatorComponent.h index 91edc9fc..d6adfa49 100644 --- a/SHADE_Engine/src/Animation/SHAnimatorComponent.h +++ b/SHADE_Engine/src/Animation/SHAnimatorComponent.h @@ -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,12 +132,14 @@ namespace SHADE /* Helper Functions */ /*---------------------------------------------------------------------------------*/ void updatePoseWithClip(float poseTime); - SHVec3 getInterpolatedValue(const std::vector>& keyframes, int closestFrameIndex, float poseTime); - SHQuaternion getInterpolatedValue(const std::vector>& keyframes, int closestFrameIndex, float poseTime); + template + T getInterpolatedValue(const std::vector>& keyframes, int closestFrameIndex, float poseTime); /*---------------------------------------------------------------------------------*/ /* RTTR */ /*---------------------------------------------------------------------------------*/ RTTR_ENABLE() }; -} \ No newline at end of file +} + +#include "SHAnimatorComponent.hpp" \ No newline at end of file diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.hpp b/SHADE_Engine/src/Animation/SHAnimatorComponent.hpp new file mode 100644 index 00000000..9c70d15e --- /dev/null +++ b/SHADE_Engine/src/Animation/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 + T SHAnimatorComponent::getInterpolatedValue(const std::vector>& keyframes, int closestFrameIndex, float poseTime) + { + // Only allow SHVec3 and SHQuaternion + static_assert(std::is_same_v || std::is_same_v, "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) + { + return SHQuaternion::Slerp(firstKeyFrame->Data, nextKeyFrame->Data, NORMALISED_TIME); + } + else if constexpr (std::is_same_v) + { + return SHVec3::Lerp(firstKeyFrame->Data, nextKeyFrame->Data, NORMALISED_TIME); + } + } +}