Added reworked AnimationClip and SHAnimClipAsset

This commit is contained in:
Kah Wei 2023-02-28 19:19:06 +08:00
parent 33b5b84fd4
commit 36af939c67
9 changed files with 94 additions and 77 deletions

View File

@ -1,65 +1,27 @@
/************************************************************************************//*! /************************************************************************************//*!
\file SHRawAnimation.cpp \file SHAnimationClip.cpp
\author Tng Kah Wei, kahwei.tng, 390009620 \author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu \par email: kahwei.tng\@digipen.edu
\date Nov 20, 2022 \date Feb 27, 2023
\brief Contains the function definitions of the SHRawAnimation class. \brief Contains the function definitions of the SHAnimationClip class.
Copyright (C) 2022 DigiPen Institute of Technology. Copyright (C) 2023 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited. of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/ *//*************************************************************************************/
// Pre-compiled Header // Pre-compiled Header
#include "SHpch.h" #include "SHpch.h"
// Primary Header // Primary Header
#include "SHRawAnimation.h" #include "SHAnimationClip.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Constructors */ /* Constructors */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHRawAnimation::SHRawAnimation(const SHAnimAsset& asset) SHAnimationClip::SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame)
: ticksPerSecond { static_cast<int>(asset.ticksPerSecond) } : rawAnim { rawAnimHandle }
, totalTime { static_cast<float>(asset.duration) / static_cast<int>(asset.ticksPerSecond) } , startFrameIndex { firstFrame }
{ , endFrameIndex { lastFrame }
// Populate keyframes {}
for (const auto& channel : asset.nodeChannels)
{
// Create a channel
Channel newChannel;
newChannel.Name = std::string(channel.name);
newChannel.PositionKeyFrames.reserve(channel.positionKeys.size());
newChannel.RotationKeyFrames.reserve(channel.rotationKeys.size());
newChannel.ScaleKeyFrames.reserve(channel.scaleKeys.size());
// Populate Keyframes
for (const auto& posKey : channel.positionKeys)
{
newChannel.PositionKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ static_cast<int>(posKey.time), posKey.value});
}
for (const auto& rotKey : channel.rotationKeys)
{
newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame<SHQuaternion>{ static_cast<int>(rotKey.time), rotKey.value});
}
for (const auto& scaleKey : channel.scaleKeys)
{
newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ static_cast<int>(scaleKey.time), scaleKey.value});
}
newChannel.MaxFrames = std::max({ newChannel.PositionKeyFrames.size(), newChannel.RotationKeyFrames.size(), newChannel.ScaleKeyFrames.size() });
// Insert the channel
channels.emplace_back(std::move(newChannel));
}
}
/*-----------------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------------*/
} }

View File

@ -2,10 +2,10 @@
\file SHAnimationClip.h \file SHAnimationClip.h
\author Tng Kah Wei, kahwei.tng, 390009620 \author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu \par email: kahwei.tng\@digipen.edu
\date Dec 12, 2022 \date Feb 27, 2023
\brief Contains the definition of the SHAnimationClip struct and related types. \brief Contains the definition of the SHAnimationClip struct and related types.
Copyright (C) 2022 DigiPen Institute of Technology. Copyright (C) 2023 DigiPen Institute of Technology.
Reproduction or disclosure of this file or its contents without the prior written consent Reproduction or disclosure of this file or its contents without the prior written consent
of DigiPen Institute of Technology is prohibited. of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/ *//*************************************************************************************/
@ -33,19 +33,23 @@ namespace SHADE
class SH_API SHAnimationClip class SH_API SHAnimationClip
{ {
public: public:
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructors */ /* Constructors */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/// <summary>
/// Constructs an animation clip that contains the following parameters.
/// </summary>
/// <param name="rawAnimHandle">Handle to the raw animation data.</param>
/// <param name="firstFrame">First frame to be played.</param>
/// <param name="lastFrame">Last frame to be played.</param>
SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame);
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
inline Handle<SHRawAnimation> GetRawAnimation() const noexcept { return rawAnim; } inline Handle<SHRawAnimation> GetRawAnimation() const noexcept { return rawAnim; }
inline float GetTotalTime() const noexcept { } inline int GetStartFrameIndex() const noexcept { return startFrameIndex; }
inline int GetEndFrameIndex() const noexcept { return endFrameIndex; }
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -54,11 +58,5 @@ namespace SHADE
Handle<SHRawAnimation> rawAnim; Handle<SHRawAnimation> rawAnim;
int startFrameIndex; // First Frame int startFrameIndex; // First Frame
int endFrameIndex; // Last Frame (inclusive) int endFrameIndex; // Last Frame (inclusive)
float totalTime; // Time to take from first to last frame
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
}; };
} }

View File

