diff --git a/SHADE_Engine/src/Animation/SHAnimationClip.cpp b/SHADE_Engine/src/Animation/SHAnimationClip.cpp
index 1f199b3f..4ef91a39 100644
--- a/SHADE_Engine/src/Animation/SHAnimationClip.cpp
+++ b/SHADE_Engine/src/Animation/SHAnimationClip.cpp
@@ -19,6 +19,10 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------------*/
+ SHAnimationClip::SHAnimationClip(const SHAnimAsset& asset)
+ {
+
+ }
/*-----------------------------------------------------------------------------------*/
diff --git a/SHADE_Engine/src/Animation/SHAnimationClip.h b/SHADE_Engine/src/Animation/SHAnimationClip.h
index ed1b7b81..d8415942 100644
--- a/SHADE_Engine/src/Animation/SHAnimationClip.h
+++ b/SHADE_Engine/src/Animation/SHAnimationClip.h
@@ -19,15 +19,12 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE
{
- /*-----------------------------------------------------------------------------------*/
- /* Forward Declarations */
- /*-----------------------------------------------------------------------------------*/
-
-
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
-
+ ///
+ /// Defines a single key frame in an animation.
+ ///
struct SHAnimationKeyFrame
{
float TimeStamp;
@@ -37,11 +34,19 @@ namespace SHADE
SHMatrix TransformationMatrix;
};
+ ///
+ /// Represents a animation clip of a 3D animation that is made for a specific model
+ /// rig.
+ ///
class SHAnimationClip
{
+ public:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
+ ///
+ /// Defines the animations of a single bone in a rig.
+ ///
struct Channel
{
std::string Name;
@@ -56,12 +61,15 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
+ const std::vector& GetChannels() const noexcept { return channels; }
+ float GetTotalTime() const noexcept { return totalTime; }
private:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
- std::vector Channels;
+ std::vector channels;
+ float totalTime;
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp
index debb2fb2..629453a6 100644
--- a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp
+++ b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp
@@ -13,12 +13,50 @@ of DigiPen Institute of Technology is prohibited.
#include "SHpch.h"
// Primary Include
#include "SHAnimatorComponent.h"
+// STL Includes
+#include
// 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
{
+ /*-----------------------------------------------------------------------------------*/
+ /* Usage Functions */
+ /*-----------------------------------------------------------------------------------*/
+ void SHAnimatorComponent::Play()
+ {
+ isPlaying = false;
+ }
+
+ void SHAnimatorComponent::Play(Handle 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 */
/*-----------------------------------------------------------------------------------*/
@@ -31,14 +69,21 @@ namespace SHADE
rig = newRig;
// Populate bone matrices based on new rig's default pose
+ boneMatrices.clear();
if (rig)
{
+ std::fill_n(std::back_inserter(boneMatrices), rig->GetNodeCount(), SHMatrix::Identity);
+ }
+ }
- }
- else
- {
- boneMatrices.clear();
- }
+ void SHAnimatorComponent::SetClip(Handle newClip)
+ {
+ // No change
+ if (currClip == newClip)
+ return;
+
+ currClip = newClip;
+ updatePoseWithClip(0.0f);
}
/*-----------------------------------------------------------------------------------*/
@@ -46,10 +91,85 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
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> 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
{
using namespace SHADE;
diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.h b/SHADE_Engine/src/Animation/SHAnimatorComponent.h
index 446014cc..056aa536 100644
--- a/SHADE_Engine/src/Animation/SHAnimatorComponent.h
+++ b/SHADE_Engine/src/Animation/SHAnimatorComponent.h
@@ -26,6 +26,8 @@ namespace SHADE
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHRig;
+ class SHAnimationClip;
+ class SHVkBuffer;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
@@ -40,20 +42,61 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Usage Functions */
/*---------------------------------------------------------------------------------*/
- /*void Play();
+ ///
+ /// Plays the currently loaded animation from the last time.
+ ///
+ void Play();
+ ///
+ /// Plays the specified animation clip from the start.
+ ///
+ ///
+ void Play(Handle clip);
+ ///
+ /// Plays the currently loaded animation clip from the start.
+ ///
void PlayFromStart();
+ ///
+ /// Pauses the animation at the current time.
+ ///
void Pause();
- void Stop();*/
+ ///
+ /// Stops the animation and resets the play time back to 0.
+ ///
+ void Stop();
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
+ ///
+ /// Sets the animation rig for this animator.
+ ///
+ /// Rig to use.
void SetRig(Handle newRig);
+ ///
+ /// 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.
+ ///
+ /// Clip to use.
+ void SetClip(Handle newClip);
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
+ ///
+ /// Retrieves all the bone matrices of this animator.
+ ///
+ /// Reference to a vector of the bone matrices.
const std::vector& GetBoneMatrices() const noexcept { return boneMatrices; }
+ ///
+ /// Retrieve the currently set animation clip.
+ ///
+ /// Handle to the currently set animation clip.
+ Handle GetCurrentClip() const noexcept { return currClip; }
+ ///
+ /// Checks if an animation is currently playing.
+ ///
+ /// True if an animation clip is currently playing.
bool IsPlaying() const { return isPlaying; }
/*---------------------------------------------------------------------------------*/
@@ -70,10 +113,19 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
+ // Resources
Handle rig;
- std::vector boneMatrices;
+ Handle currClip;
+ // Playback Tracking
float currPlaybackTime = 0.0f;
bool isPlaying = false;
+ // Buffer
+ std::vector boneMatrices;
+
+ /*---------------------------------------------------------------------------------*/
+ /* Helper Functions */
+ /*---------------------------------------------------------------------------------*/
+ void updatePoseWithClip(float poseTime);
/*---------------------------------------------------------------------------------*/
/* RTTR */
diff --git a/SHADE_Engine/src/Animation/SHRig.cpp b/SHADE_Engine/src/Animation/SHRig.cpp
index 2214baa5..7c3059de 100644
--- a/SHADE_Engine/src/Animation/SHRig.cpp
+++ b/SHADE_Engine/src/Animation/SHRig.cpp
@@ -60,6 +60,16 @@ namespace SHADE
return nodeCount;
}
+ int SHRig::GetNodeIndex(Handle node) const noexcept
+ {
+ if (nodeIndexMap.contains(node))
+ {
+ return nodeIndexMap.at(node);
+ }
+
+ return -1;
+ }
+
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------------*/
@@ -78,6 +88,8 @@ namespace SHADE
{
nodeNames.emplace(newNode, NODE_DATA.name);
nodesByName.emplace(NODE_DATA.name, newNode);
+ nodeIndexMap.emplace(newNode, nodes.size());
+ nodes.emplace_back(newNode);
}
// Fill child nodes
diff --git a/SHADE_Engine/src/Animation/SHRig.h b/SHADE_Engine/src/Animation/SHRig.h
index af1b79ec..5c4f720d 100644
--- a/SHADE_Engine/src/Animation/SHRig.h
+++ b/SHADE_Engine/src/Animation/SHRig.h
@@ -34,6 +34,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
class SHRig
{
+ public:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
@@ -78,6 +79,10 @@ namespace SHADE
/// needed.
///
int GetNodeCount() const noexcept;
+ ///
+ /// Retrieves the index in the node storage.
+ ///
+ int GetNodeIndex(Handle node) const noexcept;
private:
/*---------------------------------------------------------------------------------*/
@@ -86,6 +91,8 @@ namespace SHADE
Handle rootNode;
std::unordered_map, std::string> nodeNames;
std::unordered_map> nodesByName;
+ std::vector> nodes;
+ std::unordered_map, int> nodeIndexMap;
int nodeCount = 0;
SHResourceLibrary nodeStore;
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h
index 08f07ea6..477a5720 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h
@@ -134,6 +134,7 @@ namespace SHADE
TripleDescSet matPropsDescSet;
TripleBuffer boneMatrixBuffer;
TripleBuffer boneFirstIndexBuffer;
+ TripleDescSet boneMatricesDescSet;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */