Animation WIP merge #321

Merged
XiaoQiDigipen merged 76 commits from SP3-17-animation-system into main 2023-01-30 17:35:57 +08:00
24 changed files with 1210 additions and 2964 deletions
Showing only changes of commit d913a6dd08 - Show all commits

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -73,7 +73,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------------*/
Handle<SHRig::Node> SHRig::recurseCreateNode(const SHRigAsset& asset, const RigNode* sourceNode)
Handle<SHRig::Node> SHRig::recurseCreateNode(const SHRigAsset& asset, const SHRigNode* sourceNode)
{
// Construct the node
auto newNode = nodeStore.Create();

View File

@ -27,7 +27,7 @@ namespace SHADE
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
struct SHRigAsset;
struct RigNode;
struct SHRigNode;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
@ -99,6 +99,6 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
Handle<Node> recurseCreateNode(const SHRigAsset& asset, const RigNode* sourceNode);
Handle<Node> recurseCreateNode(const SHRigAsset& asset, const SHRigNode* sourceNode);
};
}

View File

@ -24,7 +24,6 @@ namespace SHADE
uint32_t indexCount;
uint32_t charCount;
uint32_t boneCount;
std::string name;
};
struct MeshBoneInfo
@ -48,7 +47,7 @@ namespace SHADE
struct SH_API SHMeshAsset : SHAssetData
{
SHMeshDataHeader header;
std::string name;
std::vector<SHVec3> VertexPositions;
std::vector<SHVec3> VertexTangents;
std::vector<SHVec3> VertexNormals;

View File

@ -29,9 +29,11 @@ namespace SHADE
struct SH_API SHModelAsset : SHAssetData
{
SHModelAssetHeader header;
SHRigAsset rig;
std::vector<SHMeshDataHeader> meshHeaders;
std::vector<SHAnimDataHeader> animHeaders;
std::vector<SHMeshAsset*> meshes;
std::vector<SHAnimAsset*> anims;
};

View File

@ -0,0 +1,31 @@
#include "SHpch.h"
#include "SHRigAsset.h"
#include <queue>
namespace SHADE
{
SHRigAsset::~SHRigAsset()
{
if (root == nullptr)
{
return;
}
std::queue<SHRigNode*> nodeQueue;
nodeQueue.push(root);
while(!nodeQueue.empty())
{
auto curr = nodeQueue.front();
nodeQueue.pop();
for (auto child : curr->children)
{
nodeQueue.push(child);
}
delete curr;
}
}
}

View File

@ -17,32 +17,30 @@
namespace SHADE
{
struct RigDataHeader
struct SHRigDataHeader
{
uint32_t nodeCount;
std::vector<uint32_t> charCounts;
};
struct RigNodeData
struct SHRigNodeData
{
std::string name;
SHMatrix transform;
};
struct RigNode
struct SHRigNode
{
uint32_t idRef;
std::vector<RigNode*> children;
std::vector<SHRigNode*> children;
};
struct SH_API SHRigAsset : SHAssetData
{
~SHRigAsset()
{
delete root;
}
~SHRigAsset();
std::map<uint32_t, RigNodeData> nodeDataCollection;
RigNode* root;
SHRigDataHeader header;
std::vector<SHRigNodeData> nodeDataCollection;
SHRigNode* root;
};
}

View File

@ -13,74 +13,268 @@
#include "SHpch.h"
#include "SHModelLoader.h"
#include <fstream>
#include <queue>
namespace SHADE
{
void SHModelLoader::ReadHeader(std::ifstream& file, SHMeshLoaderHeader& header) noexcept
void SHModelLoader::ReadHeaders(FileReference file, SHModelAsset& asset)
{
file.read(
reinterpret_cast<char*>(&header),
sizeof(SHMeshLoaderHeader)
reinterpret_cast<char*>(&asset.header),
sizeof(asset.header)
);
if (asset.header.meshCount > 0)
{
asset.meshHeaders.resize(asset.header.meshCount);
file.read(
reinterpret_cast<char*>(asset.meshHeaders.data()),
asset.header.meshCount * sizeof(SHMeshDataHeader)
);
}
if (asset.header.animCount > 0)
{
asset.animHeaders.resize(asset.header.animCount);
for (auto i {0}; i < asset.header.animCount; ++i)
{
auto& animHeader = asset.animHeaders[i];
file.read(
reinterpret_cast<char*>(&animHeader.charCount),
sizeof(uint32_t)
);
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)
);
}
}
}
}
void SHModelLoader::ReadData(FileReference file, SHModelAsset& asset)
{
ReadMeshData(file, asset.meshHeaders, asset.meshes);
ReadAnimData(file, asset.animHeaders, asset.anims);
// Not eof yet, animation exists
if (file.peek() != EOF)
{
ReadRigHeader(file, asset.rig.header);
ReadRigData(file, asset.rig.header, asset.rig.nodeDataCollection);
ReadRigTree(file, asset.rig.header, asset.rig.root);
}
}
void SHModelLoader::ReadAnimNode(FileReference file, SHAnimNodeInfo const& info, SHAnimData& data)
{
file.read(
data.name.data(),
info.charCount
);
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);
file.read(
reinterpret_cast<char*>(data.positionKeys.data()),
sizeof(PositionKey) * keySize
);
file.read(
reinterpret_cast<char*>(data.rotationKeys.data()),
sizeof(RotationKey) * keySize
);
file.read(
reinterpret_cast<char*>(data.scaleKeys.data()),
sizeof(ScaleKey) * keySize
);
}
void SHModelLoader::ReadData(std::ifstream& file, SHMeshLoaderHeader const& header, SHMeshAsset& data) noexcept
void SHModelLoader::ReadRigHeader(FileReference file, SHRigDataHeader& header)
{
auto const vertexVec3Byte{ sizeof(SHVec3) * header.vertexCount };
auto const vertexVec2Byte{ sizeof(SHVec2) * header.vertexCount };
file.read(
reinterpret_cast<char*>(&header.nodeCount),
sizeof(uint32_t)
);
data.VertexPositions.resize(header.vertexCount);
data.VertexTangents.resize(header.vertexCount);
data.VertexNormals.resize(header.vertexCount);
data.VertexTexCoords.resize(header.vertexCount);
data.Indices.resize(header.indexCount);
data.header.name.resize(header.charCount);
file.read(data.header.name.data(), header.charCount);
file.read(reinterpret_cast<char*>(data.VertexPositions.data()), vertexVec3Byte);
file.read(reinterpret_cast<char*>(data.VertexTangents.data()), vertexVec3Byte);
file.read(reinterpret_cast<char*>(data.VertexNormals.data()), vertexVec3Byte);
file.read(reinterpret_cast<char*>(data.VertexTexCoords.data()), vertexVec2Byte);
file.read(reinterpret_cast<char*>(data.Indices.data()), sizeof(uint32_t) * header.indexCount);
data.header.vertexCount = header.vertexCount;
data.header.indexCount = header.indexCount;
header.charCounts.resize(header.nodeCount);
file.read(
reinterpret_cast<char*>(header.charCounts.data()),
sizeof(uint32_t) * header.nodeCount
);
}
void SHModelLoader::LoadSHMesh(AssetPath path, SHModelAsset& model) noexcept
void SHModelLoader::ReadRigData(FileReference file, SHRigDataHeader const& header, std::vector<SHRigNodeData>& data)
{
data.resize(header.nodeCount);
for (auto i {0}; i < header.nodeCount; ++i)
{
data[i].name.resize(header.charCounts[i]);
file.read(
data[i].name.data(),
header.charCounts[i]
);
file.read(
reinterpret_cast<char*>(&data[i].transform),
sizeof(SHMatrix)
);
}
}
void SHModelLoader::ReadRigTree(FileReference file, SHRigDataHeader const& header, SHRigNode* root)
{
// Read All nodes into one contiguous data block
struct NodeTemp
{
uint32_t id, numChild;
};
NodeTemp* dst = new NodeTemp[header.nodeCount];
file.read(
reinterpret_cast<char*>(dst),
sizeof(NodeTemp) * header.nodeCount
);
// Build and populate tree
SHRigNode* nodePool = new SHRigNode[header.nodeCount];
root = nodePool;
std::queue<std::pair<SHRigNode*, NodeTemp*>> nodeQueue;
nodeQueue.emplace(std::make_pair(nodePool, dst));
auto depthPtr = nodePool + 1;
auto depthTempPtr = dst + 1;
while(!nodeQueue.empty())
{
auto currPair = nodeQueue.front();
nodeQueue.pop();
auto currNode = currPair.first;
auto currTemp = currPair.second;
currNode->idRef = currTemp->id;
for (auto i{0}; i < currTemp->numChild; ++i)
{
currNode->children.push_back(depthPtr);
nodeQueue.emplace(depthPtr++, depthTempPtr++);
}
}
}
void SHModelLoader::ReadMeshData(FileReference file, std::vector<SHMeshDataHeader> const& headers,
std::vector<SHMeshAsset*>& meshes)
{
meshes.resize(headers.size());
for (auto i {0}; i < headers.size(); ++i)
{
auto const& header = headers[i];
auto& data = *new SHMeshAsset;
auto const vertexVec3Byte{ sizeof(SHVec3) * header.vertexCount };
auto const vertexVec2Byte{ sizeof(SHVec2) * header.vertexCount };
data.name.resize(header.charCount);
data.VertexPositions.resize(header.vertexCount);
data.VertexTangents.resize(header.vertexCount);
data.VertexNormals.resize(header.vertexCount);
data.VertexTexCoords.resize(header.vertexCount);
data.Indices.resize(header.indexCount);
file.read(data.name.data(), header.charCount);
file.read(reinterpret_cast<char*>(data.VertexPositions.data()), vertexVec3Byte);
file.read(reinterpret_cast<char*>(data.VertexTangents.data()), vertexVec3Byte);
file.read(reinterpret_cast<char*>(data.VertexNormals.data()), vertexVec3Byte);
file.read(reinterpret_cast<char*>(data.VertexTexCoords.data()), vertexVec2Byte);
file.read(reinterpret_cast<char*>(data.Indices.data()), sizeof(uint32_t) * header.indexCount);
meshes[i] = &data;
}
}
void SHModelLoader::ReadAnimData(FileReference file, std::vector<SHAnimDataHeader> const& headers,
std::vector<SHAnimAsset*>& anims)
{
anims.resize(headers.size());
for (auto i {0}; i < headers.size(); ++i)
{
auto const& header = headers[i];
auto& animAsset = *new SHAnimAsset;
animAsset.name.resize(header.charCount);
file.read(
animAsset.name.data(),
header.charCount
);
file.read(
reinterpret_cast<char*>(&animAsset.duration),
sizeof(double)
);
file.read(
reinterpret_cast<char*>(&animAsset.ticksPerSecond),
sizeof(double)
);
animAsset.nodeChannels.resize(header.animNodeCount);
for (auto i {0}; i < header.animNodeCount; ++i)
{
ReadAnimNode(file, header.nodeHeaders[i], animAsset.nodeChannels[i]);
}
anims[i] = &animAsset;
}
}
SHAssetData* SHModelLoader::Load(AssetPath path)
{
auto result = new SHModelAsset();
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
if (!file.is_open())
{
SHLOG_ERROR("[Model Loader] Unable to open SHModel File: {}", path.string());
return;
return nullptr;
}
file.seekg(0);
ReadHeaders(file, *result);
ReadData(file, *result);
//TODO Update to new mesh header with anim count when animation saving is done
file.read(
reinterpret_cast<char*>(&model.header.meshCount),
sizeof(model.header.meshCount)
);
std::vector<SHMeshLoaderHeader> headers(model.header.meshCount);
model.meshes.resize(model.header.meshCount);
for (auto i{ 0 }; i < model.header.meshCount; ++i)
{
model.meshes[i] = new SHMeshAsset();
ReadHeader(file, headers[i]);
ReadData(file, headers[i], *model.meshes[i]);
}
file.close();
}
SHAssetData* SHModelLoader::Load(AssetPath path)
{
auto result = new SHModelAsset();
LoadSHMesh(path, *result);
return result;
}

View File

@ -18,19 +18,20 @@ namespace SHADE
{
class SHModelLoader : public SHAssetLoader
{
struct SHMeshLoaderHeader
{
uint32_t vertexCount;
uint32_t indexCount;
uint32_t charCount;
};
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);
void ReadRigTree(FileReference file, SHRigDataHeader const& header, SHRigNode* root);
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 ReadHeader(std::ifstream& file, SHMeshLoaderHeader& header) noexcept;
void ReadData(std::ifstream& file, SHMeshLoaderHeader const& header, SHMeshAsset& data) noexcept;
void ReadHeaders(FileReference file, SHModelAsset& asset);
void ReadData(FileReference file, SHModelAsset& asset);
public:
void LoadSHMesh(AssetPath path, SHModelAsset& model) noexcept;
SHAssetData* Load(AssetPath path) override;
void Write(SHAssetData const* data, AssetPath path) override;
};

View File

@ -437,7 +437,7 @@ namespace SHADE
return;
}
if (genMeta)
if (true)
{
GenerateNewMeta(newPath);
}
@ -492,8 +492,8 @@ namespace SHADE
****************************************************************************/
void SHAssetManager::Load() noexcept
{
BuildAssetCollection();
InitLoaders();
BuildAssetCollection();
//CompileAll();
//LoadAllData();
}
@ -610,7 +610,7 @@ namespace SHADE
for(auto const& subMesh : data->meshes)
{
SHAsset subAsset{
.name = subMesh->header.name,
.name = subMesh->name,
.id = GenerateAssetID(AssetType::MESH),
.type = AssetType::MESH,
.isSubAsset = true,

View File

@ -6,6 +6,11 @@ namespace SHADE
template<typename T>
std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T* const> SHAssetManager::GetData(AssetID id) noexcept
{
if (id == 0)
{
return nullptr;
}
if (!assetData.contains(id))
{
for (auto const& asset : std::ranges::views::values(assetCollection))