From 36af939c6714fe509ce5450158906bc68b8c7ea4 Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Tue, 28 Feb 2023 19:19:06 +0800 Subject: [PATCH] Added reworked AnimationClip and SHAnimClipAsset --- .../src/Animation/SHAnimationClip.cpp | 58 ++++--------------- SHADE_Engine/src/Animation/SHAnimationClip.h | 26 ++++----- .../src/Animation/SHAnimatorComponent.cpp | 26 ++++++--- .../src/Animation/SHAnimatorComponent.h | 1 + .../src/Assets/Asset Types/SHAnimClipAsset.h | 28 +++++++++ .../Inspector/SHEditorComponentView.hpp | 10 ++-- SHADE_Engine/src/Resource/SHResourceManager.h | 7 ++- .../src/Resource/SHResourceManager.hpp | 11 ++++ .../src/Serialization/SHYAMLConverters.h | 4 +- 9 files changed, 94 insertions(+), 77 deletions(-) create mode 100644 SHADE_Engine/src/Assets/Asset Types/SHAnimClipAsset.h diff --git a/SHADE_Engine/src/Animation/SHAnimationClip.cpp b/SHADE_Engine/src/Animation/SHAnimationClip.cpp index 86d0af18..2678b95b 100644 --- a/SHADE_Engine/src/Animation/SHAnimationClip.cpp +++ b/SHADE_Engine/src/Animation/SHAnimationClip.cpp @@ -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(asset.ticksPerSecond) } - , totalTime { static_cast(asset.duration) / static_cast(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{ static_cast(posKey.time), posKey.value}); - } - for (const auto& rotKey : channel.rotationKeys) - { - newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame{ static_cast(rotKey.time), rotKey.value}); - } - for (const auto& scaleKey : channel.scaleKeys) - { - newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame{ static_cast(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 rawAnimHandle, int firstFrame, int lastFrame) + : rawAnim { rawAnimHandle } + , startFrameIndex { firstFrame } + , endFrameIndex { lastFrame } + {} } \ No newline at end of file diff --git a/SHADE_Engine/src/Animation/SHAnimationClip.h b/SHADE_Engine/src/Animation/SHAnimationClip.h index a6ec923f..547acf92 100644 --- a/SHADE_Engine/src/Animation/SHAnimationClip.h +++ b/SHADE_Engine/src/Animation/SHAnimationClip.h @@ -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 */ /*---------------------------------------------------------------------------------*/ - + /// + /// Constructs an animation clip that contains the following parameters. + /// + /// Handle to the raw animation data. + /// First frame to be played. + /// Last frame to be played. + SHAnimationClip(Handle rawAnimHandle, int firstFrame, int lastFrame); + /*---------------------------------------------------------------------------------*/ /* Getter Functions */ /*---------------------------------------------------------------------------------*/ inline Handle 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 rawAnim; int startFrameIndex; // First Frame int endFrameIndex; // Last Frame (inclusive) - float totalTime; // Time to take from first to last frame - - /*---------------------------------------------------------------------------------*/ - /* Helper Functions */ - /*---------------------------------------------------------------------------------*/ - }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp index 2f886c75..eee7fd51 100644 --- a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp +++ b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp @@ -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(std::floorf(poseTime * currClip->GetTicksPerSecond())); + const int CLOSEST_FRAME_IDX = currClip->GetStartFrameIndex() + static_cast(std::floorf(poseTime * currClip->GetRawAnimation()->GetTicksPerSecond())); updatePoseWithClip(CLOSEST_FRAME_IDX, poseTime, rig->GetRootNode(), SHMatrix::Identity); } diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.h b/SHADE_Engine/src/Animation/SHAnimatorComponent.h index b5ea02b0..12d377fe 100644 --- a/SHADE_Engine/src/Animation/SHAnimatorComponent.h +++ b/SHADE_Engine/src/Animation/SHAnimatorComponent.h @@ -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 diff --git a/SHADE_Engine/src/Assets/Asset Types/SHAnimClipAsset.h b/SHADE_Engine/src/Assets/Asset Types/SHAnimClipAsset.h new file mode 100644 index 00000000..a1bd87a6 --- /dev/null +++ b/SHADE_Engine/src/Assets/Asset Types/SHAnimClipAsset.h @@ -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 + +#include "SH_API.h" +#include "SHAssetData.h" + +namespace SHADE +{ + struct SH_API SHAnimClipAsset : SHAssetData + { + std::string name; + AssetID animRawDataAssetId; + int firstIndex; + int lastIndex; + }; +} \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 7f6192f1..3ceb7166 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -27,6 +27,8 @@ #include "Physics/Collision/Shapes/SHSphere.h" #include "../SHEditorWindowManager.h" #include "../AssetBrowser/SHAssetBrowser.h" +#include "Animation/SHAnimationClip.h" + namespace SHADE { template @@ -644,12 +646,12 @@ namespace SHADE SHEditorWindowManager::GetEditorWindow()->SetScrollTo(assetID); } } - Handle const& clip = component->GetCurrentClip(); + Handle const clip = (component->GetCurrentClip() ? component->GetCurrentClip()->GetRawAnimation() : Handle{}); const auto CLIP_NAME = clip ? SHResourceManager::GetAssetName(clip).value_or("") : ""; SHEditorWidgets::DragDropReadOnlyField("Clip", CLIP_NAME, [component]() { - Handle const& clip = component->GetCurrentClip(); + Handle const clip = (component->GetCurrentClip() ? component->GetCurrentClip()->GetRawAnimation() : Handle{}); return SHResourceManager::GetAssetID(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(id)); + component->SetClip(SHResourceManager::LoadOrGet(id)); }, SHDragDrop::DRAG_RESOURCE); if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) { - if (Handle const& clip = component->GetCurrentClip()) + if (Handle const clip = component->GetCurrentClip()->GetRawAnimation()) { AssetID assetID = SHResourceManager::GetAssetID(clip).value_or(0); SHEditorWindowManager::GetEditorWindow()->SetScrollTo(assetID); diff --git a/SHADE_Engine/src/Resource/SHResourceManager.h b/SHADE_Engine/src/Resource/SHResourceManager.h index e3766cf0..1f26bf2a 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.h +++ b/SHADE_Engine/src/Resource/SHResourceManager.h @@ -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 { using AssetType = SHMaterialAsset; }; template<> struct SHResourceLoader { using AssetType = SHMaterialSpec; }; template<> struct SHResourceLoader { using AssetType = SHFontAsset; }; - template<> struct SHResourceLoader { using AssetType = SHModelAsset; }; - template<> struct SHResourceLoader { using AssetType = SHModelAsset; }; + template<> struct SHResourceLoader { using AssetType = SHModelAsset; }; + template<> struct SHResourceLoader { using AssetType = SHModelAsset; }; + template<> struct SHResourceLoader { using AssetType = SHAnimClipAsset; }; /// /// Static class responsible for loading and caching runtime resources from their diff --git a/SHADE_Engine/src/Resource/SHResourceManager.hpp b/SHADE_Engine/src/Resource/SHResourceManager.hpp index a53249f7..da557748 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.hpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.hpp @@ -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(*assetData.anims[0]); } + else if constexpr (std::is_same_v) + { + loadedAssetData.emplace_back(assetId); + return resourceHub.Create + ( + LoadOrGet(assetData->animRawDataAssetId), + assetData->firstIndex, + assetData->lastIndex + ); + } } } diff --git a/SHADE_Engine/src/Serialization/SHYAMLConverters.h b/SHADE_Engine/src/Serialization/SHYAMLConverters.h index 132e44b5..9fceb10d 100644 --- a/SHADE_Engine/src/Serialization/SHYAMLConverters.h +++ b/SHADE_Engine/src/Serialization/SHYAMLConverters.h @@ -400,7 +400,7 @@ namespace YAML { YAML::Node node; node[RIG_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetRig()).value_or(0); - node[CLIP_YAML_TAG.data()] = SHResourceManager::GetAssetID(rhs.GetCurrentClip()).value_or(0); + node[CLIP_YAML_TAG.data()] = SHResourceManager::GetAssetID(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(node[CLIP_YAML_TAG.data()].as())); + rhs.SetClip(SHResourceManager::LoadOrGet(node[CLIP_YAML_TAG.data()].as())); } return true; }