Changed structure for program, segregated asset types structs
This commit is contained in:
parent
456167e9f0
commit
c5f7b22515
|
@ -358,3 +358,5 @@ Premake/
|
||||||
*.sln
|
*.sln
|
||||||
|
|
||||||
Dependencies/
|
Dependencies/
|
||||||
|
|
||||||
|
*.shmodel
|
||||||
|
|
File diff suppressed because one or more lines are too long
BIN
Racoon.shmodel
BIN
Racoon.shmodel
Binary file not shown.
4993
racoon.gltf
4993
racoon.gltf
File diff suppressed because one or more lines are too long
|
@ -11,12 +11,13 @@
|
||||||
* of DigiPen Institute of Technology is prohibited.
|
* of DigiPen Institute of Technology is prohibited.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
#include "MeshCompiler.h"
|
#include "MeshCompiler.h"
|
||||||
|
#include "MeshWriter.h"
|
||||||
#include <assimp/postprocess.h>
|
#include <assimp/postprocess.h>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <queue>
|
#include <stack>
|
||||||
|
|
||||||
namespace SH_COMP
|
namespace SH_COMP
|
||||||
{
|
{
|
||||||
|
@ -26,23 +27,20 @@ namespace SH_COMP
|
||||||
|
|
||||||
void MeshCompiler::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes, RigData& rig) noexcept
|
void MeshCompiler::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes, RigData& rig) noexcept
|
||||||
{
|
{
|
||||||
for (size_t i{ 0 }; i < node.mNumMeshes; ++i)
|
for (auto i{0}; i < node.mNumChildren; ++i)
|
||||||
{
|
{
|
||||||
aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
|
auto const& child {*node.mChildren[i]};
|
||||||
|
|
||||||
|
if (child.mNumMeshes > 0)
|
||||||
|
{
|
||||||
|
aiMesh* mesh = scene.mMeshes[child.mMeshes[0]];
|
||||||
meshes.emplace_back();
|
meshes.emplace_back();
|
||||||
GetMesh(*mesh, meshes.back());
|
GetMesh(*mesh, meshes.back());
|
||||||
meshes.back().name = node.mName.C_Str();
|
meshes.back().name = child.mName.C_Str();
|
||||||
}
|
|
||||||
|
|
||||||
if (std::strcmp(node.mName.C_Str(), "Armature") == 0)
|
|
||||||
{
|
|
||||||
BuildArmature(node, rig.root);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (size_t i{ 0 }; i < node.mNumChildren; ++i)
|
BuildArmature(child, rig);
|
||||||
{
|
|
||||||
ProcessNode(*node.mChildren[i], scene, meshes, rig);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,150 +165,18 @@ namespace SH_COMP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshCompiler::WriteMeshHeader(std::ofstream& file, MeshDataHeader const& header)
|
uint32_t MeshCompiler::RegisterNewNode(aiNode const& node, RigData& rig) noexcept
|
||||||
{
|
{
|
||||||
file.write(
|
auto const result = rigNodeIDCounter++;
|
||||||
reinterpret_cast<char const*>(&header),
|
|
||||||
sizeof(MeshDataHeader)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshCompiler::WriteMeshData(std::ofstream& file, MeshDataHeader const& header, MeshData const& asset)
|
rig.nodeDataCollection[result].name = node.mName.C_Str();
|
||||||
{
|
std::memcpy(
|
||||||
auto const vertexVec3Byte{ sizeof(SHVec3) * header.vertexCount };
|
&rig.nodeDataCollection[result].transform,
|
||||||
auto const vertexVec2Byte{ sizeof(SHVec2) * header.vertexCount };
|
&node.mTransformation,
|
||||||
|
sizeof(SHMat4)
|
||||||
file.write(
|
|
||||||
asset.name.c_str(),
|
|
||||||
header.charCount
|
|
||||||
);
|
);
|
||||||
|
|
||||||
file.write(
|
return result;
|
||||||
reinterpret_cast<char const*>(asset.vertexPosition.data()),
|
|
||||||
vertexVec3Byte
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.vertexTangent.data()),
|
|
||||||
vertexVec3Byte
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.vertexNormal.data()),
|
|
||||||
vertexVec3Byte
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.texCoords.data()),
|
|
||||||
vertexVec2Byte
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(asset.indices.data()),
|
|
||||||
sizeof(uint32_t) * header.indexCount
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshCompiler::WriteAnimHeader(FileReference file, AnimDataHeader const& header)
|
|
||||||
{
|
|
||||||
auto constexpr intSize = sizeof(uint32_t);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&header.charCount),
|
|
||||||
intSize
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&header.animNodeCount),
|
|
||||||
intSize
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(header.nodeHeaders.data()),
|
|
||||||
sizeof(AnimNodeInfo) * header.nodeHeaders.size()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshCompiler::WriteAnimData(FileReference file, AnimDataHeader const& header, AnimData const& data)
|
|
||||||
{
|
|
||||||
file.write(
|
|
||||||
data.name.data(),
|
|
||||||
header.charCount
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&data.duration),
|
|
||||||
sizeof(double)
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&data.ticksPerSecond),
|
|
||||||
sizeof(double)
|
|
||||||
);
|
|
||||||
|
|
||||||
for (auto i{0}; i < header.animNodeCount; ++i)
|
|
||||||
{
|
|
||||||
WriteAnimNode(file, header.nodeHeaders[i], data.nodeChannels[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshCompiler::WriteAnimNode(FileReference file, AnimNodeInfo const& info, AnimNode const& node)
|
|
||||||
{
|
|
||||||
file.write(
|
|
||||||
node.name.data(),
|
|
||||||
info.charCount
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&node.pre),
|
|
||||||
sizeof(AnimationBehaviour)
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&node.post),
|
|
||||||
sizeof(AnimationBehaviour)
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(node.positionKeys.data()),
|
|
||||||
sizeof(PositionKey) * node.positionKeys.size()
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(node.rotationKeys.data()),
|
|
||||||
sizeof(RotationKey) * node.rotationKeys.size()
|
|
||||||
);
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(node.scaleKeys.data()),
|
|
||||||
sizeof(ScaleKey) * node.scaleKeys.size()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshCompiler::WriteHeaders(FileReference file, ModelConstRef asset)
|
|
||||||
{
|
|
||||||
for (auto const& header : asset.meshHeaders)
|
|
||||||
{
|
|
||||||
WriteMeshHeader(file, header);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto const& header : asset.animHeaders)
|
|
||||||
{
|
|
||||||
WriteAnimHeader(file, header);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshCompiler::WriteData(FileReference file, ModelConstRef asset)
|
|
||||||
{
|
|
||||||
for (auto i {0}; i < asset.meshes.size(); ++i)
|
|
||||||
{
|
|
||||||
WriteMeshData(file, asset.meshHeaders[i], asset.meshes[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto i {0}; i < asset.anims.size(); ++i)
|
|
||||||
{
|
|
||||||
WriteAnimData(file, asset.animHeaders[i], asset.anims[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshCompiler::ParseAnimations(aiScene const& scene, std::vector<AnimData>& anims) noexcept
|
void MeshCompiler::ParseAnimations(aiScene const& scene, std::vector<AnimData>& anims) noexcept
|
||||||
|
@ -352,27 +218,27 @@ namespace SH_COMP
|
||||||
node.rotationKeys.resize(channelData.mNumRotationKeys);
|
node.rotationKeys.resize(channelData.mNumRotationKeys);
|
||||||
for (auto k{0}; k < channelData.mNumRotationKeys; ++k)
|
for (auto k{0}; k < channelData.mNumRotationKeys; ++k)
|
||||||
{
|
{
|
||||||
auto const& posKeyData = channelData.mRotationKeys[k];
|
auto const& rotKeyData = channelData.mRotationKeys[k];
|
||||||
auto& posKey = node.rotationKeys[k];
|
auto& rotKey = node.rotationKeys[k];
|
||||||
|
|
||||||
posKey.time = posKeyData.mTime;
|
rotKey.time = rotKeyData.mTime;
|
||||||
posKey.value.x = posKeyData.mValue.x;
|
rotKey.value.x = rotKeyData.mValue.x;
|
||||||
posKey.value.y = posKeyData.mValue.y;
|
rotKey.value.y = rotKeyData.mValue.y;
|
||||||
posKey.value.z = posKeyData.mValue.z;
|
rotKey.value.z = rotKeyData.mValue.z;
|
||||||
posKey.value.w = posKeyData.mValue.w;
|
rotKey.value.w = rotKeyData.mValue.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale Keys
|
// Scale Keys
|
||||||
node.scaleKeys.resize(channelData.mNumScalingKeys);
|
node.scaleKeys.resize(channelData.mNumScalingKeys);
|
||||||
for (auto k{0}; k < channelData.mNumScalingKeys; ++k)
|
for (auto k{0}; k < channelData.mNumScalingKeys; ++k)
|
||||||
{
|
{
|
||||||
auto const& posKeyData = channelData.mScalingKeys[k];
|
auto const& scaKeyData = channelData.mScalingKeys[k];
|
||||||
auto& posKey = node.scaleKeys[k];
|
auto& scaKey = node.scaleKeys[k];
|
||||||
|
|
||||||
posKey.time = posKeyData.mTime;
|
scaKey.time = scaKeyData.mTime;
|
||||||
posKey.value.x = posKeyData.mValue.x;
|
scaKey.value.x = scaKeyData.mValue.x;
|
||||||
posKey.value.y = posKeyData.mValue.y;
|
scaKey.value.y = scaKeyData.mValue.y;
|
||||||
posKey.value.z = posKeyData.mValue.z;
|
scaKey.value.z = scaKeyData.mValue.z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,16 +246,17 @@ namespace SH_COMP
|
||||||
|
|
||||||
void MeshCompiler::LoadFromFile(AssetPath path, ModelAsset& asset) noexcept
|
void MeshCompiler::LoadFromFile(AssetPath path, ModelAsset& asset) noexcept
|
||||||
{
|
{
|
||||||
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
|
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),0
|
||||||
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
|
//aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
|
||||||
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
//| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
||||||
| aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...)
|
//| aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...)
|
||||||
| aiProcess_FindInstances // search for instanced meshes and remove them by references to one master
|
//| aiProcess_FindInstances // search for instanced meshes and remove them by references to one master
|
||||||
| aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible
|
//| aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible
|
||||||
| aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing
|
//| aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing
|
||||||
| aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors
|
//| aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors
|
||||||
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
|
//| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
|
||||||
| aiProcess_ValidateDataStructure
|
//| aiProcess_ValidateDataStructure // checks all bones, animations and vertices are linked correctly
|
||||||
|
//| aiProcess_LimitBoneWeights // Limit number of bones effect vertices to 4
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!scene || !scene->HasMeshes())
|
if (!scene || !scene->HasMeshes())
|
||||||
|
@ -398,46 +265,36 @@ namespace SH_COMP
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParseAnimations(*scene, asset.anims);
|
|
||||||
|
|
||||||
ProcessNode(*scene->mRootNode, *scene, asset.meshes, asset.rig);
|
ProcessNode(*scene->mRootNode, *scene, asset.meshes, asset.rig);
|
||||||
|
|
||||||
|
ParseAnimations(*scene, asset.anims);
|
||||||
|
|
||||||
aiImporter.FreeScene();
|
aiImporter.FreeScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshCompiler::CompileMeshBinary(AssetPath path, ModelAsset const& asset) noexcept
|
|
||||||
{
|
|
||||||
std::string newPath{ path.string().substr(0, path.string().find_last_of('.')) };
|
|
||||||
newPath += MODEL_EXTENSION;
|
|
||||||
|
|
||||||
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
|
|
||||||
if (!file.is_open())
|
|
||||||
{
|
|
||||||
std::cout << "Unable to open file for write: " << newPath << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
file.write(
|
|
||||||
reinterpret_cast<char const*>(&asset.header),
|
|
||||||
sizeof(asset.header)
|
|
||||||
);
|
|
||||||
|
|
||||||
WriteHeaders(file, asset);
|
|
||||||
WriteData(file, asset);
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MeshCompiler::BuildArmature(aiNode const& baseNode, RigData& rig) noexcept
|
void MeshCompiler::BuildArmature(aiNode const& baseNode, RigData& rig) noexcept
|
||||||
{
|
{
|
||||||
std::queue<aiNode const*> nodesQueue;
|
std::stack<std::pair<RigNode*, aiNode const*>> nodesQueue;
|
||||||
nodesQueue.push(&baseNode);
|
rig.root = new RigNode();
|
||||||
|
rig.root->idRef = RegisterNewNode(**baseNode.mChildren, rig);
|
||||||
RigNode* parent = nullptr;
|
nodesQueue.push({rig.root, *baseNode.mChildren});
|
||||||
|
|
||||||
while(!nodesQueue.empty())
|
while(!nodesQueue.empty())
|
||||||
{
|
{
|
||||||
|
auto& rigNode { *nodesQueue.top().first };
|
||||||
|
auto const& dataNode { *nodesQueue.top().second };
|
||||||
|
nodesQueue.pop();
|
||||||
|
|
||||||
|
for (auto i{ 0 }; i < dataNode.mNumChildren; ++i)
|
||||||
|
{
|
||||||
|
rigNode.children.push_back(new RigNode());
|
||||||
|
rigNode.children[i]->idRef = RegisterNewNode(*dataNode.mChildren[i], rig);
|
||||||
|
nodesQueue.push({
|
||||||
|
rigNode.children[i],
|
||||||
|
dataNode.mChildren[i]
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,7 +304,7 @@ namespace SH_COMP
|
||||||
|
|
||||||
LoadFromFile(path, *asset);
|
LoadFromFile(path, *asset);
|
||||||
BuildHeaders(*asset);
|
BuildHeaders(*asset);
|
||||||
CompileMeshBinary(path, *asset);
|
MeshWriter::CompileMeshBinary(path, *asset);
|
||||||
|
|
||||||
delete asset;
|
delete asset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*************************************************************************//**
|
/*************************************************************************//**
|
||||||
* \file SHMeshCompiler.h
|
* \file MeshCompiler.h
|
||||||
* \author Loh Xiao Qi
|
* \author Loh Xiao Qi
|
||||||
* \date 30 September 2022
|
* \date 30 September 2022
|
||||||
* \brief Library to write data in MeshAsset into binary file for faster
|
* \brief Library to write data in MeshAsset into binary file for faster
|
||||||
|
@ -28,8 +28,6 @@ namespace SH_COMP
|
||||||
using MeshVectorRef = std::vector<MeshData>&;
|
using MeshVectorRef = std::vector<MeshData>&;
|
||||||
using AnimVectorRef = std::vector<AnimData>&;
|
using AnimVectorRef = std::vector<AnimData>&;
|
||||||
|
|
||||||
using FileReference = std::ofstream&;
|
|
||||||
using ModelConstRef = ModelAsset const&;
|
|
||||||
using ModelRef = ModelAsset&;
|
using ModelRef = ModelAsset&;
|
||||||
|
|
||||||
static Assimp::Importer aiImporter;
|
static Assimp::Importer aiImporter;
|
||||||
|
@ -39,22 +37,12 @@ namespace SH_COMP
|
||||||
static void GetMesh(aiMesh const& mesh, MeshData& meshData) noexcept;
|
static void GetMesh(aiMesh const& mesh, MeshData& meshData) noexcept;
|
||||||
static void BuildHeaders(ModelRef asset) noexcept;
|
static void BuildHeaders(ModelRef asset) noexcept;
|
||||||
|
|
||||||
static void WriteMeshHeader(FileReference file, MeshDataHeader const& header);
|
static void BuildArmature(aiNode const& node, RigData& rig) noexcept;
|
||||||
static void WriteMeshData(FileReference file, MeshDataHeader const& header, MeshData const& asset);
|
static uint32_t RegisterNewNode(aiNode const& node, RigData& rig) noexcept;
|
||||||
|
static void ParseAnimations(aiScene const& scene, std::vector<AnimData>& anims) noexcept;
|
||||||
static void WriteAnimHeader(FileReference file, AnimDataHeader const& header);
|
|
||||||
static void WriteAnimData(FileReference file, AnimDataHeader const& header, AnimData const& data);
|
|
||||||
static void WriteAnimNode(FileReference file, AnimNodeInfo const& info, AnimNode const& node);
|
|
||||||
|
|
||||||
static void WriteHeaders(FileReference file, ModelConstRef asset);
|
|
||||||
static void WriteData(FileReference file, ModelConstRef asset);
|
|
||||||
|
|
||||||
static void LoadFromFile(AssetPath path, ModelRef asset) noexcept;
|
static void LoadFromFile(AssetPath path, ModelRef asset) noexcept;
|
||||||
static void CompileMeshBinary(AssetPath path, ModelConstRef asset) noexcept;
|
|
||||||
|
|
||||||
static void BuildArmature(aiNode const& node, RigData& rig) noexcept;
|
|
||||||
|
|
||||||
static void ParseAnimations(aiScene const& scene, std::vector<AnimData>& anims) noexcept;
|
|
||||||
public:
|
public:
|
||||||
static void LoadAndCompile(AssetPath path) noexcept;
|
static void LoadAndCompile(AssetPath path) noexcept;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,187 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* \file MeshWriter.cpp
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 19 November 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction
|
||||||
|
* or disclosure of this file or its contents without the prior
|
||||||
|
* written consent of Digipen Institute of Technology is prohibited.
|
||||||
|
******************************************************************************/
|
||||||
|
#include "MeshWriter.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace SH_COMP
|
||||||
|
{
|
||||||
|
|
||||||
|
void MeshWriter::WriteMeshHeader(std::ofstream& file, MeshDataHeader const& header)
|
||||||
|
{
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&header),
|
||||||
|
sizeof(MeshDataHeader)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshWriter::WriteMeshData(std::ofstream& file, MeshDataHeader const& header, MeshData const& asset)
|
||||||
|
{
|
||||||
|
auto const vertexVec3Byte{ sizeof(SHVec3) * header.vertexCount };
|
||||||
|
auto const vertexVec2Byte{ sizeof(SHVec2) * header.vertexCount };
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
asset.name.c_str(),
|
||||||
|
header.charCount
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.vertexPosition.data()),
|
||||||
|
vertexVec3Byte
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.vertexTangent.data()),
|
||||||
|
vertexVec3Byte
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.vertexNormal.data()),
|
||||||
|
vertexVec3Byte
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.texCoords.data()),
|
||||||
|
vertexVec2Byte
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(asset.indices.data()),
|
||||||
|
sizeof(uint32_t) * header.indexCount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshWriter::WriteAnimHeader(FileReference file, AnimDataHeader const& header)
|
||||||
|
{
|
||||||
|
auto constexpr intSize = sizeof(uint32_t);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&header.charCount),
|
||||||
|
intSize
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&header.animNodeCount),
|
||||||
|
intSize
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(header.nodeHeaders.data()),
|
||||||
|
sizeof(AnimNodeInfo) * header.nodeHeaders.size()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshWriter::WriteAnimData(FileReference file, AnimDataHeader const& header, AnimData const& data)
|
||||||
|
{
|
||||||
|
file.write(
|
||||||
|
data.name.data(),
|
||||||
|
header.charCount
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&data.duration),
|
||||||
|
sizeof(double)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&data.ticksPerSecond),
|
||||||
|
sizeof(double)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (auto i{0}; i < header.animNodeCount; ++i)
|
||||||
|
{
|
||||||
|
WriteAnimNode(file, header.nodeHeaders[i], data.nodeChannels[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshWriter::WriteAnimNode(FileReference file, AnimNodeInfo const& info, AnimNode const& node)
|
||||||
|
{
|
||||||
|
file.write(
|
||||||
|
node.name.data(),
|
||||||
|
info.charCount
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&node.pre),
|
||||||
|
sizeof(AnimationBehaviour)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&node.post),
|
||||||
|
sizeof(AnimationBehaviour)
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(node.positionKeys.data()),
|
||||||
|
sizeof(PositionKey) * node.positionKeys.size()
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(node.rotationKeys.data()),
|
||||||
|
sizeof(RotationKey) * node.rotationKeys.size()
|
||||||
|
);
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(node.scaleKeys.data()),
|
||||||
|
sizeof(ScaleKey) * node.scaleKeys.size()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MeshWriter::WriteHeaders(FileReference file, ModelConstRef asset)
|
||||||
|
{
|
||||||
|
for (auto const& header : asset.meshHeaders)
|
||||||
|
{
|
||||||
|
WriteMeshHeader(file, header);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const& header : asset.animHeaders)
|
||||||
|
{
|
||||||
|
WriteAnimHeader(file, header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshWriter::WriteData(FileReference file, ModelConstRef asset)
|
||||||
|
{
|
||||||
|
for (auto i {0}; i < asset.meshes.size(); ++i)
|
||||||
|
{
|
||||||
|
WriteMeshData(file, asset.meshHeaders[i], asset.meshes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i {0}; i < asset.anims.size(); ++i)
|
||||||
|
{
|
||||||
|
WriteAnimData(file, asset.animHeaders[i], asset.anims[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshWriter::CompileMeshBinary(AssetPath path, ModelAsset const& asset) noexcept
|
||||||
|
{
|
||||||
|
std::string newPath{ path.string().substr(0, path.string().find_last_of('.')) };
|
||||||
|
newPath += MODEL_EXTENSION;
|
||||||
|
|
||||||
|
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
|
||||||
|
if (!file.is_open())
|
||||||
|
{
|
||||||
|
std::cout << "Unable to open file for write: " << newPath << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.write(
|
||||||
|
reinterpret_cast<char const*>(&asset.header),
|
||||||
|
sizeof(asset.header)
|
||||||
|
);
|
||||||
|
|
||||||
|
WriteHeaders(file, asset);
|
||||||
|
WriteData(file, asset);
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* \file MeshWriter.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \date 19 November 2022
|
||||||
|
* \brief
|
||||||
|
*
|
||||||
|
* \copyright Copyright (c) 2021 Digipen Institute of Technology. Reproduction
|
||||||
|
* or disclosure of this file or its contents without the prior
|
||||||
|
* written consent of Digipen Institute of Technology is prohibited.
|
||||||
|
******************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AssetMacros.h"
|
||||||
|
#include "Types/ModelAsset.h"
|
||||||
|
|
||||||
|
namespace SH_COMP
|
||||||
|
{
|
||||||
|
struct MeshWriter
|
||||||
|
{
|
||||||
|
using FileReference = std::ofstream&;
|
||||||
|
using ModelConstRef = ModelAsset const&;
|
||||||
|
|
||||||
|
static void WriteMeshHeader(FileReference file, MeshDataHeader const& header);
|
||||||
|
static void WriteMeshData(FileReference file, MeshDataHeader const& header, MeshData const& asset);
|
||||||
|
|
||||||
|
static void WriteAnimHeader(FileReference file, AnimDataHeader const& header);
|
||||||
|
static void WriteAnimData(FileReference file, AnimDataHeader const& header, AnimData const& data);
|
||||||
|
static void WriteAnimNode(FileReference file, AnimNodeInfo const& info, AnimNode const& node);
|
||||||
|
|
||||||
|
static void WriteHeaders(FileReference file, ModelConstRef asset);
|
||||||
|
static void WriteData(FileReference file, ModelConstRef asset);
|
||||||
|
|
||||||
|
static void CompileMeshBinary(AssetPath path, ModelConstRef asset) noexcept;
|
||||||
|
};
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ namespace SH_COMP
|
||||||
enum class AnimationBehaviour : uint8_t
|
enum class AnimationBehaviour : uint8_t
|
||||||
{
|
{
|
||||||
DEFAULT = 0x0,
|
DEFAULT = 0x0,
|
||||||
CONSTNAT = 0x1,
|
CONSTANT = 0x1,
|
||||||
LINEAR = 0x2,
|
LINEAR = 0x2,
|
||||||
REPEAT = 0x3
|
REPEAT = 0x3
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,12 +23,12 @@ namespace SH_COMP
|
||||||
struct RigNode
|
struct RigNode
|
||||||
{
|
{
|
||||||
uint32_t idRef;
|
uint32_t idRef;
|
||||||
std::vector<uint32_t> children;
|
std::vector<RigNode*> children;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RigData
|
struct RigData
|
||||||
{
|
{
|
||||||
std::map<uint32_t, RigNodeData> nodeDataCollection;
|
std::map<uint32_t, RigNodeData> nodeDataCollection;
|
||||||
RigNode root;
|
RigNode* root;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ int main(int argc, char* argv[])
|
||||||
// SH_COMP::MeshCompiler::LoadAndCompile(path);
|
// SH_COMP::MeshCompiler::LoadAndCompile(path);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
SH_COMP::MeshCompiler::LoadAndCompile("Racoon.fbx");
|
SH_COMP::MeshCompiler::LoadAndCompile("Raccoon.gltf");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue