Updated Model asset and rig loading
This commit is contained in:
parent
06b7db14d5
commit
ab766d9304
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHRigAsset.h"
|
||||||
|
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
SHRigAsset::~SHRigAsset()
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,42 +13,231 @@
|
||||||
#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)
|
||||||
|
);
|
||||||
|
|
||||||
|
asset.meshHeaders.resize(asset.header.meshCount);
|
||||||
|
asset.animHeaders.resize(asset.header.animCount);
|
||||||
|
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(asset.meshHeaders.data()),
|
||||||
|
sizeof(asset.header.meshCount) * sizeof(SHMeshDataHeader)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(asset.animHeaders.data()),
|
||||||
|
sizeof(asset.header.animCount) * sizeof(SHAnimDataHeader)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHModelLoader::ReadData(std::ifstream& file, SHMeshLoaderHeader const& header, SHMeshAsset& data) noexcept
|
void SHModelLoader::ReadData(FileReference file, SHModelAsset& asset)
|
||||||
{
|
{
|
||||||
auto const vertexVec3Byte{ sizeof(SHVec3) * header.vertexCount };
|
ReadMeshData(file, asset.meshHeaders, asset.meshes);
|
||||||
auto const vertexVec2Byte{ sizeof(SHVec2) * header.vertexCount };
|
ReadAnimData(file, asset.animHeaders, asset.anims);
|
||||||
|
|
||||||
data.VertexPositions.resize(header.vertexCount);
|
// Not eof yet, animation exists
|
||||||
data.VertexTangents.resize(header.vertexCount);
|
if (file.peek() != EOF)
|
||||||
data.VertexNormals.resize(header.vertexCount);
|
{
|
||||||
data.VertexTexCoords.resize(header.vertexCount);
|
ReadRigHeader(file, asset.rig.header);
|
||||||
data.Indices.resize(header.indexCount);
|
ReadRigData(file, asset.rig.header, asset.rig.nodeDataCollection);
|
||||||
data.header.name.resize(header.charCount);
|
ReadRigTree(file, asset.rig.header, asset.rig.root);
|
||||||
|
}
|
||||||
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::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::ReadRigHeader(FileReference file, SHRigDataHeader& header)
|
||||||
|
{
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(&header.nodeCount),
|
||||||
|
sizeof(uint32_t)
|
||||||
|
);
|
||||||
|
|
||||||
|
header.charCounts.resize(header.nodeCount);
|
||||||
|
file.read(
|
||||||
|
reinterpret_cast<char*>(header.charCounts.data()),
|
||||||
|
sizeof(uint32_t) * header.nodeCount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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())
|
||||||
{
|
{
|
||||||
|
@ -58,29 +247,10 @@ namespace SHADE
|
||||||
|
|
||||||
file.seekg(0);
|
file.seekg(0);
|
||||||
|
|
||||||
//TODO Update to new mesh header with anim count when animation saving is done
|
ReadHeaders(file, *result);
|
||||||
file.read(
|
ReadData(file, *result);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,19 +18,20 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
class SHModelLoader : public SHAssetLoader
|
class SHModelLoader : public SHAssetLoader
|
||||||
{
|
{
|
||||||
struct SHMeshLoaderHeader
|
using FileReference = std::ifstream&;
|
||||||
{
|
|
||||||
uint32_t vertexCount;
|
|
||||||
uint32_t indexCount;
|
|
||||||
uint32_t charCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
void ReadAnimNode(FileReference file, SHAnimNodeInfo const& info, SHAnimData& data);
|
||||||
|
|
||||||
void ReadHeader(std::ifstream& file, SHMeshLoaderHeader& header) noexcept;
|
void ReadRigHeader(FileReference file, SHRigDataHeader& header);
|
||||||
void ReadData(std::ifstream& file, SHMeshLoaderHeader const& header, SHMeshAsset& data) noexcept;
|
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 ReadHeaders(FileReference file, SHModelAsset& asset);
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue