Implmented GLTF Compile and Load Overhaul #404
|
@ -1,4 +1,4 @@
|
|||
Start in Fullscreen: false
|
||||
Starting Scene ID: 86098106
|
||||
Starting Scene ID: 91478134
|
||||
Window Size: {x: 1920, y: 1080}
|
||||
Window Title: SHADE Engine
|
|
@ -0,0 +1,3 @@
|
|||
Name: Master
|
||||
ID: 187131295
|
||||
Type: 11
|
|
@ -0,0 +1,3 @@
|
|||
Name: Master.strings
|
||||
ID: 184993030
|
||||
Type: 11
|
|
@ -0,0 +1,3 @@
|
|||
Name: Music
|
||||
ID: 187337426
|
||||
Type: 11
|
|
@ -0,0 +1,3 @@
|
|||
Name: SFX
|
||||
ID: 200039123
|
||||
Type: 11
|
|
@ -0,0 +1,3 @@
|
|||
Name: UI
|
||||
ID: 185075145
|
||||
Type: 11
|
|
@ -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: 57342922
|
||||
data.alpha: 0
|
||||
data.beta: {x: 1, y: 1, z: 1}
|
|
@ -0,0 +1,3 @@
|
|||
Name: AnimatedHomeowner
|
||||
ID: 121518381
|
||||
Type: 7
|
|
@ -0,0 +1,8 @@
|
|||
- VertexShader: 39210065
|
||||
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}
|
|
@ -0,0 +1,3 @@
|
|||
Name: default_racoon
|
||||
ID: 125722190
|
||||
Type: 7
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
Name: MD_HomeownerV2
|
||||
ID: 76586906
|
||||
Type: 4
|
||||
Sub Assets:
|
||||
Name: Cube
|
||||
ID: 148542784
|
||||
Type: 8
|
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,33 @@
|
|||
- EID: 0
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Light Component:
|
||||
Position: {x: 0, y: 0, z: 0}
|
||||
Type: Ambient
|
||||
Direction: {x: 0, y: 0, z: 1}
|
||||
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 1
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 2
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0, z: 0}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 148542784
|
||||
Material: 121518381
|
||||
IsActive: true
|
||||
Animator Component:
|
||||
Rig: 76586906
|
||||
Clip: 76586906
|
||||
IsActive: true
|
||||
Scripts: ~
|
|
@ -0,0 +1,3 @@
|
|||
Name: anim
|
||||
ID: 91478134
|
||||
Type: 5
|
|
@ -62,7 +62,6 @@ if %_e%==3 (goto :done) else (goto :ModelCompiler)
|
|||
echo -----------------------ModelCompiler----------------------------
|
||||
rmdir "Dependencies/ModelCompiler" /S /Q
|
||||
git clone https://github.com/SHADE-DP/ModelCompiler.git "Dependencies/ModelCompiler"
|
||||
git clone https://github.com/SHADE-DP/assimp.git "Dependencies/ModelCompiler/Dependencies/assimp"
|
||||
if %_e%==4 (goto :done) else (goto :spdlog)
|
||||
|
||||
@REM :ktx
|
||||
|
|
|
@ -20,15 +20,14 @@ namespace SHADE
|
|||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHAnimationClip::SHAnimationClip(const SHAnimAsset& asset)
|
||||
: ticksPerSecond { static_cast<int>(asset.ticksPerSecond) }
|
||||
, totalTime { static_cast<float>(asset.duration) / static_cast<int>(asset.ticksPerSecond) }
|
||||
{
|
||||
// Populate keyframes
|
||||
int maxFrames = 0;
|
||||
totalTime = 0.0f;
|
||||
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());
|
||||
|
@ -36,22 +35,31 @@ namespace SHADE
|
|||
// Populate Keyframes
|
||||
for (const auto& posKey : channel.positionKeys)
|
||||
{
|
||||
newChannel.PositionKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ static_cast<int>(posKey.time), posKey.value});
|
||||
newChannel.PositionKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ posKey.time, posKey.value});
|
||||
}
|
||||
for (const auto& rotKey : channel.rotationKeys)
|
||||
{
|
||||
newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame<SHQuaternion>{ static_cast<int>(rotKey.time), rotKey.value});
|
||||
newChannel.RotationKeyFrames.emplace_back(SHAnimationKeyFrame<SHQuaternion>{ rotKey.time, rotKey.value});
|
||||
}
|
||||
for (const auto& scaleKey : channel.scaleKeys)
|
||||
{
|
||||
newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ static_cast<int>(scaleKey.time), scaleKey.value});
|
||||
newChannel.ScaleKeyFrames.emplace_back(SHAnimationKeyFrame<SHVec3>{ scaleKey.time, scaleKey.value });
|
||||
}
|
||||
|
||||
newChannel.MaxFrames = std::max({ newChannel.PositionKeyFrames.size(), newChannel.RotationKeyFrames.size(), newChannel.ScaleKeyFrames.size() });
|
||||
|
||||
// Compute max frames
|
||||
maxFrames = std::max(maxFrames, newChannel.MaxFrames);
|
||||
|
||||
// Compute total time
|
||||
totalTime = std::max({ totalTime, newChannel.PositionKeyFrames.back().TimeStamp, newChannel.RotationKeyFrames.back().TimeStamp, newChannel.ScaleKeyFrames.back().TimeStamp });
|
||||
|
||||
// Insert the channel
|
||||
channels.emplace_back(std::move(newChannel));
|
||||
}
|
||||
|
||||
// Compute fps
|
||||
ticksPerSecond = static_cast<int>(maxFrames / totalTime);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -27,8 +27,8 @@ namespace SHADE
|
|||
template<typename T>
|
||||
struct SHAnimationKeyFrame
|
||||
{
|
||||
int FrameIndex;
|
||||
T Data;
|
||||
float TimeStamp;
|
||||
T Data;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
@ -46,7 +46,6 @@ namespace SHADE
|
|||
/// </summary>
|
||||
struct Channel
|
||||
{
|
||||
std::string Name;
|
||||
std::vector<SHAnimationKeyFrame<SHVec3>> PositionKeyFrames;
|
||||
std::vector<SHAnimationKeyFrame<SHQuaternion>> RotationKeyFrames;
|
||||
std::vector<SHAnimationKeyFrame<SHVec3>> ScaleKeyFrames;
|
||||
|
|
|
@ -89,16 +89,7 @@ namespace SHADE
|
|||
currClip = newClip;
|
||||
secsPerTick = 1.0f / currClip->GetTicksPerSecond();
|
||||
|
||||
// Build channel map
|
||||
channelMap.clear();
|
||||
if (currClip)
|
||||
{
|
||||
for (const auto& channel : currClip->GetChannels())
|
||||
{
|
||||
channelMap.emplace(channel.Name, &channel);
|
||||
}
|
||||
}
|
||||
|
||||
// Set to initial pose
|
||||
if (rig && rig->GetRootNode() && currClip)
|
||||
{
|
||||
updatePoseWithClip(0.0f);
|
||||
|
@ -133,24 +124,23 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHAnimatorComponent::updatePoseWithClip(float poseTime)
|
||||
{
|
||||
// Get closest frame index
|
||||
const int CLOSEST_FRAME_IDX = static_cast<int>(std::floorf(poseTime * currClip->GetTicksPerSecond()));
|
||||
updatePoseWithClip(CLOSEST_FRAME_IDX, poseTime, rig->GetRootNode(), SHMatrix::Identity);
|
||||
updatePoseWithClip(poseTime, rig->GetRootNode(), SHMatrix::Identity);
|
||||
}
|
||||
|
||||
void SHAnimatorComponent::updatePoseWithClip(int closestFrameIndex, float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix)
|
||||
void SHAnimatorComponent::updatePoseWithClip(float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix)
|
||||
{
|
||||
// Check if there is a channel for this node
|
||||
const std::string& BONE_NAME = rig->GetName(node);
|
||||
SHMatrix transformMatrix = node->TransformMatrix;
|
||||
if (channelMap.contains(BONE_NAME))
|
||||
const int BONE_IDX = rig->GetNodeIndex(node);
|
||||
const auto& CHANNELS = currClip->GetChannels();
|
||||
if (BONE_IDX < CHANNELS.size())
|
||||
{
|
||||
const auto CHANNEL = channelMap[BONE_NAME];
|
||||
const auto& CHANNEL = CHANNELS[BONE_IDX];
|
||||
transformMatrix = SHMatrix::Transform
|
||||
(
|
||||
getInterpolatedValue(CHANNEL->PositionKeyFrames, closestFrameIndex, poseTime),
|
||||
getInterpolatedValue(CHANNEL->RotationKeyFrames, closestFrameIndex, poseTime),
|
||||
getInterpolatedValue(CHANNEL->ScaleKeyFrames, closestFrameIndex, poseTime)
|
||||
getInterpolatedValue(CHANNEL.PositionKeyFrames, poseTime),
|
||||
getInterpolatedValue(CHANNEL.RotationKeyFrames, poseTime),
|
||||
getInterpolatedValue(CHANNEL.ScaleKeyFrames, poseTime)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -168,7 +158,7 @@ namespace SHADE
|
|||
// Apply pose to children
|
||||
for (auto& child : node->Children)
|
||||
{
|
||||
updatePoseWithClip(closestFrameIndex, poseTime, child, transformMatrix);
|
||||
updatePoseWithClip(poseTime, child, transformMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,16 +134,14 @@ namespace SHADE
|
|||
float secsPerTick = 0.0f;
|
||||
// Buffer
|
||||
std::vector<SHMatrix> boneMatrices;
|
||||
// Caches
|
||||
std::unordered_map<std::string, const SHAnimationClip::Channel*> channelMap;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void updatePoseWithClip(float poseTime);
|
||||
void updatePoseWithClip(int closestFrameIndex, float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix);
|
||||
void updatePoseWithClip(float poseTime, Handle<SHRigNode> node, const SHMatrix& parentMatrix);
|
||||
template<typename T>
|
||||
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime);
|
||||
T getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, float poseTime);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* RTTR */
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace SHADE
|
|||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
template<typename T>
|
||||
T SHAnimatorComponent::getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, int closestFrameIndex, float poseTime)
|
||||
T SHAnimatorComponent::getInterpolatedValue(const std::vector<SHAnimationKeyFrame<T>>& keyframes, 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.");
|
||||
|
@ -38,11 +38,11 @@ namespace SHADE
|
|||
{
|
||||
const auto& KEYFRAME = *iter;
|
||||
|
||||
if (KEYFRAME.FrameIndex <= closestFrameIndex)
|
||||
if (KEYFRAME.TimeStamp <= poseTime)
|
||||
{
|
||||
firstKeyFrame = iter;
|
||||
}
|
||||
else // KEYFRAME.FrameIndex > closestFrameIndex
|
||||
else // KEYFRAME.FrameIndex > poseTime
|
||||
{
|
||||
nextKeyFrame = iter;
|
||||
break;
|
||||
|
@ -66,8 +66,8 @@ namespace SHADE
|
|||
}
|
||||
|
||||
// Get interpolated vector
|
||||
const float PREV_FRAME_TIME = firstKeyFrame->FrameIndex * secsPerTick;
|
||||
const float NEXT_FRAME_TIME = nextKeyFrame->FrameIndex * secsPerTick;
|
||||
const float PREV_FRAME_TIME = firstKeyFrame->TimeStamp;
|
||||
const float NEXT_FRAME_TIME = nextKeyFrame->TimeStamp;
|
||||
const float NORMALISED_TIME = (poseTime - PREV_FRAME_TIME) / (NEXT_FRAME_TIME - PREV_FRAME_TIME);
|
||||
|
||||
if constexpr (std::is_same_v<T, SHQuaternion>)
|
||||
|
|
|
@ -120,8 +120,10 @@ namespace SHADE
|
|||
|
||||
// Fill the node with data
|
||||
const auto& NODE_DATA = asset.nodeDataCollection.at(sourceNode->idRef);
|
||||
newNode->OffsetMatrix = SHMatrix::Transpose(NODE_DATA.offset);
|
||||
newNode->TransformMatrix = SHMatrix::Transpose(NODE_DATA.transform);
|
||||
//newNode->OffsetMatrix = SHMatrix::Transpose(NODE_DATA.inverseBindMatrix);
|
||||
//newNode->TransformMatrix = SHMatrix::Transpose(NODE_DATA.transform);
|
||||
newNode->OffsetMatrix = NODE_DATA.inverseBindMatrix;
|
||||
newNode->TransformMatrix = NODE_DATA.transform;
|
||||
|
||||
// Populate maps
|
||||
if (!NODE_DATA.name.empty())
|
||||
|
|
|
@ -18,71 +18,61 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
enum class SHAnimationBehaviour : uint8_t
|
||||
{
|
||||
DEFAULT = 0x0,
|
||||
CONSTANT = 0x1,
|
||||
LINEAR = 0x2,
|
||||
REPEAT = 0x3
|
||||
};
|
||||
enum class AnimationInterpolation : uint8_t
|
||||
{
|
||||
DEFAULT = 0x1,
|
||||
LINEAR = 0x1,
|
||||
STEP = 0x2,
|
||||
CUBICSPLINE = 0x3
|
||||
};
|
||||
|
||||
// Smallest data containers
|
||||
struct PositionKey
|
||||
{
|
||||
float time;
|
||||
SHVec3 value;
|
||||
};
|
||||
|
||||
struct RotationKey
|
||||
{
|
||||
float time;
|
||||
SHVec4 value;
|
||||
};
|
||||
|
||||
struct ScaleKey
|
||||
{
|
||||
float time;
|
||||
SHVec3 value;
|
||||
};
|
||||
// Base
|
||||
struct KeyBase
|
||||
{
|
||||
float time;
|
||||
};
|
||||
|
||||
// Smallest data containers
|
||||
struct PositionKey :KeyBase
|
||||
{
|
||||
SHVec3 value;
|
||||
};
|
||||
|
||||
struct RotationKey : KeyBase
|
||||
{
|
||||
SHVec4 value;
|
||||
};
|
||||
|
||||
struct ScaleKey :KeyBase
|
||||
{
|
||||
SHVec3 value;
|
||||
};
|
||||
|
||||
// Headers for read/write
|
||||
struct SHAnimNodeInfo
|
||||
{
|
||||
uint32_t charCount;
|
||||
uint32_t posKeyCount;
|
||||
uint32_t rotKeyCount;
|
||||
uint32_t scaKeyCount;
|
||||
};
|
||||
|
||||
struct SHAnimDataHeader
|
||||
{
|
||||
uint32_t charCount;
|
||||
uint32_t animNodeCount;
|
||||
std::vector<SHAnimNodeInfo> nodeHeaders;
|
||||
uint32_t animNodeCount;
|
||||
uint32_t frameCount;
|
||||
};
|
||||
|
||||
// Main data containers
|
||||
struct SHAnimData
|
||||
struct SHAnimNode
|
||||
{
|
||||
std::string name;
|
||||
SHAnimationBehaviour pre;
|
||||
SHAnimationBehaviour post;
|
||||
|
||||
std::vector<PositionKey> positionKeys;
|
||||
std::vector<RotationKey> rotationKeys;
|
||||
std::vector<ScaleKey> scaleKeys;
|
||||
AnimationInterpolation interpolation;
|
||||
|
||||
std::vector<PositionKey> positionKeys{};
|
||||
std::vector<RotationKey> rotationKeys{};
|
||||
std::vector<ScaleKey> scaleKeys{};
|
||||
};
|
||||
|
||||
struct SH_API SHAnimAsset : SHAssetData
|
||||
struct SH_API SHAnimAsset final : SHAssetData
|
||||
{
|
||||
std::string name;
|
||||
|
||||
double duration;
|
||||
double ticksPerSecond;
|
||||
double duration{};
|
||||
double ticksPerSecond{};
|
||||
|
||||
std::vector<SHAnimData> nodeChannels;
|
||||
//std::vector<aiMeshAnim*> meshChannels;
|
||||
//std::vector<aiMeshMorphAnim*> morphMeshChannels;
|
||||
std::vector<SHAnimNode> nodeChannels{};
|
||||
};
|
||||
}
|
|
@ -19,45 +19,28 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
constexpr int BONE_INDEX_ALIGHTMENT = 4;
|
||||
|
||||
struct SHMeshDataHeader
|
||||
{
|
||||
uint32_t vertexCount;
|
||||
uint32_t indexCount;
|
||||
uint32_t charCount;
|
||||
uint32_t boneCount;
|
||||
};
|
||||
|
||||
struct MeshBoneInfo
|
||||
{
|
||||
uint32_t charCount;
|
||||
uint32_t weightCount; // Size should be same as boneCount
|
||||
};
|
||||
|
||||
struct BoneWeight
|
||||
{
|
||||
uint32_t index;
|
||||
float weight;
|
||||
};
|
||||
|
||||
struct MeshBone
|
||||
{
|
||||
std::string name;
|
||||
SHMatrix offset;
|
||||
std::vector<BoneWeight> weights;
|
||||
bool hasWeights;
|
||||
};
|
||||
|
||||
struct SH_API SHMeshAsset : SHAssetData
|
||||
{
|
||||
std::string name;
|
||||
std::vector<SHVec3> VertexPositions;
|
||||
std::vector<SHVec3> VertexTangents;
|
||||
std::vector<SHVec3> VertexNormals;
|
||||
std::vector<SHVec2> VertexTexCoords;
|
||||
std::vector<uint32_t> Indices;
|
||||
std::vector<SHVec4U> VertexBoneIndices;
|
||||
std::vector<SHVec4> VertexBoneWeights;
|
||||
std::vector<SHVec3> VertexPositions{};
|
||||
std::vector<SHVec3> VertexTangents{};
|
||||
std::vector<SHVec3> VertexNormals{};
|
||||
std::vector<SHVec2> VertexTexCoords{};
|
||||
std::vector<uint32_t> Indices{};
|
||||
|
||||
//Variables
|
||||
std::vector<SHVec4> VertexBoneWeights{};
|
||||
std::vector<SHVec4U> VertexBoneIndices{};
|
||||
|
||||
uint32_t BoneCount;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHRigAsset.h"
|
||||
|
||||
#include <queue>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
SHRigAsset::~SHRigAsset()
|
||||
{
|
||||
if (root != nullptr)
|
||||
delete[] root;
|
||||
delete[] root;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,31 +17,43 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
using NodeDataFlag = unsigned char;
|
||||
|
||||
constexpr NodeDataFlag NODE_DATA_ROTATION = 0b0001;
|
||||
constexpr NodeDataFlag NODE_DATA_SCALE = 0b0010;
|
||||
constexpr NodeDataFlag NODE_DATA_TRANSLATION = 0b0100;
|
||||
constexpr NodeDataFlag NODE_DATA_MATRIX = 0b1000;
|
||||
|
||||
constexpr size_t NODE_COMPONENT_COUNT_ROTATION{ 4 };
|
||||
constexpr size_t NODE_COMPONENT_COUNT_SCALE{ 3 };
|
||||
constexpr size_t NODE_COMPONENT_COUNT_TRANSLATION{ 3 };
|
||||
constexpr size_t NODE_COMPONENT_COUNT_MATRIX{ 16 };
|
||||
|
||||
struct SHRigDataHeader
|
||||
{
|
||||
uint32_t nodeCount;
|
||||
std::vector<uint32_t> charCounts;
|
||||
uint32_t nodeCount{};
|
||||
uint32_t startNode{};
|
||||
std::vector<uint32_t> charCounts{};
|
||||
};
|
||||
|
||||
struct SHRigNodeData
|
||||
{
|
||||
std::string name;
|
||||
SHMatrix transform;
|
||||
SHMatrix offset;
|
||||
SHMatrix transform;
|
||||
SHMatrix inverseBindMatrix;
|
||||
};
|
||||
|
||||
struct SHRigNodeAsset
|
||||
{
|
||||
uint32_t idRef;
|
||||
std::vector<SHRigNodeAsset*> children;
|
||||
};
|
||||
struct SHRigNodeAsset
|
||||
{
|
||||
uint32_t idRef;
|
||||
std::vector<SHRigNodeAsset*> children;
|
||||
};
|
||||
|
||||
struct SH_API SHRigAsset : SHAssetData
|
||||
{
|
||||
~SHRigAsset();
|
||||
|
||||
SHRigDataHeader header;
|
||||
std::vector<SHRigNodeData> nodeDataCollection;
|
||||
SHRigNodeAsset* root;
|
||||
std::vector<SHRigNodeData> nodeDataCollection{};
|
||||
SHRigNodeAsset* root;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/******************************************************************************
|
||||
* \file SHAudioBankAsset.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 31 January 2023
|
||||
* \brief
|
||||
*
|
||||
* \copyright 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 "SHAssetData.h"
|
||||
#include <string>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHAudioBankAsset : SHAssetData
|
||||
{
|
||||
std::string name;
|
||||
std::string path;
|
||||
};
|
||||
}
|
|
@ -17,6 +17,52 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
inline SHVec3 GetVec3FromVector(std::vector<double> const& vec)
|
||||
{
|
||||
assert(vec.size() == NODE_COMPONENT_COUNT_TRANSLATION);
|
||||
|
||||
return SHVec3{
|
||||
static_cast<float>(vec[0]),
|
||||
static_cast<float>(vec[1]),
|
||||
static_cast<float>(vec[2])
|
||||
};
|
||||
}
|
||||
|
||||
inline SHVec4 GetVec4FromVector(std::vector<double> const& vec)
|
||||
{
|
||||
assert(vec.size() == NODE_COMPONENT_COUNT_ROTATION);
|
||||
return SHVec4{
|
||||
static_cast<float>(vec[0]),
|
||||
static_cast<float>(vec[1]),
|
||||
static_cast<float>(vec[2]),
|
||||
static_cast<float>(vec[3])
|
||||
};
|
||||
}
|
||||
|
||||
inline SHMatrix GetMatrixFromVector(std::vector<double> const& vec)
|
||||
{
|
||||
assert(vec.size() == NODE_COMPONENT_COUNT_MATRIX);
|
||||
|
||||
return SHMatrix{
|
||||
static_cast<float>(vec[0]),
|
||||
static_cast<float>(vec[1]),
|
||||
static_cast<float>(vec[2]),
|
||||
static_cast<float>(vec[3]),
|
||||
static_cast<float>(vec[4]),
|
||||
static_cast<float>(vec[5]),
|
||||
static_cast<float>(vec[6]),
|
||||
static_cast<float>(vec[7]),
|
||||
static_cast<float>(vec[8]),
|
||||
static_cast<float>(vec[9]),
|
||||
static_cast<float>(vec[10]),
|
||||
static_cast<float>(vec[11]),
|
||||
static_cast<float>(vec[12]),
|
||||
static_cast<float>(vec[13]),
|
||||
static_cast<float>(vec[14]),
|
||||
static_cast<float>(vec[15])
|
||||
};
|
||||
}
|
||||
|
||||
void SHModelLoader::ReadHeaders(FileReference file, SHModelAsset& asset)
|
||||
{
|
||||
file.read(
|
||||
|
@ -36,29 +82,12 @@ namespace SHADE
|
|||
if (asset.header.animCount > 0)
|
||||
{
|
||||
asset.animHeaders.resize(asset.header.animCount);
|
||||
for (auto i {0}; i < asset.header.animCount; ++i)
|
||||
for (auto& animHeader : asset.animHeaders)
|
||||
{
|
||||
auto& animHeader = asset.animHeaders[i];
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&animHeader.charCount),
|
||||
sizeof(uint32_t)
|
||||
reinterpret_cast<char*>(&animHeader),
|
||||
sizeof(animHeader)
|
||||
);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&animHeader.animNodeCount),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
animHeader.nodeHeaders.resize(animHeader.animNodeCount);
|
||||
for (auto j {0}; j < animHeader.animNodeCount; ++j)
|
||||
{
|
||||
auto& nodeHeader = animHeader.nodeHeaders[j];
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&nodeHeader),
|
||||
sizeof(SHAnimNodeInfo)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,53 +103,63 @@ namespace SHADE
|
|||
ReadRigHeader(file, asset.rig.header);
|
||||
ReadRigData(file, asset.rig.header, asset.rig.nodeDataCollection);
|
||||
ReadRigTree(file, asset.rig.header, asset.rig.root);
|
||||
|
||||
for (auto& mesh : asset.meshes)
|
||||
{
|
||||
mesh->BoneCount = asset.rig.nodeDataCollection.size();
|
||||
}
|
||||
|
||||
//BuildTransformMatrices(asset.rig);
|
||||
}
|
||||
}
|
||||
|
||||
void SHModelLoader::ReadAnimNode(FileReference file, SHAnimNodeInfo const& info, SHAnimData& data)
|
||||
void SHModelLoader::ReadAnimNode(FileReference file, uint32_t frameCount, SHAnimNode& data)
|
||||
{
|
||||
data.name.resize(info.charCount);
|
||||
file.read(
|
||||
data.name.data(),
|
||||
info.charCount
|
||||
reinterpret_cast<char*>(&data.interpolation),
|
||||
1
|
||||
);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&data.pre),
|
||||
sizeof(SHAnimationBehaviour)
|
||||
);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&data.post),
|
||||
sizeof(SHAnimationBehaviour)
|
||||
);
|
||||
|
||||
uint32_t keySize {0};
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&keySize),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
data.positionKeys.resize(keySize);
|
||||
data.rotationKeys.resize(keySize);
|
||||
data.scaleKeys.resize(keySize);
|
||||
data.positionKeys.resize(frameCount);
|
||||
data.rotationKeys.resize(frameCount);
|
||||
data.scaleKeys.resize(frameCount);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(data.positionKeys.data()),
|
||||
sizeof(PositionKey) * keySize
|
||||
sizeof(PositionKey) * frameCount
|
||||
);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(data.rotationKeys.data()),
|
||||
sizeof(RotationKey) * keySize
|
||||
sizeof(RotationKey) * frameCount
|
||||
);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(data.scaleKeys.data()),
|
||||
sizeof(ScaleKey) * keySize
|
||||
sizeof(ScaleKey) * frameCount
|
||||
);
|
||||
}
|
||||
|
||||
void SHModelLoader::BuildTransformMatrices(SHRigAsset& rig)
|
||||
{
|
||||
std::queue<SHRigNodeAsset const*> nodeQueue;
|
||||
nodeQueue.push(rig.root);
|
||||
|
||||
while(!nodeQueue.empty())
|
||||
{
|
||||
auto& current = nodeQueue.front();
|
||||
nodeQueue.pop();
|
||||
auto& parentData {rig.nodeDataCollection[current->idRef]};
|
||||
|
||||
for (auto const& child: current->children)
|
||||
{
|
||||
nodeQueue.push(child);
|
||||
auto& childData {rig.nodeDataCollection[child->idRef]};
|
||||
childData.transform = childData.transform * parentData.transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHModelLoader::ReadRigHeader(FileReference file, SHRigDataHeader& header)
|
||||
{
|
||||
file.read(
|
||||
|
@ -128,6 +167,11 @@ namespace SHADE
|
|||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&header.startNode),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
header.charCounts.resize(header.nodeCount);
|
||||
file.read(
|
||||
reinterpret_cast<char*>(header.charCounts.data()),
|
||||
|
@ -141,21 +185,72 @@ namespace SHADE
|
|||
|
||||
for (auto i {0}; i < header.nodeCount; ++i)
|
||||
{
|
||||
data[i].name.resize(header.charCounts[i]);
|
||||
auto& node = data[i];
|
||||
node.name.resize(header.charCounts[i]);
|
||||
file.read(
|
||||
data[i].name.data(),
|
||||
node.name.data(),
|
||||
header.charCounts[i]
|
||||
);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&data[i].transform),
|
||||
reinterpret_cast<char*>(&node.inverseBindMatrix),
|
||||
sizeof(SHMatrix)
|
||||
);
|
||||
node.inverseBindMatrix = node.inverseBindMatrix;
|
||||
|
||||
NodeDataFlag flag;
|
||||
file.get(reinterpret_cast<char&>(flag));
|
||||
|
||||
SHVec3 scale{ SHVec3::One }, translation{ SHVec3::Zero };
|
||||
SHVec4 rotation{ SHVec4::UnitW };
|
||||
SHMatrix matrix{ SHMatrix::Identity };
|
||||
std::vector<double> carrier;
|
||||
|
||||
if (flag & NODE_DATA_ROTATION)
|
||||
{
|
||||
carrier.resize(NODE_COMPONENT_COUNT_ROTATION);
|
||||
file.read(
|
||||
reinterpret_cast<char*>(carrier.data()),
|
||||
sizeof(double) * NODE_COMPONENT_COUNT_ROTATION
|
||||
);
|
||||
rotation = GetVec4FromVector(carrier);
|
||||
}
|
||||
|
||||
if (flag & NODE_DATA_SCALE)
|
||||
{
|
||||
carrier.resize(NODE_COMPONENT_COUNT_SCALE);
|
||||
file.read(
|
||||
reinterpret_cast<char*>(carrier.data()),
|
||||
sizeof(double) * NODE_COMPONENT_COUNT_SCALE
|
||||
);
|
||||
scale = GetVec3FromVector(carrier);
|
||||
}
|
||||
|
||||
if (flag & NODE_DATA_TRANSLATION)
|
||||
{
|
||||
carrier.resize(NODE_COMPONENT_COUNT_TRANSLATION);
|
||||
file.read(
|
||||
reinterpret_cast<char*>(carrier.data()),
|
||||
sizeof(double) * NODE_COMPONENT_COUNT_TRANSLATION
|
||||
);
|
||||
translation = GetVec3FromVector(carrier);
|
||||
}
|
||||
|
||||
if (flag & NODE_DATA_MATRIX)
|
||||
{
|
||||
carrier.resize(NODE_COMPONENT_COUNT_MATRIX);
|
||||
file.read(
|
||||
reinterpret_cast<char*>(carrier.data()),
|
||||
sizeof(double) * NODE_COMPONENT_COUNT_MATRIX
|
||||
);
|
||||
matrix = GetMatrixFromVector(carrier);
|
||||
}
|
||||
|
||||
//matrix *= SHMatrix::Transform(translation, rotation, scale);
|
||||
matrix *= SHMatrix::Translate(translation) * SHMatrix::Rotate(rotation) * SHMatrix::Scale(scale);
|
||||
node.transform = matrix;
|
||||
//node.transform = SHMatrix::Inverse(node.inverseBindMatrix);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&data[i].offset),
|
||||
sizeof(SHMatrix)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,8 +294,6 @@ namespace SHADE
|
|||
nodeQueue.emplace(depthPtr++, depthTempPtr++);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] dst;
|
||||
}
|
||||
|
||||
void SHModelLoader::ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers,
|
||||
|
@ -221,7 +314,6 @@ namespace SHADE
|
|||
data.VertexNormals.resize(header.vertexCount);
|
||||
data.VertexTexCoords.resize(header.vertexCount);
|
||||
data.Indices.resize(header.indexCount);
|
||||
data.BoneCount = header.boneCount;
|
||||
|
||||
file.read(data.name.data(), header.charCount);
|
||||
file.read(reinterpret_cast<char*>(data.VertexPositions.data()), vertexVec3Byte);
|
||||
|
@ -230,48 +322,20 @@ namespace SHADE
|
|||
file.read(reinterpret_cast<char*>(data.VertexTexCoords.data()), vertexVec2Byte);
|
||||
file.read(reinterpret_cast<char*>(data.Indices.data()), sizeof(uint32_t) * header.indexCount);
|
||||
|
||||
if (header.boneCount)
|
||||
if (header.hasWeights)
|
||||
{
|
||||
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));
|
||||
|
||||
bone.weights.resize(info.weightCount);
|
||||
file.read(reinterpret_cast<char*>(bone.weights.data()), sizeof(BoneWeight) * info.weightCount);
|
||||
}
|
||||
|
||||
data.VertexBoneIndices.resize(header.vertexCount);
|
||||
data.VertexBoneWeights.resize(header.vertexCount);
|
||||
|
||||
for (uint32_t boneIndex{0}; boneIndex < bones.size(); ++boneIndex)
|
||||
{
|
||||
auto const& bone = bones[boneIndex];
|
||||
for (auto const& weight : bone.weights)
|
||||
{
|
||||
auto& boneIndices = data.VertexBoneIndices[weight.index];
|
||||
auto& boneWeight = data.VertexBoneWeights[weight.index];
|
||||
file.read(
|
||||
reinterpret_cast<char*>(data.VertexBoneWeights.data()),
|
||||
sizeof(SHVec4) * header.vertexCount
|
||||
);
|
||||
|
||||
for (auto j{0}; j < BONE_INDEX_ALIGHTMENT; ++j)
|
||||
{
|
||||
if (boneWeight[j] == 0.f)
|
||||
{
|
||||
boneIndices[j] = boneIndex;
|
||||
boneWeight[j] = weight.weight;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
file.read(
|
||||
reinterpret_cast<char*>(data.VertexBoneIndices.data()),
|
||||
sizeof(SHVec4U) * header.vertexCount
|
||||
);
|
||||
}
|
||||
|
||||
meshes[i] = &data;
|
||||
|
@ -306,7 +370,7 @@ namespace SHADE
|
|||
animAsset.nodeChannels.resize(header.animNodeCount);
|
||||
for (auto i {0}; i < header.animNodeCount; ++i)
|
||||
{
|
||||
ReadAnimNode(file, header.nodeHeaders[i], animAsset.nodeChannels[i]);
|
||||
ReadAnimNode(file, header.frameCount, animAsset.nodeChannels[i]);
|
||||
}
|
||||
|
||||
anims[i] = &animAsset;
|
||||
|
|
|
@ -20,7 +20,6 @@ namespace SHADE
|
|||
{
|
||||
using FileReference = std::ifstream&;
|
||||
|
||||
void ReadAnimNode(FileReference file, SHAnimNodeInfo const& info, SHAnimData& data);
|
||||
|
||||
void ReadRigHeader(FileReference file, SHRigDataHeader& header);
|
||||
void ReadRigData(FileReference file, SHRigDataHeader const& header, std::vector<SHRigNodeData>& data);
|
||||
|
@ -28,6 +27,9 @@ namespace SHADE
|
|||
|
||||
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 ReadAnimNode(FileReference file, uint32_t frameCount, SHAnimNode& data);
|
||||
|
||||
void BuildTransformMatrices(SHRigAsset& rig);
|
||||
|
||||
void ReadHeaders(FileReference file, SHModelAsset& asset);
|
||||
void ReadData(FileReference file, SHModelAsset& asset);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "Assets/Asset Types/SHSceneAsset.h"
|
||||
#include "Assets/Asset Types/SHPrefabAsset.h"
|
||||
#include "Assets/Asset Types/SHMaterialAsset.h"
|
||||
#include "Assets/Asset Types/SHAudioBankAsset.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
@ -22,6 +23,14 @@ namespace SHADE
|
|||
{
|
||||
SHAssetData* SHTextBasedLoader::Load(AssetPath path)
|
||||
{
|
||||
if (path.extension().string() == AUDIO_BANK_EXTENSION)
|
||||
{
|
||||
auto data = new SHAudioBankAsset();
|
||||
data->name = path.stem().string();
|
||||
data->path = path.string();
|
||||
return data;
|
||||
}
|
||||
|
||||
std::ifstream file{ path, std::ios::in };
|
||||
|
||||
if (!file.is_open())
|
||||
|
|
|
@ -56,6 +56,7 @@ enum class AssetType : AssetTypeMeta
|
|||
MESH,
|
||||
SCRIPT,
|
||||
FONT,
|
||||
AUDIO_BANK,
|
||||
MAX_COUNT
|
||||
};
|
||||
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
|
||||
|
@ -83,6 +84,7 @@ constexpr std::string_view MATERIAL_FOLDER{ "/Materials/" };
|
|||
constexpr std::string_view META_EXTENSION {".shmeta"};
|
||||
constexpr std::string_view AUDIO_EXTENSION {".ogg"};
|
||||
constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"};
|
||||
constexpr std::string_view AUDIO_BANK_EXTENSION {".bank"};
|
||||
constexpr std::string_view SHADER_EXTENSION{ ".shshader" };
|
||||
constexpr std::string_view SHADER_BUILT_IN_EXTENSION{ ".shshaderb" };
|
||||
constexpr std::string_view FONT_EXTENSION{ ".shfont" };
|
||||
|
@ -105,10 +107,10 @@ constexpr std::string_view EXTENSIONS[] = {
|
|||
"dummy",
|
||||
SCRIPT_EXTENSION,
|
||||
FONT_EXTENSION,
|
||||
AUDIO_WAV_EXTENSION,
|
||||
AUDIO_BANK_EXTENSION
|
||||
};
|
||||
|
||||
constexpr size_t EXTENSIONS_COUNT{ 11 };
|
||||
constexpr size_t EXTENSIONS_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
|
||||
|
||||
// EXTERNAL EXTENSIONS
|
||||
constexpr std::string_view GLSL_EXTENSION{ ".glsl" };
|
||||
|
|
|
@ -445,6 +445,10 @@ namespace SHADE
|
|||
fontPath += FONT_EXTENSION;
|
||||
newPath = fontPath;
|
||||
}
|
||||
else if (ext == AUDIO_BANK_EXTENSION.data())
|
||||
{
|
||||
newPath = path.string();
|
||||
}
|
||||
else
|
||||
{
|
||||
SHLOG_WARNING("[Asset Manager] File Type compilation not yet Implemented: {}", path.string());
|
||||
|
@ -528,6 +532,7 @@ namespace SHADE
|
|||
loaders[static_cast<size_t>(AssetType::MESH)] = nullptr;
|
||||
loaders[static_cast<size_t>(AssetType::SCRIPT)] = nullptr;
|
||||
loaders[static_cast<size_t>(AssetType::FONT)] = dynamic_cast<SHAssetLoader*>(new SHFontLoader());
|
||||
loaders[static_cast<size_t>(AssetType::AUDIO_BANK)] = loaders[static_cast<size_t>(AssetType::SCENE)];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -696,6 +701,20 @@ namespace SHADE
|
|||
|
||||
return newAsset.id;
|
||||
}
|
||||
else if (ext == AUDIO_BANK_EXTENSION)
|
||||
{
|
||||
SHAsset newAsset{
|
||||
path.stem().string(),
|
||||
GenerateAssetID(AssetType::AUDIO_BANK),
|
||||
AssetType::AUDIO_BANK,
|
||||
path,
|
||||
false
|
||||
};
|
||||
assetCollection.emplace(newAsset.id, newAsset);
|
||||
SHAssetMetaHandler::WriteMetaData(newAsset);
|
||||
|
||||
return newAsset.id;
|
||||
}
|
||||
else if(ext == MATERIAL_EXTENSION)
|
||||
{
|
||||
SHAsset newAsset{
|
||||
|
|
|
@ -162,6 +162,7 @@ namespace SHADE
|
|||
{
|
||||
assetCollection.emplace(asset.id, asset);
|
||||
}
|
||||
|
||||
if (file.name == asset.name)
|
||||
{
|
||||
AssetPath path{ file.path };
|
||||
|
|
Loading…
Reference in New Issue