@ -92,15 +92,27 @@ namespace SHADE
if (currClip == newClip) if (currClip == newClip)
return; return;
// Get animation data
auto animData = currClip->GetRawAnimation();
if (!animData)
return;
// Set parameters // Set parameters
currClip = newClip; currClip = newClip;
secsPerTick = 1.0f / currClip->GetTicksPerSecond(); secsPerTick = 1.0f / animData->GetTicksPerSecond();
// Build channel map // Calculate total time for the clip
channelMap.clear();
if (currClip) if (currClip)
{ {
for (const auto& channel : currClip->GetChannels()) const int ONE_PAST_LAST_FRAME = currClip->GetEndFrameIndex() + 1;
currClipTotalTime = (ONE_PAST_LAST_FRAME - currClip->GetStartFrameIndex()) / animData->GetTicksPerSecond();
}
// Build channel map and clip-specific data
channelMap.clear();
if (animData)
{
for (const auto& channel : animData->GetChannels())
{ {
channelMap.emplace(channel.Name, &channel); channelMap.emplace(channel.Name, &channel);
} }
@ -131,7 +143,7 @@ namespace SHADE
// Update time on the playback // Update time on the playback
currPlaybackTime += dt; currPlaybackTime += dt;
if (currPlaybackTime > animData->GetTotalTime()) if (currPlaybackTime > currClipTotalTime)
{ {
if (playOnce) if (playOnce)
{ {
@ -140,7 +152,7 @@ namespace SHADE
} }
else else
{ {
currPlaybackTime = currPlaybackTime - animData->GetTotalTime(); currPlaybackTime = currPlaybackTime - currClipTotalTime;
} }
} }
@ -154,7 +166,7 @@ namespace SHADE
void SHAnimatorComponent::updatePoseWithClip(float poseTime) void SHAnimatorComponent::updatePoseWithClip(float poseTime)
{ {
// Get closest frame index // Get closest frame index
const int CLOSEST_FRAME_IDX = static_cast<int>(std::floorf(poseTime * currClip->GetTicksPerSecond())); const int CLOSEST_FRAME_IDX = currClip->GetStartFrameIndex() + static_cast<int>(std::floorf(poseTime * currClip->GetRawAnimation()->GetTicksPerSecond()));
updatePoseWithClip(CLOSEST_FRAME_IDX, poseTime, rig->GetRootNode(), SHMatrix::Identity); updatePoseWithClip(CLOSEST_FRAME_IDX, poseTime, rig->GetRootNode(), SHMatrix::Identity);
} }

View File

@ -136,6 +136,7 @@ namespace SHADE
float currPlaybackTime = 0.0f; float currPlaybackTime = 0.0f;
bool isPlaying = true; bool isPlaying = true;
bool playOnce = false; bool playOnce = false;
float currClipTotalTime = 0.0f;
// Useful Cached Data // Useful Cached Data
float secsPerTick = 0.0f; float secsPerTick = 0.0f;
// Buffer // Buffer

View File

@ -0,0 +1,28 @@
/************************************************************************************//*!
\file SHAnimClipAsset.h
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Feb 27, 2023
\brief Contains the definition of the SHAnimationClip struct and related types.
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.
*//*************************************************************************************/
#pragma once
#include <string>
#include "SH_API.h"
#include "SHAssetData.h"
namespace SHADE
{
struct SH_API SHAnimClipAsset : SHAssetData
{
std::string name;
AssetID animRawDataAssetId;
int firstIndex;
int lastIndex;
};
}

View File

@ -27,6 +27,8 @@
#include "Physics/Collision/Shapes/SHSphere.h" #include "Physics/Collision/Shapes/SHSphere.h"
#include "../SHEditorWindowManager.h" #include "../SHEditorWindowManager.h"
#include "../AssetBrowser/SHAssetBrowser.h" #include "../AssetBrowser/SHAssetBrowser.h"
#include "Animation/SHAnimationClip.h"
namespace SHADE namespace SHADE
{ {
template<typename T> template<typename T>
@ -644,12 +646,12 @@ namespace SHADE
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID); SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
} }
} }
Handle<SHRawAnimation> const& clip = component->GetCurrentClip(); Handle<SHRawAnimation> const clip = (component->GetCurrentClip() ? component->GetCurrentClip()->GetRawAnimation() : Handle<SHRawAnimation>{});
const auto CLIP_NAME = clip ? SHResourceManager::GetAssetName<SHRawAnimation>(clip).value_or("") : ""; const auto CLIP_NAME = clip ? SHResourceManager::GetAssetName<SHRawAnimation>(clip).value_or("") : "";
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Clip", CLIP_NAME, SHEditorWidgets::DragDropReadOnlyField<AssetID>("Clip", CLIP_NAME,
[component]() [component]()
{ {
Handle<SHRawAnimation> const& clip = component->GetCurrentClip(); Handle<SHRawAnimation> const clip = (component->GetCurrentClip() ? component->GetCurrentClip()->GetRawAnimation() : Handle<SHRawAnimation>{});
return SHResourceManager::GetAssetID<SHRawAnimation>(clip).value_or(0); return SHResourceManager::GetAssetID<SHRawAnimation>(clip).value_or(0);
}, },
[component](AssetID const& id) [component](AssetID const& id)
@ -659,11 +661,11 @@ namespace SHADE
SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!") SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!")
return; return;
} }
component->SetClip(SHResourceManager::LoadOrGet<SHRawAnimation>(id)); component->SetClip(SHResourceManager::LoadOrGet<SHAnimationClip>(id));
}, SHDragDrop::DRAG_RESOURCE); }, SHDragDrop::DRAG_RESOURCE);
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
{ {
if (Handle<SHRawAnimation> const& clip = component->GetCurrentClip()) if (Handle<SHRawAnimation> const clip = component->GetCurrentClip()->GetRawAnimation())
{ {
AssetID assetID = SHResourceManager::GetAssetID<SHRawAnimation>(clip).value_or(0); AssetID assetID = SHResourceManager::GetAssetID<SHRawAnimation>(clip).value_or(0);
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID); SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);

View File

@ -21,6 +21,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Assets/Asset Types/Models/SHModelAsset.h" #include "Assets/Asset Types/Models/SHModelAsset.h"
#include "Assets/Asset Types/SHTextureAsset.h" #include "Assets/Asset Types/SHTextureAsset.h"
#include "Assets/Asset Types/SHShaderAsset.h" #include "Assets/Asset Types/SHShaderAsset.h"
#include "Assets/Asset Types/SHAnimClipAsset.h"
#include "Graphics/Shaders/SHVkShaderModule.h" #include "Graphics/Shaders/SHVkShaderModule.h"
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h" #include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h" #include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
@ -38,6 +39,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
class SHMaterial; class SHMaterial;
struct SHRigNode; struct SHRigNode;
class SHAnimationClip;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -53,8 +55,9 @@ namespace SHADE
template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; }; template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; };
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; }; template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; };
template<> struct SHResourceLoader<SHFont> { using AssetType = SHFontAsset; }; template<> struct SHResourceLoader<SHFont> { using AssetType = SHFontAsset; };
template<> struct SHResourceLoader<SHRawAnimation> { using AssetType = SHModelAsset; }; template<> struct SHResourceLoader<SHRawAnimation> { using AssetType = SHModelAsset; };
template<> struct SHResourceLoader<SHRig> { using AssetType = SHModelAsset; }; template<> struct SHResourceLoader<SHRig> { using AssetType = SHModelAsset; };
template<> struct SHResourceLoader<SHAnimationClip> { using AssetType = SHAnimClipAsset; };
/// <summary> /// <summary>
/// Static class responsible for loading and caching runtime resources from their /// Static class responsible for loading and caching runtime resources from their

View File

@ -25,6 +25,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/Devices/SHVkLogicalDevice.h" #include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
#include "Serialization/SHYAMLConverters.h" #include "Serialization/SHYAMLConverters.h"
#include "Animation/SHAnimationClip.h"
namespace SHADE namespace SHADE
{ {
@ -360,5 +361,15 @@ namespace SHADE
loadedAssetData.emplace_back(assetId); loadedAssetData.emplace_back(assetId);
return resourceHub.Create<ResourceType>(*assetData.anims[0]); return resourceHub.Create<ResourceType>(*assetData.anims[0]);
} }
else if constexpr (std::is_same_v<ResourceType, SHAnimClipAsset>)
{
loadedAssetData.emplace_back(assetId);
return resourceHub.Create<ResourceType>
(
LoadOrGet<SHRawAnimation>(assetData->animRawDataAssetId),
assetData->firstIndex,
assetData->lastIndex
);
}
} }
} }

View File

@ -400,7 +400,7 @@ namespace YAML
{ {
YAML::Node node; YAML::Node node;
node[RIG_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHRig>(rhs.GetRig()).value_or(0); node[RIG_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHRig>(rhs.GetRig()).value_or(0);
node[CLIP_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHRawAnimation>(rhs.GetCurrentClip()).value_or(0); node[CLIP_YAML_TAG.data()] = SHResourceManager::GetAssetID<SHAnimationClip>(rhs.GetCurrentClip()).value_or(0);
return node; return node;
} }
static bool decode(YAML::Node const& node, SHAnimatorComponent& rhs) static bool decode(YAML::Node const& node, SHAnimatorComponent& rhs)
@ -411,7 +411,7 @@ namespace YAML
} }
if (node[CLIP_YAML_TAG.data()].IsDefined()) if (node[CLIP_YAML_TAG.data()].IsDefined())
{ {
rhs.SetClip(SHResourceManager::LoadOrGet<SHRawAnimation>(node[CLIP_YAML_TAG.data()].as<AssetID>())); rhs.SetClip(SHResourceManager::LoadOrGet<SHAnimationClip>(node[CLIP_YAML_TAG.data()].as<AssetID>()));
} }
return true; return true;
} }