Updated Loading of .shmodel files and updated original models #303
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
{
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,42 +13,231 @@
|
|||
#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)
|
||||
);
|
||||
|
||||
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 };
|
||||
auto const vertexVec2Byte{ sizeof(SHVec2) * header.vertexCount };
|
||||
ReadMeshData(file, asset.meshHeaders, asset.meshes);
|
||||
ReadAnimData(file, asset.animHeaders, asset.anims);
|
||||
|
||||
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;
|
||||
// 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::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 };
|
||||
if (!file.is_open())
|
||||
{
|
||||
|
@ -58,29 +247,10 @@ namespace SHADE
|
|||
|
||||
file.seekg(0);
|
||||
|
||||
//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)
|
||||
);
|
||||
ReadHeaders(file, *result);
|
||||
ReadData(file, *result);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue