Updated Loading of .shmodel files and updated original models #303
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.
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.
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
}
|
|
@ -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,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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,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;
|
||||
}
|
||||
|
|
|
@ -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 ReadHeader(std::ifstream& file, SHMeshLoaderHeader& header) noexcept;
|
||||
void ReadData(std::ifstream& file, SHMeshLoaderHeader const& header, SHMeshAsset& data) noexcept;
|
||||
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 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;
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue