Implemented Animation Clip asset and animation controller #410
|
@ -1,65 +1,27 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHRawAnimation.cpp
|
||||
\file SHAnimationClip.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Nov 20, 2022
|
||||
\brief Contains the function definitions of the SHRawAnimation class.
|
||||
\date Feb 27, 2023
|
||||
\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
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
// Pre-compiled Header
|
||||
#include "SHpch.h"
|
||||
// Primary Header
|
||||
#include "SHRawAnimation.h"
|
||||
#include "SHAnimationClip.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHRawAnimation::SHRawAnimation(const SHAnimAsset& asset)
|
||||
: ticksPerSecond { static_cast<int>(asset.ticksPerSecond) }
|
||||
, totalTime { static_cast<float>(asset.duration) / static_cast<int>(asset.ticksPerSecond) }
|
||||
{
|
||||
// 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 */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHAnimationClip::SHAnimationClip(Handle<SHRawAnimation> rawAnimHandle, int firstFrame, int lastFrame)
|
||||
: rawAnim { rawAnimHandle }
|
||||
, startFrameIndex { firstFrame }
|
||||
, endFrameIndex { lastFrame }
|
||||
{}
|
||||
}
|
|
@ -2,10 +2,10 @@
|
|||
\file SHAnimationClip.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\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.
|
||||
|
||||
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
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
|
@ -33,19 +33,23 @@ namespace SHADE
|
|||
class SH_API SHAnimationClip
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* 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 */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
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:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -54,11 +58,5 @@ namespace SHADE
|
|||
Handle<SHRawAnimation> rawAnim;
|
||||
int startFrameIndex; // First Frame
|
||||
int endFrameIndex; // Last Frame (inclusive)
|
||||
float totalTime; // Time to take from first to last frame
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
};
|
||||
}
|
|
@ -92,15 +92,27 @@ namespace SHADE
|
|||
if (currClip == newClip)
|
||||
return;
|
||||
|
||||
// Get animation data
|
||||
auto animData = currClip->GetRawAnimation();
|
||||
if (!animData)
|
||||
return;
|
||||
|
||||
// Set parameters
|
||||
currClip = newClip;
|
||||
secsPerTick = 1.0f / currClip->GetTicksPerSecond();
|
||||
secsPerTick = 1.0f / animData->GetTicksPerSecond();
|
||||
|
||||
// Build channel map
|
||||
channelMap.clear();
|
||||
// Calculate total time for the clip
|
||||
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);
|
||||
}
|
||||
|
@ -131,7 +143,7 @@ namespace SHADE
|
|||
|
||||
// Update time on the playback
|
||||
currPlaybackTime += dt;
|
||||
if (currPlaybackTime > animData->GetTotalTime())
|
||||
if (currPlaybackTime > currClipTotalTime)
|
||||
{
|
||||
if (playOnce)
|
||||
{
|
||||
|
@ -140,7 +152,7 @@ namespace SHADE
|
|||
}
|
||||
else
|
||||
{
|
||||
currPlaybackTime = currPlaybackTime - animData->GetTotalTime();
|
||||
currPlaybackTime = currPlaybackTime - currClipTotalTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,7 +166,7 @@ namespace SHADE
|
|||
void SHAnimatorComponent::updatePoseWithClip(float poseTime)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -136,6 +136,7 @@ namespace SHADE
|
|||
float currPlaybackTime = 0.0f;
|
||||
bool isPlaying = true;
|
||||
bool playOnce = false;
|
||||
float currClipTotalTime = 0.0f;
|
||||
// Useful Cached Data
|
||||
float secsPerTick = 0.0f;
|
||||
// Buffer
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
|
@ -27,6 +27,8 @@
|
|||
#include "Physics/Collision/Shapes/SHSphere.h"
|
||||
#include "../SHEditorWindowManager.h"
|
||||
#include "../AssetBrowser/SHAssetBrowser.h"
|
||||
#include "Animation/SHAnimationClip.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
template<typename T>
|
||||
|
@ -644,12 +646,12 @@ namespace SHADE
|
|||
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("") : "";
|
||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Clip", CLIP_NAME,
|
||||
[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);
|
||||
},
|
||||
[component](AssetID const& id)
|
||||
|
@ -659,11 +661,11 @@ namespace SHADE
|
|||
SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!")
|
||||
return;
|
||||
}
|
||||
component->SetClip(SHResourceManager::LoadOrGet<SHRawAnimation>(id));
|
||||
component->SetClip(SHResourceManager::LoadOrGet<SHAnimationClip>(id));
|
||||
}, SHDragDrop::DRAG_RESOURCE);
|
||||
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);
|
||||
SHEditorWindowManager::GetEditorWindow<SHAssetBrowser>()->SetScrollTo(assetID);
|
||||
|
|
|
@ -21,6 +21,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Assets/Asset Types/Models/SHModelAsset.h"
|
||||
#include "Assets/Asset Types/SHTextureAsset.h"
|
||||
#include "Assets/Asset Types/SHShaderAsset.h"
|
||||
#include "Assets/Asset Types/SHAnimClipAsset.h"
|
||||
#include "Graphics/Shaders/SHVkShaderModule.h"
|
||||
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
|
||||
|
@ -38,6 +39,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
class SHMaterial;
|
||||
struct SHRigNode;
|
||||
class SHAnimationClip;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -53,8 +55,9 @@ namespace SHADE
|
|||
template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; };
|
||||
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; };
|
||||
template<> struct SHResourceLoader<SHFont> { using AssetType = SHFontAsset; };
|
||||
template<> struct SHResourceLoader<SHRawAnimation> { using AssetType = SHModelAsset; };
|
||||
template<> struct SHResourceLoader<SHRig> { using AssetType = SHModelAsset; };
|
||||
template<> struct SHResourceLoader<SHRawAnimation> { using AssetType = SHModelAsset; };
|
||||
template<> struct SHResourceLoader<SHRig> { using AssetType = SHModelAsset; };
|
||||
template<> struct SHResourceLoader<SHAnimationClip> { using AssetType = SHAnimClipAsset; };
|
||||
|
||||
/// <summary>
|
||||
/// Static class responsible for loading and caching runtime resources from their
|
||||
|
|
|
@ -25,6 +25,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
||||
#include "Serialization/SHYAMLConverters.h"
|
||||
#include "Animation/SHAnimationClip.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -360,5 +361,15 @@ namespace SHADE
|
|||
loadedAssetData.emplace_back(assetId);
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -400,7 +400,7 @@ namespace YAML
|
|||
{
|
||||
YAML::Node node;
|
||||
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;
|
||||
}
|
||||
static bool decode(YAML::Node const& node, SHAnimatorComponent& rhs)
|
||||
|
@ -411,7 +411,7 @@ namespace YAML
|
|||
}
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue