Merge branch 'SP3-17-animation-system' into SP3-17-animation-viewer

# Conflicts:
#	SHADE_Engine/src/Animation/SHAnimationClip.h
This commit is contained in:
Kah Wei 2023-01-16 14:48:57 +08:00
commit 3b5d1ef6d5
31 changed files with 414 additions and 187 deletions

View File

@ -0,0 +1,8 @@
- VertexShader: 47911992
FragmentShader: 46377769
SubPass: G-Buffer Write
Properties:
data.color: {x: 1, y: 1, z: 1, w: 1}
data.textureIndex: 64651793
data.alpha: 0
data.beta: {x: 1, y: 1, z: 1}

View File

@ -0,0 +1,3 @@
Name: AnimatedRaccoon
ID: 128805346
Type: 7

Binary file not shown.

Binary file not shown.

View File

@ -1,65 +0,0 @@
#version 450
#extension GL_KHR_vulkan_glsl : enable
//#include "ShaderDescriptorDefinitions.glsl"
layout(location = 0) in vec3 aVertexPos;
layout(location = 1) in vec2 aUV;
layout(location = 2) in vec3 aNormal;
layout(location = 3) in vec3 aTangent;
layout(location = 4) in mat4 worldTransform;
layout(location = 5) in ivec4 aBoneIndices;
layout(location = 6) in vec4 aBoneWeights;
layout(location = 8) in uvec2 integerData;
layout(location = 0) out struct
{
vec4 vertPos; // location 0
vec2 uv; // location = 1
vec4 normal; // location = 2
} Out;
// material stuff
layout(location = 3) out struct
{
int materialIndex;
uint eid;
uint lightLayerIndex;
} Out2;
layout(set = 2, binding = 0) uniform CameraData
{
vec4 position;
mat4 vpMat;
mat4 viewMat;
mat4 projMat;
} cameraData;
void main()
{
Out2.materialIndex = gl_InstanceIndex;
Out2.eid = integerData[0];
Out2.lightLayerIndex = integerData[1];
// for transforming gBuffer position and normal data
mat4 modelViewMat = cameraData.viewMat * worldTransform;
// gBuffer position will be in view space
Out.vertPos = modelViewMat * vec4(aVertexPos, 1.0f);
// uvs for texturing in fragment shader
Out.uv = aUV;
mat3 transposeInv = mat3 (transpose(inverse(modelViewMat)));
// normals are also in view space
Out.normal.rgb = transposeInv * aNormal.rgb;
Out.normal.rgb = normalize (Out.normal.rgb);
// clip space for rendering
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);
}

View File

@ -47,6 +47,7 @@
#include "Tools/Logger/SHLogger.h" #include "Tools/Logger/SHLogger.h"
#include "Tools/SHDebugDraw.h" #include "Tools/SHDebugDraw.h"
#include "Resource/SHResourceManager.h"
using namespace SHADE; using namespace SHADE;
@ -170,6 +171,10 @@ namespace Sandbox
// Link up SHDebugDraw // Link up SHDebugDraw
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>()); SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
auto clip = SHResourceManager::LoadOrGet<SHAnimationClip>(77816045);
auto rig = SHResourceManager::LoadOrGet<SHRig>(77816045);
int i = 0;
} }
void SBApplication::Update(void) void SBApplication::Update(void)

View File

@ -20,10 +20,39 @@ namespace SHADE
/* Constructors */ /* Constructors */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHAnimationClip::SHAnimationClip(const SHAnimAsset& asset) SHAnimationClip::SHAnimationClip(const SHAnimAsset& asset)
: ticksPerSecond { static_cast<int>(asset.ticksPerSecond) }
, totalTime { static_cast<float>(asset.duration) }
{ {
// 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 */ /* Usage Functions */

View File

@ -11,9 +11,8 @@ of DigiPen Institute of Technology is prohibited.
*//*************************************************************************************/ *//*************************************************************************************/
#pragma once #pragma once
// STL Includes
// Project Includes // Project Includes
#include "SH_API.h"
#include "Math/SHMatrix.h" #include "Math/SHMatrix.h"
#include "Assets/Asset Types/Models/SHAnimationAsset.h" #include "Assets/Asset Types/Models/SHAnimationAsset.h"
@ -23,22 +22,20 @@ namespace SHADE
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/// <summary> /// <summary>
/// Defines a single key frame in an animation. /// Defines a single key frame in an animation for a specific type of data.
/// </summary> /// </summary>
template<typename T>
struct SHAnimationKeyFrame struct SHAnimationKeyFrame
{ {
float TimeStamp; int FrameIndex;
SHVec3 Position; T Data;
SHQuaternion Orientation;
SHVec3 Scale;
SHMatrix TransformationMatrix;
}; };
/// <summary> /// <summary>
/// Represents a animation clip of a 3D animation that is made for a specific model /// Represents a animation clip of a 3D animation that is made for a specific model
/// rig. /// rig.
/// </summary> /// </summary>
class SHAnimationClip class SH_API SHAnimationClip
{ {
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -50,19 +47,26 @@ namespace SHADE
struct Channel struct Channel
{ {
std::string Name; std::string Name;
std::vector<SHAnimationKeyFrame> KeyFrames; std::vector<SHAnimationKeyFrame<SHVec3>> PositionKeyFrames;
std::vector<SHAnimationKeyFrame<SHQuaternion>> RotationKeyFrames;
std::vector<SHAnimationKeyFrame<SHVec3>> ScaleKeyFrames;
int MaxFrames;
}; };
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Constructors */ /* Constructors */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
SHAnimationClip() = default; /// <summary>
/// Constructs an SHAnimation Clip from a specified SHAnimAsset.
/// </summary>
/// <param name="asset">Animation asset to load.</param>
explicit SHAnimationClip(const SHAnimAsset& asset); explicit SHAnimationClip(const SHAnimAsset& asset);
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
const std::vector<Channel>& GetChannels() const noexcept { return channels; } const std::vector<Channel>& GetChannels() const noexcept { return channels; }
int GetTicksPerSecond() const noexcept { return ticksPerSecond; }
float GetTotalTime() const noexcept { return totalTime; } float GetTotalTime() const noexcept { return totalTime; }
//private: //private:
@ -70,6 +74,7 @@ namespace SHADE
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
std::vector<Channel> channels; std::vector<Channel> channels;
int ticksPerSecond;
float totalTime; float totalTime;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -3,7 +3,8 @@
\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 Nov 20, 2022
\brief Contains the definition of functions of the SHRenderable Component class. \brief Contains the definition of functions of the SHAnimatorComponent Component
class.
Copyright (C) 2022 DigiPen Institute of Technology. Copyright (C) 2022 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
@ -83,8 +84,13 @@ namespace SHADE
return; return;
currClip = newClip; currClip = newClip;
secsPerTick = 1.0f / currClip->GetTicksPerSecond();
if (rig)
{
updatePoseWithClip(0.0f); updatePoseWithClip(0.0f);
} }
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Update Functions */ /* Update Functions */
@ -92,7 +98,7 @@ namespace SHADE
void SHAnimatorComponent::Update(float dt) void SHAnimatorComponent::Update(float dt)
{ {
// Nothing to animate // Nothing to animate
if (!currClip || !isPlaying) if (!currClip || !isPlaying || !rig)
return; return;
// Update time on the playback // Update time on the playback
@ -135,36 +141,20 @@ namespace SHADE
bones.push(child); bones.push(child);
} }
// Get interpolated frame // Get closest frame index
auto firstKeyFrame = channel.KeyFrames.end(); const int CLOSEST_FRAME_IDX = static_cast<int>(std::floorf(poseTime * currClip->GetTicksPerSecond()));
auto nextKeyFrame = channel.KeyFrames.end();
for (auto iter = channel.KeyFrames.begin(); iter != channel.KeyFrames.end(); ++iter)
{
const auto& KEYFRAME = *iter;
if(KEYFRAME.TimeStamp <= poseTime) // Calculate the matrix from interpolated values
{
firstKeyFrame = iter;
}
else if (KEYFRAME.TimeStamp > poseTime)
{
nextKeyFrame = iter;
break;
}
}
// Calculate the matrix
const int BONE_MTX_IDX = rig->GetNodeIndex(bone); 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 boneMatrices[BONE_MTX_IDX] = boneMatrices[BONE_MTX_IDX] * SHMatrix::Transform
( (
SHVec3::Lerp(firstKeyFrame->Position, nextKeyFrame->Position, T), getInterpolatedValue(channel.PositionKeyFrames, CLOSEST_FRAME_IDX, poseTime),
SHQuaternion::Slerp(firstKeyFrame->Orientation, nextKeyFrame->Orientation, T), getInterpolatedValue(channel.RotationKeyFrames, CLOSEST_FRAME_IDX, poseTime),
SHVec3::Lerp(firstKeyFrame->Scale, nextKeyFrame->Scale, T) getInterpolatedValue(channel.ScaleKeyFrames , CLOSEST_FRAME_IDX, poseTime)
); );
} }
} }
} }
} }
/*-------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------*/

View File

@ -3,7 +3,8 @@
\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 Nov 20, 2022
\brief Contains the definition of the SHAnimationSystem class and related types. \brief Contains the definition of the SHAnimatorComponent class and related
types.
Copyright (C) 2022 DigiPen Institute of Technology. Copyright (C) 2022 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
@ -19,6 +20,9 @@ of DigiPen Institute of Technology is prohibited.
#include "ECS_Base/Components/SHComponent.h" #include "ECS_Base/Components/SHComponent.h"
#include "Resource/SHHandle.h" #include "Resource/SHHandle.h"
#include "Math/SHMatrix.h" #include "Math/SHMatrix.h"
#include "Math/Vector/SHVec3.h"
#include "Math/SHQuaternion.h"
#include "SHAnimationClip.h"
namespace SHADE namespace SHADE
{ {
@ -89,6 +93,12 @@ namespace SHADE
/// <returns>Reference to a vector of the bone matrices.</returns> /// <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> /// <summary>
/// Retrieve the currently set model rig.
/// </summary>
/// <returns>Handle to the currently set rig.</returns>
Handle<SHRig> GetRig() const noexcept { return rig; }
/// <summary>
/// <summary>
/// Retrieve the currently set animation clip. /// Retrieve the currently set animation clip.
/// </summary> /// </summary>
/// <returns>Handle to the currently set animation clip.</returns> /// <returns>Handle to the currently set animation clip.</returns>
@ -119,6 +129,8 @@ namespace SHADE
// Playback Tracking // Playback Tracking
float currPlaybackTime = 0.0f; float currPlaybackTime = 0.0f;
bool isPlaying = false; bool isPlaying = false;
// Useful Cached Data
float secsPerTick = 0.0f;
// Buffer // Buffer
std::vector<SHMatrix> boneMatrices; std::vector<SHMatrix> boneMatrices;
@ -126,6 +138,8 @@ namespace SHADE
/* Helper Functions */ /* Helper Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void updatePoseWithClip(float poseTime); void updatePoseWithClip(float poseTime);
template<typename T>
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime);
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* RTTR */ /* RTTR */
@ -133,3 +147,5 @@ namespace SHADE
RTTR_ENABLE() RTTR_ENABLE()
}; };
} }
#include "SHAnimatorComponent.hpp"

View File

@ -0,0 +1,82 @@
/************************************************************************************//*!
\file SHAnimatorComponent.hpp
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Jan 10, 2023
\brief Contains the definition of function templates of the SHAnimatorComponent
Component class.
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.
*//*************************************************************************************/
// Primary Include
#include "SHAnimatorComponent.h"
// 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
{
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------------*/
template<typename T>
T SHAnimatorComponent::getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime)
{
// Only allow SHVec3 and SHQuaternion
static_assert(std::is_same_v<T, SHVec3> || std::is_same_v<T, SHQuaternion>, "Only interpolation for SHVec3 and SHQuaternion is allowed.");
// Find the key frames that surround the current frame index
auto firstKeyFrame = keyframes.end();
auto nextKeyFrame = keyframes.end();
for (auto iter = keyframes.begin(); iter != keyframes.end(); ++iter)
{
const auto& KEYFRAME = *iter;
if (KEYFRAME.FrameIndex <= closestFrameIndex)
{
firstKeyFrame = iter;
}
else if (KEYFRAME.FrameIndex > closestFrameIndex)
{
nextKeyFrame = iter;
break;
}
}
// Edge Cases
if (firstKeyFrame == keyframes.end())
{
// No keyframes at all, means no changes
if (nextKeyFrame == keyframes.end())
return T();
// At the back, so no keyframes will follow
else
return firstKeyFrame->Data;
}
// At the front, so no prior key frames
else if (nextKeyFrame != keyframes.end())
{
return nextKeyFrame->Data;
}
// Get interpolated vector
const float PREV_FRAME_TIME = firstKeyFrame->FrameIndex * secsPerTick;
const float NEXT_FRAME_TIME = nextKeyFrame->FrameIndex * secsPerTick;
const float NORMALISED_TIME = (poseTime - PREV_FRAME_TIME) / (NEXT_FRAME_TIME - PREV_FRAME_TIME);
if constexpr (std::is_same_v<T, SHQuaternion>)
{
return SHQuaternion::Slerp(firstKeyFrame->Data, nextKeyFrame->Data, NORMALISED_TIME);
}
else if constexpr (std::is_same_v<T, SHVec3>)
{
return SHVec3::Lerp(firstKeyFrame->Data, nextKeyFrame->Data, NORMALISED_TIME);
}
}
}

View File

@ -27,7 +27,10 @@ namespace SHADE
{ {
// Don't bother if empty // Don't bother if empty
if (asset.root == nullptr) if (asset.root == nullptr)
{
SHLOG_ERROR("[SHRig] Attempted to load an invalid rig with no root.");
return; return;
}
// Do a recursive depth first traversal to populate the rig // Do a recursive depth first traversal to populate the rig
nodeCount = 0; nodeCount = 0;
@ -100,7 +103,8 @@ namespace SHADE
continue; continue;
// Recursively create children // Recursively create children
newNode->Children.emplace_back(recurseCreateNode(asset, child)); auto childNode = recurseCreateNode(asset, child); // Not sure why this works but it is required for
newNode->Children.emplace_back(childNode); // the emplace_back operation to not crash
} }
return newNode; return newNode;

View File

@ -17,6 +17,7 @@ of DigiPen Institute of Technology is prohibited.
#include <unordered_map> #include <unordered_map>
// Project Includes // Project Includes
#include "SH_API.h"
#include "Math/SHMatrix.h" #include "Math/SHMatrix.h"
#include "Resource/SHHandle.h" #include "Resource/SHHandle.h"
#include "Resource/SHResourceLibrary.h" #include "Resource/SHResourceLibrary.h"
@ -32,7 +33,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
class SHRig class SH_API SHRig
{ {
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -153,7 +153,7 @@ namespace SHADE
} }
} }
void SHModelLoader::ReadRigTree(FileReference file, SHRigDataHeader const& header, SHRigNode* root) void SHModelLoader::ReadRigTree(FileReference file, SHRigDataHeader const& header, SHRigNode*& root)
{ {
// Read All nodes into one contiguous data block // Read All nodes into one contiguous data block
struct NodeTemp struct NodeTemp
@ -193,6 +193,8 @@ namespace SHADE
nodeQueue.emplace(depthPtr++, depthTempPtr++); nodeQueue.emplace(depthPtr++, depthTempPtr++);
} }
} }
delete[] dst;
} }
void SHModelLoader::ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers, void SHModelLoader::ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers,
@ -221,6 +223,34 @@ namespace SHADE
file.read(reinterpret_cast<char*>(data.VertexTexCoords.data()), vertexVec2Byte); file.read(reinterpret_cast<char*>(data.VertexTexCoords.data()), vertexVec2Byte);
file.read(reinterpret_cast<char*>(data.Indices.data()), sizeof(uint32_t) * header.indexCount); file.read(reinterpret_cast<char*>(data.Indices.data()), sizeof(uint32_t) * header.indexCount);
std::vector<MeshBoneInfo> boneInfos(header.boneCount);
std::vector<MeshBone> bones(header.boneCount);
file.read(reinterpret_cast<char*>(boneInfos.data()), sizeof(MeshBoneInfo) * header.boneCount);
for (auto i{ 0 }; i < header.boneCount; ++i)
{
auto& bone = bones[i];
auto const& info = boneInfos[i];
bone.name.resize(info.charCount);
file.read(bone.name.data(), info.charCount);
file.read(reinterpret_cast<char*>(&bone.offset), sizeof(SHMatrix));
uint32_t weightCount;
file.read(reinterpret_cast<char*>(&weightCount), sizeof(uint32_t));
bone.weights.resize(weightCount);
file.read(reinterpret_cast<char*>(bone.weights.data()), sizeof(BoneWeight) * weightCount);
}
data.VertexBoneIndices.resize(header.vertexCount);
data.VertexBoneWeights.resize(header.vertexCount);
for (auto const& bone : bones)
{
}
meshes[i] = &data; meshes[i] = &data;
} }
} }

View File

@ -24,7 +24,7 @@ namespace SHADE
void ReadRigHeader(FileReference file, SHRigDataHeader& header); void ReadRigHeader(FileReference file, SHRigDataHeader& header);
void ReadRigData(FileReference file, SHRigDataHeader const& header, std::vector<SHRigNodeData>& data); void ReadRigData(FileReference file, SHRigDataHeader const& header, std::vector<SHRigNodeData>& data);
void ReadRigTree(FileReference file, SHRigDataHeader const& header, SHRigNode* root); void ReadRigTree(FileReference file, SHRigDataHeader const& header, SHRigNode*& root);
void ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers, std::vector<SHMeshAsset*>& meshes); void ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers, std::vector<SHMeshAsset*>& meshes);
void ReadAnimData(FileReference file, std::vector<SHAnimDataHeader> const& headers, std::vector<SHAnimAsset*>& anims); void ReadAnimData(FileReference file, std::vector<SHAnimDataHeader> const& headers, std::vector<SHAnimAsset*>& anims);

View File

@ -437,7 +437,7 @@ namespace SHADE
return; return;
} }
if (true) if (genMeta)
{ {
GenerateNewMeta(newPath); GenerateNewMeta(newPath);
} }

View File

@ -22,6 +22,7 @@
#include "Serialization/SHSerializationHelper.hpp" #include "Serialization/SHSerializationHelper.hpp"
#include "Tools/Utilities/SHClipboardUtilities.h" #include "Tools/Utilities/SHClipboardUtilities.h"
#include "SHInspectorCommands.h" #include "SHInspectorCommands.h"
#include "Animation/SHAnimatorComponent.h"
namespace SHADE namespace SHADE
{ {
template<typename T> template<typename T>
@ -574,4 +575,60 @@ namespace SHADE
} }
ImGui::PopID(); ImGui::PopID();
} }
template<>
static void DrawComponent(SHAnimatorComponent* component)
{
if (!component)
return;
ImGui::PushID(SHFamilyID<SHComponent>::GetID<SHAnimatorComponent>());
const auto componentType = rttr::type::get(*component);
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
ImGui::SameLine();
if (ImGui::CollapsingHeader(componentType.get_name().data()))
{
DrawContextMenu(component);
Handle<SHRig> const& rig = component->GetRig();
const auto RIG_NAME = rig ? SHResourceManager::GetAssetName<SHRig>(rig).value_or("") : "";
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Rig", RIG_NAME, [component]()
{
Handle<SHRig> const& rig = component->GetRig();
return SHResourceManager::GetAssetID<SHRig>(rig).value_or(0);
},
[component](AssetID const& id)
{
if (SHAssetManager::GetType(id) != AssetType::MODEL)
{
SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!")
return;
}
component->SetRig(SHResourceManager::LoadOrGet<SHRig>(id));
SHResourceManager::FinaliseChanges();
}, SHDragDrop::DRAG_RESOURCE);
Handle<SHAnimationClip> const& clip = component->GetCurrentClip();
const auto CLIP_NAME = rig ? SHResourceManager::GetAssetName<SHAnimationClip>(clip).value_or("") : "";
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Clip", CLIP_NAME,
[component]()
{
Handle<SHAnimationClip> const& clip = component->GetCurrentClip();
return SHResourceManager::GetAssetID<SHAnimationClip>(clip).value_or(0);
},
[component](AssetID const& id)
{
if (SHAssetManager::GetType(id) != AssetType::MODEL)
{
SHLOG_WARNING("Attempted to assign non mesh asset to Renderable Mesh property!")
return;
}
component->SetClip(SHResourceManager::LoadOrGet<SHAnimationClip>(id));
}, SHDragDrop::DRAG_RESOURCE);
}
else
{
DrawContextMenu(component);
}
ImGui::PopID();
}
} }

View File

@ -27,6 +27,13 @@
namespace SHADE namespace SHADE
{ {
template<typename Component>
void EnsureComponent(EntityID eid)
{
if(SHComponentManager::GetComponent_s<Component>(eid) == nullptr)
SHComponentManager::AddComponent<Component>(eid);
}
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true> template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
bool DrawAddComponentButton(EntityID const& eid) bool DrawAddComponentButton(EntityID const& eid)
{ {
@ -48,9 +55,13 @@ namespace SHADE
return selected; return selected;
} }
template <typename ComponentType, typename EnforcedComponent, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true, std::enable_if_t<std::is_base_of_v<SHComponent, EnforcedComponent>, bool> = true> template <typename ComponentType, typename ... EnforcedComponents>
bool DrawAddComponentWithEnforcedComponentButton(EntityID const& eid) bool DrawAddComponentWithEnforcedComponentButton(EntityID const& eid)
{ {
// Only make sure components are passed here
static_assert(std::is_base_of_v<SHComponent, ComponentType>, "");
//(static_assert(std::is_base_of_v<SHComponent, EnforcedComponents>, ""), ...);
bool selected = false; bool selected = false;
if (!SHComponentManager::HasComponent<ComponentType>(eid)) if (!SHComponentManager::HasComponent<ComponentType>(eid))
{ {
@ -58,9 +69,8 @@ namespace SHADE
if(selected = ImGui::Selectable(std::format("Add {}", componentName).data()); selected) if(selected = ImGui::Selectable(std::format("Add {}", componentName).data()); selected)
{ {
if(SHComponentManager::GetComponent_s<EnforcedComponent>(eid) == nullptr) // Ensure that all required components are present
SHComponentManager::AddComponent<EnforcedComponent>(eid); (EnsureComponent<EnforcedComponents>(eid), ...);
SHComponentManager::AddComponent<ComponentType>(eid); SHComponentManager::AddComponent<ComponentType>(eid);
} }
if(ImGui::IsItemHovered()) if(ImGui::IsItemHovered())
@ -69,9 +79,8 @@ namespace SHADE
ImGui::Text("Adds", componentName); ImGui::SameLine(); ImGui::Text("Adds", componentName); ImGui::SameLine();
ImGui::TextColored(ImGuiColors::green, "%s", componentName); ImGui::SameLine(); ImGui::TextColored(ImGuiColors::green, "%s", componentName); ImGui::SameLine();
ImGui::Text("to this entity", componentName); ImGui::Text("to this entity", componentName);
ImGui::Text("Adds"); ImGui::SameLine(); ImGui::Text("Adds the following components if the entity does not already have it: ");
ImGui::TextColored(ImGuiColors::red, "%s", rttr::type::get<EnforcedComponent>().get_name().data()); ImGui::SameLine(); (ImGui::TextColored(ImGuiColors::red, "%s", rttr::type::get<EnforcedComponents>().get_name().data()), ...);
ImGui::Text("if the entity does not already have it");
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
} }
@ -118,6 +127,10 @@ namespace SHADE
{ {
DrawComponent(renderableComponent); DrawComponent(renderableComponent);
} }
if (auto animatorComponent = SHComponentManager::GetComponent_s<SHAnimatorComponent>(eid))
{
DrawComponent(animatorComponent);
}
if(auto colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(eid)) if(auto colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(eid))
{ {
DrawComponent(colliderComponent); DrawComponent(colliderComponent);
@ -174,6 +187,7 @@ namespace SHADE
DrawAddComponentWithEnforcedComponentButton<SHRigidBodyComponent, SHTransformComponent>(eid); DrawAddComponentWithEnforcedComponentButton<SHRigidBodyComponent, SHTransformComponent>(eid);
DrawAddComponentWithEnforcedComponentButton<SHColliderComponent, SHTransformComponent>(eid); DrawAddComponentWithEnforcedComponentButton<SHColliderComponent, SHTransformComponent>(eid);
DrawAddComponentWithEnforcedComponentButton<SHTextRenderableComponent, SHTransformComponent>(eid); DrawAddComponentWithEnforcedComponentButton<SHTextRenderableComponent, SHTransformComponent>(eid);
DrawAddComponentWithEnforcedComponentButton<SHAnimatorComponent, SHTransformComponent, SHRenderable>(eid);
ImGui::EndMenu(); ImGui::EndMenu();

View File

@ -581,7 +581,11 @@ namespace SHADE
return; return;
// Bind all required objects before drawing // Bind all required objects before drawing
static std::array dynamicOffset{ 0U, static_cast<uint32_t>(boneMatrixData.size() * sizeof(SHMatrix)) }; std::vector<uint32_t> dynamicOffset{ 0 };
if (!boneMatrixData.empty())
{
dynamicOffset.emplace_back(0);
}
cmdBuffer->BeginLabeledSegment("SHBatch for Pipeline #" + std::to_string(pipeline.GetId().Data.Index)); cmdBuffer->BeginLabeledSegment("SHBatch for Pipeline #" + std::to_string(pipeline.GetId().Data.Index));
cmdBuffer->BindPipeline(pipeline); cmdBuffer->BindPipeline(pipeline);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0); cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
@ -598,10 +602,6 @@ namespace SHADE
dynamicOffset dynamicOffset
); );
} }
if (boneMatrixBuffer[frameIndex] && boneFirstIndexBuffer[frameIndex])
{
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::BONE_INDICES, boneFirstIndexBuffer[frameIndex], 0);
}
cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size())); cmdBuffer->DrawMultiIndirect(drawDataBuffer[frameIndex], static_cast<uint32_t>(drawData.size()));
cmdBuffer->EndLabeledSegment(); cmdBuffer->EndLabeledSegment();
} }
@ -648,15 +648,16 @@ namespace SHADE
using PreDefDescLayoutType = SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes; using PreDefDescLayoutType = SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes;
static constexpr uint32_t MATERIAL_DESC_SET_INDEX = 0; static constexpr uint32_t MATERIAL_DESC_SET_INDEX = 0;
// Flags
bool descSetUpdateRequired = false;
/* Create Descriptor Sets if Needed */ /* Create Descriptor Sets if Needed */
PreDefDescLayoutType layoutTypes = {}; PreDefDescLayoutType layoutTypes = {};
if (matPropsData) if (matPropsData)
layoutTypes |= PreDefDescLayoutType::MATERIALS; {
layoutTypes = PreDefDescLayoutType::MATERIALS;
}
if (!boneMatrixData.empty()) if (!boneMatrixData.empty())
layoutTypes |= PreDefDescLayoutType::BONES; {
layoutTypes = PreDefDescLayoutType::MATERIAL_AND_BONES;
}
if (matPropsData || !boneMatrixData.empty()) if (matPropsData || !boneMatrixData.empty())
{ {
@ -699,21 +700,19 @@ namespace SHADE
0, static_cast<uint32_t>(matPropsDataSize) 0, static_cast<uint32_t>(matPropsDataSize)
); );
descSetUpdateRequired = true; // Update the descriptor set buffer
instanceDataDescSet[frameIndex]->UpdateDescriptorSetBuffer
(
MATERIAL_DESC_SET_INDEX,
SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA
);
} }
/* Animation Bone Data */ /* Animation Bone Data */
if (!boneMatrixData.empty()) if (!boneMatrixData.empty())
{ {
// Update GPU Buffers // Update GPU Buffers
const uint32_t BONE_IDX_DATA_BYTES = static_cast<uint32_t>(boneMatrixIndices.size() * sizeof(uint32_t)); const uint32_t BONE_MTX_DATA_BYTES = static_cast<uint32_t>(boneMatrixData.size() * sizeof(SHMatrix));
SHVkUtil::EnsureBufferAndCopyHostVisibleData
(
device, boneFirstIndexBuffer[frameIndex], boneMatrixIndices.data(), BONE_IDX_DATA_BYTES,
BuffUsage::eVertexBuffer,
"Batch Bone Indices Buffer"
);
const uint32_t BONE_MTX_DATA_BYTES = static_cast<uint32_t>(boneMatrixData.size() * sizeof(uint32_t));
SHVkUtil::EnsureBufferAndCopyHostVisibleData SHVkUtil::EnsureBufferAndCopyHostVisibleData
( (
device, boneMatrixBuffer[frameIndex], boneMatrixData.data(), BONE_MTX_DATA_BYTES, device, boneMatrixBuffer[frameIndex], boneMatrixData.data(), BONE_MTX_DATA_BYTES,
@ -728,21 +727,15 @@ namespace SHADE
MATERIAL_DESC_SET_INDEX, MATERIAL_DESC_SET_INDEX,
SHGraphicsConstants::DescriptorSetBindings::PER_INST_BONE_DATA, SHGraphicsConstants::DescriptorSetBindings::PER_INST_BONE_DATA,
bufferList, bufferList,
static_cast<uint32_t>(matPropsDataSize), 0,
static_cast<uint32_t>(boneMatrixData.size() * sizeof(SHMatrix)) static_cast<uint32_t>(boneMatrixData.size() * sizeof(SHMatrix))
); );
descSetUpdateRequired = true;
}
// Build and prepare the descriptor set if necessary
if (descSetUpdateRequired)
{
// Update the descriptor set buffer // Update the descriptor set buffer
instanceDataDescSet[frameIndex]->UpdateDescriptorSetBuffer instanceDataDescSet[frameIndex]->UpdateDescriptorSetBuffer
( (
MATERIAL_DESC_SET_INDEX, MATERIAL_DESC_SET_INDEX,
SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA SHGraphicsConstants::DescriptorSetBindings::PER_INST_BONE_DATA
); );
} }
} }

View File

@ -134,7 +134,6 @@ namespace SHADE
TripleBuffer instancedIntegerBuffer; TripleBuffer instancedIntegerBuffer;
TripleBuffer matPropsBuffer; TripleBuffer matPropsBuffer;
TripleBuffer boneMatrixBuffer; TripleBuffer boneMatrixBuffer;
TripleBuffer boneFirstIndexBuffer;
TripleDescSet instanceDataDescSet; TripleDescSet instanceDataDescSet;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -28,6 +28,13 @@ namespace SHADE
{SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH, 2}, {SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH, 2},
}); });
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING_ANIM)].descMappings.AddMappings
({
{SHPredefinedDescriptorTypes::STATIC_DATA, 0},
{SHPredefinedDescriptorTypes::CAMERA, 1},
{SHPredefinedDescriptorTypes::PER_INSTANCE_ANIM_BATCH, 2},
});
perSystemData[SHUtilities::ConvertEnum(SystemType::TEXT_RENDERING)].descMappings.AddMappings perSystemData[SHUtilities::ConvertEnum(SystemType::TEXT_RENDERING)].descMappings.AddMappings
({ ({
{SHPredefinedDescriptorTypes::STATIC_DATA, 0}, {SHPredefinedDescriptorTypes::STATIC_DATA, 0},
@ -129,14 +136,7 @@ namespace SHADE
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA, .BindPoint = SHGraphicsConstants::DescriptorSetBindings::PER_INST_MATERIAL_DATA,
.DescriptorCount = 1, .DescriptorCount = 1,
}; };
SHVkDescriptorSetLayout::Binding boneDataBinding Handle<SHVkDescriptorSetLayout> materialDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout({ materialDataBinding });
{
.Type = vk::DescriptorType::eStorageBufferDynamic,
.Stage = vk::ShaderStageFlagBits::eVertex,
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::PER_INST_BONE_DATA,
.DescriptorCount = 1,
};
Handle<SHVkDescriptorSetLayout> materialDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout({ materialDataBinding, boneDataBinding });
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, materialDataPerInstanceLayout->GetVkHandle(), "[Descriptor Set Layout] Material Globals"); SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, materialDataPerInstanceLayout->GetVkHandle(), "[Descriptor Set Layout] Material Globals");
// font bitmap data (texture) // font bitmap data (texture)
@ -160,17 +160,16 @@ namespace SHADE
Handle<SHVkDescriptorSetLayout> fontDataDescSetLayout = logicalDevice->CreateDescriptorSetLayout({ fontBitmapBinding, fontMatrixBinding }); Handle<SHVkDescriptorSetLayout> fontDataDescSetLayout = logicalDevice->CreateDescriptorSetLayout({ fontBitmapBinding, fontMatrixBinding });
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, fontDataDescSetLayout->GetVkHandle(), "[Descriptor Set Layout] Font Data"); SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, fontDataDescSetLayout->GetVkHandle(), "[Descriptor Set Layout] Font Data");
// Bone matrix data // For per instance data (transforms, materials, etc.)
SHVkDescriptorSetLayout::Binding boneMatrixBinding SHVkDescriptorSetLayout::Binding boneDataBinding
{ {
.Type = vk::DescriptorType::eStorageBuffer, .Type = vk::DescriptorType::eStorageBufferDynamic,
.Stage = vk::ShaderStageFlagBits::eVertex, .Stage = vk::ShaderStageFlagBits::eVertex,
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::BONE_MATRIX_DATA, .BindPoint = SHGraphicsConstants::DescriptorSetBindings::PER_INST_BONE_DATA,
.DescriptorCount = 1, .DescriptorCount = 1,
}; };
Handle<SHVkDescriptorSetLayout> materialBoneDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout({ materialDataBinding, boneDataBinding });
Handle<SHVkDescriptorSetLayout> boneMatricesDescSetLayout = logicalDevice->CreateDescriptorSetLayout({ boneMatrixBinding }); SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, materialBoneDataPerInstanceLayout->GetVkHandle(), "[Descriptor Set Layout] Material and Bone Globals");
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, boneMatricesDescSetLayout->GetVkHandle(), "[Descriptor Set Layout] Bone Matrix Data");
predefinedLayouts.push_back(staticGlobalLayout); predefinedLayouts.push_back(staticGlobalLayout);
predefinedLayouts.push_back(lightDataDescSetLayout); predefinedLayouts.push_back(lightDataDescSetLayout);
@ -178,7 +177,7 @@ namespace SHADE
predefinedLayouts.push_back(materialDataPerInstanceLayout); predefinedLayouts.push_back(materialDataPerInstanceLayout);
predefinedLayouts.push_back(fontDataDescSetLayout); predefinedLayouts.push_back(fontDataDescSetLayout);
predefinedLayouts.push_back({}); predefinedLayouts.push_back({});
predefinedLayouts.push_back(boneMatricesDescSetLayout); predefinedLayouts.push_back(materialBoneDataPerInstanceLayout);
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING)].descSetLayouts = GetPredefinedDescSetLayouts perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING)].descSetLayouts = GetPredefinedDescSetLayouts
( (
@ -187,6 +186,13 @@ namespace SHADE
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::MATERIALS SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::MATERIALS
); );
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING_ANIM)].descSetLayouts = GetPredefinedDescSetLayouts
(
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::STATIC_DATA |
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::CAMERA |
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::MATERIAL_AND_BONES
);
perSystemData[SHUtilities::ConvertEnum(SystemType::TEXT_RENDERING)].descSetLayouts = GetPredefinedDescSetLayouts perSystemData[SHUtilities::ConvertEnum(SystemType::TEXT_RENDERING)].descSetLayouts = GetPredefinedDescSetLayouts
( (
SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::STATIC_DATA | SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::STATIC_DATA |

View File

@ -23,18 +23,19 @@ namespace SHADE
// This enum is mainly to initialize a bit field to retrieve bit fields from SHPRedefinedData // This enum is mainly to initialize a bit field to retrieve bit fields from SHPRedefinedData
enum class PredefinedDescSetLayoutTypes : uint64_t enum class PredefinedDescSetLayoutTypes : uint64_t
{ {
STATIC_DATA = 0b0000001, STATIC_DATA = 0b00000001,
LIGHTS = 0b0000010, LIGHTS = 0b00000010,
CAMERA = 0b0000100, CAMERA = 0b00000100,
MATERIALS = 0b0001000, MATERIALS = 0b00001000,
FONT = 0b0010000, FONT = 0b00010000,
SHADOW = 0b0100000, SHADOW = 0b00100000,
BONES = 0b1000000, MATERIAL_AND_BONES = 0b01000000
}; };
enum class SystemType enum class SystemType
{ {
BATCHING = 0, BATCHING = 0,
BATCHING_ANIM,
TEXT_RENDERING, TEXT_RENDERING,
RENDER_GRAPH_NODE_COMPUTE, RENDER_GRAPH_NODE_COMPUTE,
NUM_TYPES NUM_TYPES

View File

@ -12,7 +12,7 @@ namespace SHADE
LIGHTS, LIGHTS,
CAMERA, CAMERA,
PER_INSTANCE_BATCH, PER_INSTANCE_BATCH,
BONES, PER_INSTANCE_ANIM_BATCH,
FONT, FONT,
RENDER_GRAPH_RESOURCE, RENDER_GRAPH_RESOURCE,
RENDER_GRAPH_NODE_COMPUTE_RESOURCE, RENDER_GRAPH_NODE_COMPUTE_RESOURCE,

View File

@ -173,7 +173,7 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
static constexpr uint32_t BONE_MATRIX_DATA = 0; static constexpr uint32_t BONE_MATRIX_DATA = 1;
}; };
struct VertexBufferBindings struct VertexBufferBindings

View File

@ -185,7 +185,9 @@ namespace SHADE
} }
else else
{ {
const auto OG_SIZE = vertBoneWeightStorage.size();
vertBoneWeightStorage.resize(vertBoneWeightStorage.size() + addJob.VertexCount); vertBoneWeightStorage.resize(vertBoneWeightStorage.size() + addJob.VertexCount);
std::fill_n(vertBoneWeightStorage.begin() + OG_SIZE, addJob.VertexCount, SHVec4(1.0f, 0.0f, 0.0f, 0.0f));
} }
indexStorage.insert indexStorage.insert
( (

View File

@ -8,12 +8,12 @@
namespace SHADE namespace SHADE
{ {
Handle<SHVkPipeline> SHPipelineLibrary::CreateGraphicsPipelines(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass) noexcept Handle<SHVkPipeline> SHPipelineLibrary::CreateGraphicsPipelines(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass, SHGraphicsPredefinedData::SystemType systemType) noexcept
{ {
SHPipelineLayoutParams params SHPipelineLayoutParams params
{ {
.shaderModules = {vsFsPair.first, vsFsPair.second}, .shaderModules = {vsFsPair.first, vsFsPair.second},
.predefinedDescSetLayouts = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::BATCHING).descSetLayouts .predefinedDescSetLayouts = SHGraphicsPredefinedData::GetSystemData(systemType).descSetLayouts
}; };
// Create the pipeline layout // Create the pipeline layout

View File

@ -3,6 +3,7 @@
#include <unordered_map> #include <unordered_map>
#include "Graphics/Shaders/SHVkShaderModule.h" #include "Graphics/Shaders/SHVkShaderModule.h"
#include "Graphics/Pipeline/SHVkPipeline.h" #include "Graphics/Pipeline/SHVkPipeline.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h"
namespace SHADE namespace SHADE
{ {
@ -32,7 +33,8 @@ namespace SHADE
Handle<SHVkPipeline> CreateGraphicsPipelines ( Handle<SHVkPipeline> CreateGraphicsPipelines (
std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair,
Handle<SHVkRenderpass> renderpass, Handle<SHVkRenderpass> renderpass,
Handle<SHSubpass> subpass Handle<SHSubpass> subpass,
SHGraphicsPredefinedData::SystemType systemType
) noexcept; ) noexcept;
Handle<SHVkPipeline> GetGraphicsPipeline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept; Handle<SHVkPipeline> GetGraphicsPipeline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
bool CheckGraphicsPipelineExistence (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept; bool CheckGraphicsPipelineExistence (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;

View File

@ -583,11 +583,37 @@ namespace SHADE
Handle<SHVkPipeline> pipeline = pipelineLibrary.GetGraphicsPipeline(vsFsPair); Handle<SHVkPipeline> pipeline = pipelineLibrary.GetGraphicsPipeline(vsFsPair);
if (!pipeline) if (!pipeline)
{ {
// default to batching system type
SHGraphicsPredefinedData::SystemType systemType{ SHGraphicsPredefinedData::SystemType::BATCHING };
auto const& REFLECTED_SETS = vsFsPair.first->GetReflectedData().GetDescriptorBindingInfo().GetReflectedSets();
// look for animation set binding in the shader (set 2 binding 1)
for (auto const& set : REFLECTED_SETS)
{
auto const mappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING_ANIM);
// Look for set 2
if (set->set == mappings.at(SHPredefinedDescriptorTypes::PER_INSTANCE_ANIM_BATCH))
{
for (int i = 0; i < set->binding_count; i++)
{
// look for binding 1. if found use BATCHING_ANIM system type
if (set->bindings[i]->binding == SHGraphicsConstants::DescriptorSetBindings::BONE_MATRIX_DATA)
{
systemType = SHGraphicsPredefinedData::SystemType::BATCHING_ANIM;
break;
}
}
break;
}
}
pipeline = pipelineLibrary.CreateGraphicsPipelines pipeline = pipelineLibrary.CreateGraphicsPipelines
( (
vsFsPair, vsFsPair,
renderpass, renderpass,
subpass subpass,
systemType
); );
} }

View File

@ -27,6 +27,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h" #include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
#include "Assets/Asset Types/SHMaterialAsset.h" #include "Assets/Asset Types/SHMaterialAsset.h"
#include "Graphics/MiddleEnd/TextRendering/SHFont.h" #include "Graphics/MiddleEnd/TextRendering/SHFont.h"
#include "Animation/SHAnimationClip.h"
#include "Animation/SHRig.h"
namespace SHADE namespace SHADE
{ {
@ -49,6 +51,8 @@ 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<SHAnimationClip> { using AssetType = SHModelAsset; };
template<> struct SHResourceLoader<SHRig> { using AssetType = SHModelAsset; };
/// <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

@ -40,7 +40,9 @@ namespace SHADE
!std::is_same_v<ResourceType, SHVkShaderModule> && !std::is_same_v<ResourceType, SHVkShaderModule> &&
!std::is_same_v<ResourceType, SHMaterialSpec> && !std::is_same_v<ResourceType, SHMaterialSpec> &&
!std::is_same_v<ResourceType, SHFont> && !std::is_same_v<ResourceType, SHFont> &&
!std::is_same_v<ResourceType, SHMaterial> !std::is_same_v<ResourceType, SHMaterial> &&
!std::is_same_v<ResourceType, SHAnimationClip> &&
!std::is_same_v<ResourceType, SHRig>
) )
{ {
static_assert(true, "Unsupported Resource Type specified for SHResourceManager."); static_assert(true, "Unsupported Resource Type specified for SHResourceManager.");
@ -209,7 +211,9 @@ namespace SHADE
assetData.VertexTangents.data(), assetData.VertexTangents.data(),
assetData.VertexNormals.data(), assetData.VertexNormals.data(),
assetData.Indices.size(), assetData.Indices.size(),
assetData.Indices.data() assetData.Indices.data(),
assetData.VertexBoneIndices.empty() ? nullptr : assetData.VertexBoneIndices.data(),
assetData.VertexBoneWeights.empty() ? nullptr : assetData.VertexBoneWeights.data()
); );
} }
// Textures // Textures
@ -345,5 +349,16 @@ namespace SHADE
return gfxSystem->AddFont(assetData); return gfxSystem->AddFont(assetData);
} }
// Animation Clip and Rig
else if constexpr (std::is_same_v<ResourceType, SHRig>)
{
loadedAssetData.emplace_back(assetId);
return resourceHub.Create<ResourceType>(assetData.rig);
}
else if constexpr (std::is_same_v<ResourceType, SHAnimationClip>)
{
loadedAssetData.emplace_back(assetId);
return resourceHub.Create<ResourceType>(*assetData.anims[0]);
}
} }
} }