Merge pull request #303 from SHADE-DP/Model-Loader-Update

Updated Loading of .shmodel files and updated original models
This commit is contained in:
XiaoQiDigipen 2023-01-08 12:40:01 +08:00 committed by GitHub
commit d913a6dd08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 1210 additions and 2964 deletions

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 */ /* 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 // Construct the node
auto newNode = nodeStore.Create(); auto newNode = nodeStore.Create();

View File

@ -27,7 +27,7 @@ namespace SHADE
/* Forward Declarations */ /* Forward Declarations */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
struct SHRigAsset; struct SHRigAsset;
struct RigNode; struct SHRigNode;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -99,6 +99,6 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Helper Functions */ /* 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 indexCount;
uint32_t charCount; uint32_t charCount;
uint32_t boneCount; uint32_t boneCount;
std::string name;
}; };
struct MeshBoneInfo struct MeshBoneInfo
@ -48,7 +47,7 @@ namespace SHADE
struct SH_API SHMeshAsset : SHAssetData struct SH_API SHMeshAsset : SHAssetData
{ {
SHMeshDataHeader header; 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;

View File

@ -29,9 +29,11 @@ namespace SHADE
struct SH_API SHModelAsset : SHAssetData struct SH_API SHModelAsset : SHAssetData
{ {
SHModelAssetHeader header; SHModelAssetHeader header;
SHRigAsset rig; SHRigAsset rig;
std::vector<SHMeshDataHeader> meshHeaders;
std::vector<SHAnimDataHeader> animHeaders;
std::vector<SHMeshAsset*> meshes; std::vector<SHMeshAsset*> meshes;
std::vector<SHAnimAsset*> anims; 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 namespace SHADE
{ {
struct RigDataHeader struct SHRigDataHeader
{ {
uint32_t nodeCount; uint32_t nodeCount;
std::vector<uint32_t> charCounts; std::vector<uint32_t> charCounts;
}; };
struct RigNodeData struct SHRigNodeData
{ {
std::string name; std::string name;
SHMatrix transform; SHMatrix transform;
}; };
struct RigNode struct SHRigNode
{ {
uint32_t idRef; uint32_t idRef;
std::vector<RigNode*> children; std::vector<SHRigNode*> children;
}; };
struct SH_API SHRigAsset : SHAssetData struct SH_API SHRigAsset : SHAssetData
{ {
~SHRigAsset() ~SHRigAsset();
{
delete root;
}
std::map<uint32_t, RigNodeData> nodeDataCollection; SHRigDataHeader header;
RigNode* root; std::vector<SHRigNodeData> nodeDataCollection;
SHRigNode* root;
}; };
} }

View File

@ -13,74 +13,268 @@
#include "SHpch.h" #include "SHpch.h"
#include "SHModelLoader.h" #include "SHModelLoader.h"
#include <fstream> #include <fstream>
#include <queue>
namespace SHADE namespace SHADE
{ {
void SHModelLoader::ReadHeader(std::ifstream& file, SHMeshLoaderHeader& header) noexcept void SHModelLoader::ReadHeaders(FileReference file, SHModelAsset& asset)
{ {
file.read( file.read(
reinterpret_cast<char*>(&header), reinterpret_cast<char*>(&asset.header),
sizeof(SHMeshLoaderHeader) 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 }; file.read(
auto const vertexVec2Byte{ sizeof(SHVec2) * header.vertexCount }; reinterpret_cast<char*>(&header.nodeCount),
sizeof(uint32_t)
);
data.VertexPositions.resize(header.vertexCount); header.charCounts.resize(header.nodeCount);
data.VertexTangents.resize(header.vertexCount); file.read(
data.VertexNormals.resize(header.vertexCount); reinterpret_cast<char*>(header.charCounts.data()),
data.VertexTexCoords.resize(header.vertexCount); sizeof(uint32_t) * header.nodeCount
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;
} }
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 }; std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
if (!file.is_open()) if (!file.is_open())
{ {
SHLOG_ERROR("[Model Loader] Unable to open SHModel File: {}", path.string()); 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(); file.close();
}
SHAssetData* SHModelLoader::Load(AssetPath path)
{
auto result = new SHModelAsset();
LoadSHMesh(path, *result);
return result; return result;
} }

View File

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

View File

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

View File

@ -6,6 +6,11 @@ namespace SHADE
template<typename T> template<typename T>
std::enable_if_t<std::is_base_of_v<SHAssetData, T>, T* const> SHAssetManager::GetData(AssetID id) noexcept 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)) if (!assetData.contains(id))
{ {
for (auto const& asset : std::ranges::views::values(assetCollection)) for (auto const& asset : std::ranges::views::values(assetCollection))