Animation WIP merge #321

Merged
XiaoQiDigipen merged 76 commits from SP3-17-animation-system into main 2023-01-30 17:35:57 +08:00
7 changed files with 220 additions and 16 deletions
Showing only changes of commit c1910db2af - Show all commits

View File

@ -19,6 +19,10 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Constructors */ /* Constructors */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHAnimationClip::SHAnimationClip(const SHAnimAsset& asset)
{
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -19,15 +19,12 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/// <summary>
/// Defines a single key frame in an animation.
/// </summary>
struct SHAnimationKeyFrame struct SHAnimationKeyFrame
{ {
float TimeStamp; float TimeStamp;
@ -37,11 +34,19 @@ namespace SHADE
SHMatrix TransformationMatrix; SHMatrix TransformationMatrix;
}; };
/// <summary>
/// Represents a animation clip of a 3D animation that is made for a specific model
/// rig.
/// </summary>
class SHAnimationClip class SHAnimationClip
{ {
public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/// <summary>
/// Defines the animations of a single bone in a rig.
/// </summary>
struct Channel struct Channel
{ {
std::string Name; std::string Name;
@ -56,12 +61,15 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
const std::vector<Channel>& GetChannels() const noexcept { return channels; }
float GetTotalTime() const noexcept { return totalTime; }
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
std::vector<Channel> Channels; std::vector<Channel> channels;
float totalTime;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */

View File

@ -13,12 +13,50 @@ of DigiPen Institute of Technology is prohibited.
#include "SHpch.h" #include "SHpch.h"
// Primary Include // Primary Include
#include "SHAnimatorComponent.h" #include "SHAnimatorComponent.h"
// STL Includes
#include <queue>
// Project Includes // Project Includes
#include "SHRig.h" #include "SHRig.h"
#include "Math/SHMatrix.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 namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------------*/
void SHAnimatorComponent::Play()
{
isPlaying = false;
}
void SHAnimatorComponent::Play(Handle<SHAnimationClip> clip)
{
currClip = clip;
currPlaybackTime = 0.0f;
Play();
}
void SHAnimatorComponent::PlayFromStart()
{
isPlaying = true;
currPlaybackTime = 0.0f;
}
void SHAnimatorComponent::Pause()
{
isPlaying = false;
}
void SHAnimatorComponent::Stop()
{
isPlaying = false;
currPlaybackTime = 0.0f;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -31,14 +69,21 @@ namespace SHADE
rig = newRig; rig = newRig;
// Populate bone matrices based on new rig's default pose // Populate bone matrices based on new rig's default pose
boneMatrices.clear();
if (rig) if (rig)
{ {
std::fill_n(std::back_inserter(boneMatrices), rig->GetNodeCount(), SHMatrix::Identity);
}
}
} void SHAnimatorComponent::SetClip(Handle<SHAnimationClip> newClip)
else
{ {
boneMatrices.clear(); // No change
} if (currClip == newClip)
return;
currClip = newClip;
updatePoseWithClip(0.0f);
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -46,10 +91,85 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHAnimatorComponent::Update(float dt) void SHAnimatorComponent::Update(float dt)
{ {
// Set everything to identity // Nothing to animate
if (!currClip || !isPlaying)
return;
// Update time on the playback
currPlaybackTime += dt;
if (currPlaybackTime > currClip->GetTotalTime())
{
currPlaybackTime = currPlaybackTime - currClip->GetTotalTime();
}
// Reset all matrices
for (auto& mat : boneMatrices)
{
mat = SHMatrix::Identity;
}
// Play the clip
updatePoseWithClip(currPlaybackTime);
}
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------------*/
void SHAnimatorComponent::updatePoseWithClip(float poseTime)
{
for (const auto& channel : currClip->GetChannels())
{
// Get the bone
std::queue<Handle<SHRig::Node>> bones;
bones.push(rig->GetNode(channel.Name));
while (!bones.empty())
{
// Select bone at front of the queue
auto bone = bones.front(); bones.pop();
if (!bone)
continue;
// Add any children to the queue
for (auto child : bone->Children)
{
bones.push(child);
}
// Get interpolated frame
auto firstKeyFrame = channel.KeyFrames.end();
auto nextKeyFrame = channel.KeyFrames.end();
for (auto iter = channel.KeyFrames.begin(); iter != channel.KeyFrames.end(); ++iter)
{
const auto& KEYFRAME = *iter;
if(KEYFRAME.TimeStamp <= poseTime)
{
firstKeyFrame = iter;
}
else if (KEYFRAME.TimeStamp > poseTime)
{
nextKeyFrame = iter;
break;
}
}
// Calculate the matrix
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
(
SHVec3::Lerp(firstKeyFrame->Position, nextKeyFrame->Position, T),
SHQuaternion::Slerp(firstKeyFrame->Orientation, nextKeyFrame->Orientation, T),
SHVec3::Lerp(firstKeyFrame->Scale, nextKeyFrame->Scale, T)
);
}
} }
} }
}
/*-------------------------------------------------------------------------------------*/
/* RTTR Registration */
/*-------------------------------------------------------------------------------------*/
RTTR_REGISTRATION RTTR_REGISTRATION
{ {
using namespace SHADE; using namespace SHADE;

View File

@ -26,6 +26,8 @@ namespace SHADE
/* Forward Declarations */ /* Forward Declarations */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
class SHRig; class SHRig;
class SHAnimationClip;
class SHVkBuffer;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -40,20 +42,61 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Usage Functions */ /* Usage Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/*void Play(); /// <summary>
/// Plays the currently loaded animation from the last time.
/// </summary>
void Play();
/// <summary>
/// Plays the specified animation clip from the start.
/// </summary>
/// <param name="clip"></param>
void Play(Handle<SHAnimationClip> clip);
/// <summary>
/// Plays the currently loaded animation clip from the start.
/// </summary>
void PlayFromStart(); void PlayFromStart();
/// <summary>
/// Pauses the animation at the current time.
/// </summary>
void Pause(); void Pause();
void Stop();*/ /// <summary>
/// Stops the animation and resets the play time back to 0.
/// </summary>
void Stop();
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/// <summary>
/// Sets the animation rig for this animator.
/// </summary>
/// <param name="newRig">Rig to use.</param>
void SetRig(Handle<SHRig> newRig); void SetRig(Handle<SHRig> newRig);
/// <summary>
/// Sets the animation clip of this animator without playing it.
/// This will set the pose of the model to it's initial pose.
/// If the clip is the same as the current clip, nothing happens.
/// </summary>
/// <param name="newClip">Clip to use.</param>
void SetClip(Handle<SHAnimationClip> newClip);
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/// <summary>
/// Retrieves all the bone matrices of this animator.
/// </summary>
/// <returns>Reference to a vector of the bone matrices.</returns>
const std::vector<SHMatrix>& GetBoneMatrices() const noexcept { return boneMatrices; } const std::vector<SHMatrix>& GetBoneMatrices() const noexcept { return boneMatrices; }
/// <summary>
/// Retrieve the currently set animation clip.
/// </summary>
/// <returns>Handle to the currently set animation clip.</returns>
Handle<SHAnimationClip> GetCurrentClip() const noexcept { return currClip; }
/// <summary>
/// Checks if an animation is currently playing.
/// </summary>
/// <returns>True if an animation clip is currently playing.</returns>
bool IsPlaying() const { return isPlaying; } bool IsPlaying() const { return isPlaying; }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -70,10 +113,19 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
// Resources
Handle<SHRig> rig; Handle<SHRig> rig;
std::vector<SHMatrix> boneMatrices; Handle<SHAnimationClip> currClip;
// Playback Tracking
float currPlaybackTime = 0.0f; float currPlaybackTime = 0.0f;
bool isPlaying = false; bool isPlaying = false;
// Buffer
std::vector<SHMatrix> boneMatrices;
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
void updatePoseWithClip(float poseTime);
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* RTTR */ /* RTTR */

View File

@ -60,6 +60,16 @@ namespace SHADE
return nodeCount; return nodeCount;
} }
int SHRig::GetNodeIndex(Handle<Node> node) const noexcept
{
if (nodeIndexMap.contains(node))
{
return nodeIndexMap.at(node);
}
return -1;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -78,6 +88,8 @@ namespace SHADE
{ {
nodeNames.emplace(newNode, NODE_DATA.name); nodeNames.emplace(newNode, NODE_DATA.name);
nodesByName.emplace(NODE_DATA.name, newNode); nodesByName.emplace(NODE_DATA.name, newNode);
nodeIndexMap.emplace(newNode, nodes.size());
nodes.emplace_back(newNode);
} }
// Fill child nodes // Fill child nodes

View File

@ -34,6 +34,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
class SHRig class SHRig
{ {
public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -78,6 +79,10 @@ namespace SHADE
/// needed. /// needed.
/// </summary> /// </summary>
int GetNodeCount() const noexcept; int GetNodeCount() const noexcept;
/// <summary>
/// Retrieves the index in the node storage.
/// </summary>
int GetNodeIndex(Handle<Node> node) const noexcept;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -86,6 +91,8 @@ namespace SHADE
Handle<Node> rootNode; Handle<Node> rootNode;
std::unordered_map<Handle<Node>, std::string> nodeNames; std::unordered_map<Handle<Node>, std::string> nodeNames;
std::unordered_map<std::string, Handle<Node>> nodesByName; std::unordered_map<std::string, Handle<Node>> nodesByName;
std::vector<Handle<Node>> nodes;
std::unordered_map<Handle<Node>, int> nodeIndexMap;
int nodeCount = 0; int nodeCount = 0;
SHResourceLibrary<Node> nodeStore; SHResourceLibrary<Node> nodeStore;

View File

@ -134,6 +134,7 @@ namespace SHADE
TripleDescSet matPropsDescSet; TripleDescSet matPropsDescSet;
TripleBuffer boneMatrixBuffer; TripleBuffer boneMatrixBuffer;
TripleBuffer boneFirstIndexBuffer; TripleBuffer boneFirstIndexBuffer;
TripleDescSet boneMatricesDescSet;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */