Implmented GLTF Compile and Load Overhaul #404

Merged
XiaoQiDigipen merged 17 commits from SP3-13-Assets-Manager into main 2023-03-07 23:27:01 +08:00
42 changed files with 4111 additions and 532 deletions

View File

@ -1,4 +1,4 @@
Start in Fullscreen: false Start in Fullscreen: false
Starting Scene ID: 86098106 Starting Scene ID: 91478134
Window Size: {x: 1920, y: 1080} Window Size: {x: 1920, y: 1080}
Window Title: SHADE Engine Window Title: SHADE Engine

View File

@ -0,0 +1,3 @@
Name: Master
ID: 187131295
Type: 11

View File

@ -0,0 +1,3 @@
Name: Master.strings
ID: 184993030
Type: 11

View File

@ -0,0 +1,3 @@
Name: Music
ID: 187337426
Type: 11

View File

@ -0,0 +1,3 @@
Name: SFX
ID: 200039123
Type: 11

View File

@ -0,0 +1,3 @@
Name: UI
ID: 185075145
Type: 11

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: 57342922
data.alpha: 0
data.beta: {x: 1, y: 1, z: 1}

View File

@ -0,0 +1,3 @@
Name: AnimatedHomeowner
ID: 121518381
Type: 7

View File

@ -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}

View File

@ -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.

View File

@ -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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

33
Assets/Scenes/anim.shade Normal file
View File

@ -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: ~

View File

@ -0,0 +1,3 @@
Name: anim
ID: 91478134
Type: 5

View File

@ -62,7 +62,6 @@ if %_e%==3 (goto :done) else (goto :ModelCompiler)
echo -----------------------ModelCompiler---------------------------- echo -----------------------ModelCompiler----------------------------
rmdir "Dependencies/ModelCompiler" /S /Q rmdir "Dependencies/ModelCompiler" /S /Q
git clone https://github.com/SHADE-DP/ModelCompiler.git "Dependencies/ModelCompiler" 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) if %_e%==4 (goto :done) else (goto :spdlog)
@REM :ktx @REM :ktx

View File

@ -20,15 +20,14 @@ 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) / static_cast<int>(asset.ticksPerSecond) }
{ {
// Populate keyframes // Populate keyframes
int maxFrames = 0;
totalTime = 0.0f;
for (const auto& channel : asset.nodeChannels) for (const auto& channel : asset.nodeChannels)
{ {
// Create a channel // Create a channel
Channel newChannel; Channel newChannel;
newChannel.Name = std::string(channel.name);
newChannel.PositionKeyFrames.reserve(channel.positionKeys.size()); newChannel.PositionKeyFrames.reserve(channel.positionKeys.size());
newChannel.RotationKeyFrames.reserve(channel.rotationKeys.size()); newChannel.RotationKeyFrames.reserve(channel.rotationKeys.size());
newChannel.ScaleKeyFrames.reserve(channel.scaleKeys.size()); newChannel.ScaleKeyFrames.reserve(channel.scaleKeys.size());
@ -36,22 +35,31 @@ namespace SHADE
// Populate Keyframes // Populate Keyframes
for (const auto& posKey : channel.positionKeys) 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) 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) 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() }); 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 // Insert the channel
channels.emplace_back(std::move(newChannel)); channels.emplace_back(std::move(newChannel));
} }
// Compute fps
ticksPerSecond = static_cast<int>(maxFrames / totalTime);
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -27,8 +27,8 @@ namespace SHADE
template<typename T> template<typename T>
struct SHAnimationKeyFrame struct SHAnimationKeyFrame
{ {
int FrameIndex; float TimeStamp;
T Data; T Data;
}; };
/// <summary> /// <summary>
@ -46,7 +46,6 @@ namespace SHADE
/// </summary> /// </summary>
struct Channel struct Channel
{ {
std::string Name;
std::vector<SHAnimationKeyFrame<SHVec3>> PositionKeyFrames; std::vector<SHAnimationKeyFrame<SHVec3>> PositionKeyFrames;
std::vector<SHAnimationKeyFrame<SHQuaternion>> RotationKeyFrames; std::vector<SHAnimationKeyFrame<SHQuaternion>> RotationKeyFrames;
std::vector<SHAnimationKeyFrame<SHVec3>> ScaleKeyFrames; std::vector<SHAnimationKeyFrame<SHVec3>> ScaleKeyFrames;

View File

@ -89,16 +89,7 @@ namespace SHADE
currClip = newClip; currClip = newClip;
secsPerTick = 1.0f / currClip->GetTicksPerSecond(); secsPerTick = 1.0f / currClip->GetTicksPerSecond();
// Build channel map // Set to initial pose
channelMap.clear();
if (currClip)
{
for (const auto& channel : currClip->GetChannels())
{
channelMap.emplace(channel.Name, &channel);
}
}
if (rig && rig->GetRootNode() && currClip) if (rig && rig->GetRootNode() && currClip)
{ {
updatePoseWithClip(0.0f); updatePoseWithClip(0.0f);
@ -133,24 +124,23 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHAnimatorComponent::updatePoseWithClip(float poseTime) void SHAnimatorComponent::updatePoseWithClip(float poseTime)
{ {
// Get closest frame index updatePoseWithClip(poseTime, rig->GetRootNode(), SHMatrix::Identity);
const int CLOSEST_FRAME_IDX = static_cast<int>(std::floorf(poseTime * currClip->GetTicksPerSecond()));
updatePoseWithClip(CLOSEST_FRAME_IDX, 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 // Check if there is a channel for this node
const std::string& BONE_NAME = rig->GetName(node);
SHMatrix transformMatrix = node->TransformMatrix; 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 transformMatrix = SHMatrix::Transform
( (
getInterpolatedValue(CHANNEL->PositionKeyFrames, closestFrameIndex, poseTime), getInterpolatedValue(CHANNEL.PositionKeyFrames, poseTime),
getInterpolatedValue(CHANNEL->RotationKeyFrames, closestFrameIndex, poseTime), getInterpolatedValue(CHANNEL.RotationKeyFrames, poseTime),
getInterpolatedValue(CHANNEL->ScaleKeyFrames, closestFrameIndex, poseTime) getInterpolatedValue(CHANNEL.ScaleKeyFrames, poseTime)
); );
} }
@ -168,7 +158,7 @@ namespace SHADE
// Apply pose to children // Apply pose to children
for (auto& child : node->Children) for (auto& child : node->Children)
{ {
updatePoseWithClip(closestFrameIndex, poseTime, child, transformMatrix); updatePoseWithClip(poseTime, child, transformMatrix);
} }
} }
} }

View File

@ -134,16 +134,14 @@ namespace SHADE
float secsPerTick = 0.0f; float secsPerTick = 0.0f;
// Buffer // Buffer
std::vector<SHMatrix> boneMatrices; std::vector<SHMatrix> boneMatrices;
// Caches
std::unordered_map<std::string, const SHAnimationClip::Channel*> channelMap;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void updatePoseWithClip(float poseTime); 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> 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 */ /* RTTR */

View File

@ -26,7 +26,7 @@ namespace SHADE
/* Helper Functions */ /* Helper Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
template<typename T> 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 // 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."); 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; const auto& KEYFRAME = *iter;
if (KEYFRAME.FrameIndex <= closestFrameIndex) if (KEYFRAME.TimeStamp <= poseTime)
{ {
firstKeyFrame = iter; firstKeyFrame = iter;
} }
else // KEYFRAME.FrameIndex > closestFrameIndex else // KEYFRAME.FrameIndex > poseTime
{ {
nextKeyFrame = iter; nextKeyFrame = iter;
break; break;
@ -66,8 +66,8 @@ namespace SHADE
} }
// Get interpolated vector // Get interpolated vector
const float PREV_FRAME_TIME = firstKeyFrame->FrameIndex * secsPerTick; const float PREV_FRAME_TIME = firstKeyFrame->TimeStamp;
const float NEXT_FRAME_TIME = nextKeyFrame->FrameIndex * secsPerTick; const float NEXT_FRAME_TIME = nextKeyFrame->TimeStamp;
const float NORMALISED_TIME = (poseTime - PREV_FRAME_TIME) / (NEXT_FRAME_TIME - PREV_FRAME_TIME); const float NORMALISED_TIME = (poseTime - PREV_FRAME_TIME) / (NEXT_FRAME_TIME - PREV_FRAME_TIME);
if constexpr (std::is_same_v<T, SHQuaternion>) if constexpr (std::is_same_v<T, SHQuaternion>)

View File

@ -120,8 +120,10 @@ namespace SHADE
// Fill the node with data // Fill the node with data
const auto& NODE_DATA = asset.nodeDataCollection.at(sourceNode->idRef); const auto& NODE_DATA = asset.nodeDataCollection.at(sourceNode->idRef);
newNode->OffsetMatrix = SHMatrix::Transpose(NODE_DATA.offset); //newNode->OffsetMatrix = SHMatrix::Transpose(NODE_DATA.inverseBindMatrix);
newNode->TransformMatrix = SHMatrix::Transpose(NODE_DATA.transform); //newNode->TransformMatrix = SHMatrix::Transpose(NODE_DATA.transform);
newNode->OffsetMatrix = NODE_DATA.inverseBindMatrix;
newNode->TransformMatrix = NODE_DATA.transform;
// Populate maps // Populate maps
if (!NODE_DATA.name.empty()) if (!NODE_DATA.name.empty())

View File

@ -18,71 +18,61 @@
namespace SHADE namespace SHADE
{ {
enum class SHAnimationBehaviour : uint8_t enum class AnimationInterpolation : uint8_t
{ {
DEFAULT = 0x0, DEFAULT = 0x1,
CONSTANT = 0x1, LINEAR = 0x1,
LINEAR = 0x2, STEP = 0x2,
REPEAT = 0x3 CUBICSPLINE = 0x3
}; };
// Smallest data containers // Base
struct PositionKey struct KeyBase
{ {
float time; float time;
SHVec3 value; };
};
// Smallest data containers
struct RotationKey struct PositionKey :KeyBase
{ {
float time; SHVec3 value;
SHVec4 value; };
};
struct RotationKey : KeyBase
struct ScaleKey {
{ SHVec4 value;
float time; };
SHVec3 value;
}; struct ScaleKey :KeyBase
{
SHVec3 value;
};
// Headers for read/write // Headers for read/write
struct SHAnimNodeInfo
{
uint32_t charCount;
uint32_t posKeyCount;
uint32_t rotKeyCount;
uint32_t scaKeyCount;
};
struct SHAnimDataHeader struct SHAnimDataHeader
{ {
uint32_t charCount; uint32_t charCount;
uint32_t animNodeCount; uint32_t animNodeCount;
std::vector<SHAnimNodeInfo> nodeHeaders; uint32_t frameCount;
}; };
// Main data containers // Main data containers
struct SHAnimData struct SHAnimNode
{ {
std::string name; AnimationInterpolation interpolation;
SHAnimationBehaviour pre;
SHAnimationBehaviour post;
std::vector<PositionKey> positionKeys;
std::vector<RotationKey> rotationKeys;
std::vector<ScaleKey> scaleKeys;
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; std::string name;
double duration; double duration{};
double ticksPerSecond; double ticksPerSecond{};
std::vector<SHAnimData> nodeChannels; std::vector<SHAnimNode> nodeChannels{};
//std::vector<aiMeshAnim*> meshChannels;
//std::vector<aiMeshMorphAnim*> morphMeshChannels;
}; };
} }

View File

@ -19,45 +19,28 @@
namespace SHADE namespace SHADE
{ {
constexpr int BONE_INDEX_ALIGHTMENT = 4;
struct SHMeshDataHeader struct SHMeshDataHeader
{ {
uint32_t vertexCount; uint32_t vertexCount;
uint32_t indexCount; uint32_t indexCount;
uint32_t charCount; uint32_t charCount;
uint32_t boneCount; bool hasWeights;
};
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;
}; };
struct SH_API SHMeshAsset : SHAssetData struct SH_API SHMeshAsset : SHAssetData
{ {
std::string name; std::string name;
std::vector<SHVec3> VertexPositions; std::vector<SHVec3> VertexPositions{};
std::vector<SHVec3> VertexTangents; std::vector<SHVec3> VertexTangents{};
std::vector<SHVec3> VertexNormals; std::vector<SHVec3> VertexNormals{};
std::vector<SHVec2> VertexTexCoords; std::vector<SHVec2> VertexTexCoords{};
std::vector<uint32_t> Indices; std::vector<uint32_t> Indices{};
std::vector<SHVec4U> VertexBoneIndices;
std::vector<SHVec4> VertexBoneWeights; //Variables
std::vector<SHVec4> VertexBoneWeights{};
std::vector<SHVec4U> VertexBoneIndices{};
uint32_t BoneCount; uint32_t BoneCount;
}; };
} }

View File

@ -1,13 +1,11 @@
#include "SHpch.h" #include "SHpch.h"
#include "SHRigAsset.h" #include "SHRigAsset.h"
#include <queue>
namespace SHADE namespace SHADE
{ {
SHRigAsset::~SHRigAsset() SHRigAsset::~SHRigAsset()
{ {
if (root != nullptr) if (root != nullptr)
delete[] root; delete[] root;
} }
} }

View File

@ -17,31 +17,43 @@
namespace SHADE 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 struct SHRigDataHeader
{ {
uint32_t nodeCount; uint32_t nodeCount{};
std::vector<uint32_t> charCounts; uint32_t startNode{};
std::vector<uint32_t> charCounts{};
}; };
struct SHRigNodeData struct SHRigNodeData
{ {
std::string name; std::string name;
SHMatrix transform; SHMatrix transform;
SHMatrix offset; SHMatrix inverseBindMatrix;
}; };
struct SHRigNodeAsset struct SHRigNodeAsset
{ {
uint32_t idRef; uint32_t idRef;
std::vector<SHRigNodeAsset*> children; std::vector<SHRigNodeAsset*> children;
}; };
struct SH_API SHRigAsset : SHAssetData struct SH_API SHRigAsset : SHAssetData
{ {
~SHRigAsset(); ~SHRigAsset();
SHRigDataHeader header; SHRigDataHeader header;
std::vector<SHRigNodeData> nodeDataCollection; std::vector<SHRigNodeData> nodeDataCollection{};
SHRigNodeAsset* root; SHRigNodeAsset* root;
}; };
} }

View File

@ -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;
};
}

View File

@ -17,6 +17,52 @@
namespace SHADE 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) void SHModelLoader::ReadHeaders(FileReference file, SHModelAsset& asset)
{ {
file.read( file.read(
@ -36,29 +82,12 @@ namespace SHADE
if (asset.header.animCount > 0) if (asset.header.animCount > 0)
{ {
asset.animHeaders.resize(asset.header.animCount); 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( file.read(
reinterpret_cast<char*>(&animHeader.charCount), reinterpret_cast<char*>(&animHeader),
sizeof(uint32_t) 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); ReadRigHeader(file, asset.rig.header);
ReadRigData(file, asset.rig.header, asset.rig.nodeDataCollection); ReadRigData(file, asset.rig.header, asset.rig.nodeDataCollection);
ReadRigTree(file, asset.rig.header, asset.rig.root); 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( file.read(
data.name.data(), reinterpret_cast<char*>(&data.interpolation),
info.charCount 1
); );
file.read( data.positionKeys.resize(frameCount);
reinterpret_cast<char*>(&data.pre), data.rotationKeys.resize(frameCount);
sizeof(SHAnimationBehaviour) data.scaleKeys.resize(frameCount);
);
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);
file.read( file.read(
reinterpret_cast<char*>(data.positionKeys.data()), reinterpret_cast<char*>(data.positionKeys.data()),
sizeof(PositionKey) * keySize sizeof(PositionKey) * frameCount
); );
file.read( file.read(
reinterpret_cast<char*>(data.rotationKeys.data()), reinterpret_cast<char*>(data.rotationKeys.data()),
sizeof(RotationKey) * keySize sizeof(RotationKey) * frameCount
); );
file.read( file.read(
reinterpret_cast<char*>(data.scaleKeys.data()), 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) void SHModelLoader::ReadRigHeader(FileReference file, SHRigDataHeader& header)
{ {
file.read( file.read(
@ -128,6 +167,11 @@ namespace SHADE
sizeof(uint32_t) sizeof(uint32_t)
); );
file.read(
reinterpret_cast<char*>(&header.startNode),
sizeof(uint32_t)
);
header.charCounts.resize(header.nodeCount); header.charCounts.resize(header.nodeCount);
file.read( file.read(
reinterpret_cast<char*>(header.charCounts.data()), reinterpret_cast<char*>(header.charCounts.data()),
@ -141,21 +185,72 @@ namespace SHADE
for (auto i {0}; i < header.nodeCount; ++i) 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( file.read(
data[i].name.data(), node.name.data(),
header.charCounts[i] header.charCounts[i]
); );
file.read( file.read(
reinterpret_cast<char*>(&data[i].transform), reinterpret_cast<char*>(&node.inverseBindMatrix),
sizeof(SHMatrix) 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++); 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,7 +314,6 @@ namespace SHADE
data.VertexNormals.resize(header.vertexCount); data.VertexNormals.resize(header.vertexCount);
data.VertexTexCoords.resize(header.vertexCount); data.VertexTexCoords.resize(header.vertexCount);
data.Indices.resize(header.indexCount); data.Indices.resize(header.indexCount);
data.BoneCount = header.boneCount;
file.read(data.name.data(), header.charCount); file.read(data.name.data(), header.charCount);
file.read(reinterpret_cast<char*>(data.VertexPositions.data()), vertexVec3Byte); 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.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);
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.VertexBoneIndices.resize(header.vertexCount);
data.VertexBoneWeights.resize(header.vertexCount); data.VertexBoneWeights.resize(header.vertexCount);
for (uint32_t boneIndex{0}; boneIndex < bones.size(); ++boneIndex) file.read(
{ reinterpret_cast<char*>(data.VertexBoneWeights.data()),
auto const& bone = bones[boneIndex]; sizeof(SHVec4) * header.vertexCount
for (auto const& weight : bone.weights) );
{
auto& boneIndices = data.VertexBoneIndices[weight.index];
auto& boneWeight = data.VertexBoneWeights[weight.index];
for (auto j{0}; j < BONE_INDEX_ALIGHTMENT; ++j) file.read(
{ reinterpret_cast<char*>(data.VertexBoneIndices.data()),
if (boneWeight[j] == 0.f) sizeof(SHVec4U) * header.vertexCount
{ );
boneIndices[j] = boneIndex;
boneWeight[j] = weight.weight;
break;
}
}
}
}
} }
meshes[i] = &data; meshes[i] = &data;
@ -306,7 +370,7 @@ namespace SHADE
animAsset.nodeChannels.resize(header.animNodeCount); animAsset.nodeChannels.resize(header.animNodeCount);
for (auto i {0}; i < header.animNodeCount; ++i) 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; anims[i] = &animAsset;

View File

@ -20,7 +20,6 @@ namespace SHADE
{ {
using FileReference = std::ifstream&; using FileReference = std::ifstream&;
void ReadAnimNode(FileReference file, SHAnimNodeInfo const& info, SHAnimData& data);
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);
@ -28,6 +27,9 @@ namespace SHADE
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);
void ReadAnimNode(FileReference file, uint32_t frameCount, SHAnimNode& data);
void BuildTransformMatrices(SHRigAsset& rig);
void ReadHeaders(FileReference file, SHModelAsset& asset); void ReadHeaders(FileReference file, SHModelAsset& asset);
void ReadData(FileReference file, SHModelAsset& asset); void ReadData(FileReference file, SHModelAsset& asset);

View File

@ -14,6 +14,7 @@
#include "Assets/Asset Types/SHSceneAsset.h" #include "Assets/Asset Types/SHSceneAsset.h"
#include "Assets/Asset Types/SHPrefabAsset.h" #include "Assets/Asset Types/SHPrefabAsset.h"
#include "Assets/Asset Types/SHMaterialAsset.h" #include "Assets/Asset Types/SHMaterialAsset.h"
#include "Assets/Asset Types/SHAudioBankAsset.h"
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
@ -22,6 +23,14 @@ namespace SHADE
{ {
SHAssetData* SHTextBasedLoader::Load(AssetPath path) 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 }; std::ifstream file{ path, std::ios::in };
if (!file.is_open()) if (!file.is_open())

View File

@ -56,6 +56,7 @@ enum class AssetType : AssetTypeMeta
MESH, MESH,
SCRIPT, SCRIPT,
FONT, FONT,
AUDIO_BANK,
MAX_COUNT MAX_COUNT
}; };
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::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 META_EXTENSION {".shmeta"};
constexpr std::string_view AUDIO_EXTENSION {".ogg"}; constexpr std::string_view AUDIO_EXTENSION {".ogg"};
constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"}; 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_EXTENSION{ ".shshader" };
constexpr std::string_view SHADER_BUILT_IN_EXTENSION{ ".shshaderb" }; constexpr std::string_view SHADER_BUILT_IN_EXTENSION{ ".shshaderb" };
constexpr std::string_view FONT_EXTENSION{ ".shfont" }; constexpr std::string_view FONT_EXTENSION{ ".shfont" };
@ -105,10 +107,10 @@ constexpr std::string_view EXTENSIONS[] = {
"dummy", "dummy",
SCRIPT_EXTENSION, SCRIPT_EXTENSION,
FONT_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 // EXTERNAL EXTENSIONS
constexpr std::string_view GLSL_EXTENSION{ ".glsl" }; constexpr std::string_view GLSL_EXTENSION{ ".glsl" };

View File

@ -445,6 +445,10 @@ namespace SHADE
fontPath += FONT_EXTENSION; fontPath += FONT_EXTENSION;
newPath = fontPath; newPath = fontPath;
} }
else if (ext == AUDIO_BANK_EXTENSION.data())
{
newPath = path.string();
}
else else
{ {
SHLOG_WARNING("[Asset Manager] File Type compilation not yet Implemented: {}", path.string()); 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::MESH)] = nullptr;
loaders[static_cast<size_t>(AssetType::SCRIPT)] = 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::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; 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) else if(ext == MATERIAL_EXTENSION)
{ {
SHAsset newAsset{ SHAsset newAsset{

View File

@ -162,6 +162,7 @@ namespace SHADE
{ {
assetCollection.emplace(asset.id, asset); assetCollection.emplace(asset.id, asset);
} }
if (file.name == asset.name) if (file.name == asset.name)
{ {
AssetPath path{ file.path }; AssetPath path{ file.path };