diff --git a/.gitignore b/.gitignore index 0977673..868e693 100644 --- a/.gitignore +++ b/.gitignore @@ -356,3 +356,5 @@ MigrationBackup/ Premake/ *.sln + +Dependencies/ diff --git a/premake5.lua b/premake5.lua index 7fe839f..d9caa58 100644 --- a/premake5.lua +++ b/premake5.lua @@ -8,13 +8,6 @@ project "ModelCompileLibrary" objdir (interdir) systemversion "latest" - - configurations - { - "Debug", - "Release", - "Publish" - } files { diff --git a/src/SHAssetMacros.h b/src/AssetMacros.h similarity index 100% rename from src/SHAssetMacros.h rename to src/AssetMacros.h diff --git a/src/Libraries/SHMeshCompiler.cpp b/src/Libraries/MeshCompiler.cpp similarity index 61% rename from src/Libraries/SHMeshCompiler.cpp rename to src/Libraries/MeshCompiler.cpp index 0e29ec4..cd7eea7 100644 --- a/src/Libraries/SHMeshCompiler.cpp +++ b/src/Libraries/MeshCompiler.cpp @@ -1,8 +1,8 @@ /*************************************************************************//** - * \file SHMeshCompiler.cpp + * \file MeshCompiler.cpp * \author Loh Xiao Qi * \date 30 September 2022 - * \brief Library to write data in SHMeshAsset into binary file for faster + * \brief Library to write data in MeshAsset into binary file for faster * loading in the future * * @@ -10,23 +10,24 @@ * disclosure of this file or its contents without the prior written consent * of DigiPen Institute of Technology is prohibited. *****************************************************************************/ -#include "SHMeshCompiler.h" +#include "MeshCompiler.h" #include #include #include -namespace SHADE +namespace SH_COMP { - Assimp::Importer SHMeshCompiler::aiImporter; + Assimp::Importer MeshCompiler::aiImporter; - void SHMeshCompiler::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept + void MeshCompiler::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept { for (size_t i{ 0 }; i < node.mNumMeshes; ++i) { aiMesh* mesh = scene.mMeshes[node.mMeshes[i]]; - meshes.push_back(ProcessMesh(*mesh)); + meshes.emplace_back(); + GetMesh(*mesh, meshes.back()); } for (size_t i{ 0 }; i < node.mNumChildren; ++i) @@ -35,11 +36,11 @@ namespace SHADE } } - void SHMeshCompiler::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept + void MeshCompiler::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept { if (scene.HasAnimations()) { - std::vector anims(scene.mNumAnimations); + std::vector anims(scene.mNumAnimations); for (auto i{ 0 }; i < scene.mNumAnimations; ++i) { auto const& anim{ *scene.mAnimations[i] }; @@ -56,11 +57,12 @@ namespace SHADE } } - SHMeshAsset* SHMeshCompiler::ProcessMesh(aiMesh const& mesh) noexcept + void MeshCompiler::GetMesh(aiMesh const& mesh, MeshData& meshData) noexcept { - SHMeshAsset* result = new SHMeshAsset(); - result->compiled = false; - result->changed = false; + meshData.vertexPosition.reserve(mesh.mNumVertices); + meshData.vertexNormal.reserve(mesh.mNumVertices); + meshData.vertexTangent.reserve(mesh.mNumVertices); + meshData.texCoords.reserve(mesh.mNumVertices); for (size_t i{ 0 }; i < mesh.mNumVertices; ++i) { @@ -69,7 +71,7 @@ namespace SHADE vertex.x = mesh.mVertices[i].x; vertex.y = mesh.mVertices[i].y; vertex.z = mesh.mVertices[i].z; - result->vertexPosition.push_back(vertex); + meshData.vertexPosition.push_back(vertex); // Tex coords SHVec2 texCoord{ 0.f, 0.f }; @@ -78,7 +80,7 @@ namespace SHADE texCoord.x = mesh.mTextureCoords[0][i].x; texCoord.y = mesh.mTextureCoords[0][i].y; } - result->texCoords.push_back(texCoord); + meshData.texCoords.push_back(texCoord); // Normals SHVec3 normal{ 0.f, 0.f, 0.f }; @@ -88,7 +90,7 @@ namespace SHADE normal.y = mesh.mNormals[i].y; normal.z = mesh.mNormals[i].z; } - result->vertexNormal.push_back(normal); + meshData.vertexNormal.push_back(normal); // Tangent SHVec3 tangent{ 0.f, 0.f, 0.f }; @@ -98,7 +100,7 @@ namespace SHADE tangent.y = mesh.mTangents[i].y; tangent.z = mesh.mTangents[i].z; } - result->vertexTangent.push_back(tangent); + meshData.vertexTangent.push_back(tangent); } for (size_t i{ 0 }; i < mesh.mNumFaces; ++i) @@ -106,68 +108,46 @@ namespace SHADE aiFace face = mesh.mFaces[i]; for (size_t j{ 0 }; j < face.mNumIndices; ++j) { - result->indices.push_back(face.mIndices[j]); + meshData.indices.push_back(face.mIndices[j]); } } - result->header.vertexCount = static_cast(result->vertexPosition.size()); - result->header.indexCount = static_cast(result->indices.size()); - result->header.name = mesh.mName.C_Str(); - - return result; + meshData.name = mesh.mName.C_Str(); } - void SHMeshCompiler::LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept + void MeshCompiler::BuildHeaders(MeshAsset& asset) noexcept { - const aiScene* scene = aiImporter.ReadFile(path.string().c_str(), - aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons - | aiProcess_GenUVCoords // Convert any type of mapping to uv mapping - | aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...) - | aiProcess_FindInstances // search for instanced meshes and remove them by references to one master - | aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible - | aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing - | aiProcess_RemoveRedundantMaterials // remove redundant materials - | aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors - | aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs - ); - - if (!scene || !scene->HasMeshes()) + for (auto const& mesh : asset.meshes) { - std::cout << "ERROR in GLTF::ASSIMP: " << aiImporter.GetErrorString() << "\nFile: " << path.string() << std::endl; - return; + asset.headers.emplace_back(); + auto& head = asset.headers.back(); + + head.charCount = mesh.name.size(); + head.indexCount = mesh.indices.size(); + head.vertexCount = mesh.vertexPosition.size(); + + asset.header.meshCount++; } - - //ExtractAnimations(*scene, anims); - - ProcessNode(*scene->mRootNode, *scene, meshes); - - aiImporter.FreeScene(); } - std::optional SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept + void MeshCompiler::WriteMeshHeader(std::ofstream& file, MeshDataHeader const& header) { - std::string newPath{ path.string() + asset.header.name + MESH_EXTENSION.data() }; + file.write( + reinterpret_cast(&header), + sizeof(MeshDataHeader) + ); + } - 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 {}; - } + void MeshCompiler::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( - reinterpret_cast(&(asset.header.vertexCount)), - sizeof(uint32_t) + asset.name.c_str(), + header.charCount ); - file.write( - reinterpret_cast(&(asset.header.indexCount)), - sizeof(uint32_t) - ); - - auto const vertexVec3Byte{ sizeof(SHVec3) * asset.header.vertexCount }; - auto const vertexVec2Byte{ sizeof(SHVec2) * asset.header.vertexCount }; - file.write( reinterpret_cast(asset.vertexPosition.data()), vertexVec3Byte @@ -190,24 +170,71 @@ namespace SHADE file.write( reinterpret_cast(asset.indices.data()), - sizeof(uint32_t) * asset.header.indexCount + sizeof(uint32_t) * header.indexCount + ); + } + + void MeshCompiler::LoadFromFile(AssetPath path, MeshAsset& asset) noexcept + { + const aiScene* scene = aiImporter.ReadFile(path.string().c_str(), + aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons + | aiProcess_GenUVCoords // Convert any type of mapping to uv mapping + | aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...) + | aiProcess_FindInstances // search for instanced meshes and remove them by references to one master + | aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible + | aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing + | aiProcess_RemoveRedundantMaterials // remove redundant materials + | aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors + | aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs ); - file.close(); + if (!scene || !scene->HasMeshes()) + { + std::cout << "ERROR in GLTF::ASSIMP: " << aiImporter.GetErrorString() << "\nFile: " << path.string() << std::endl; + return; + } - return newPath; + //ExtractAnimations(*scene, anims); + + ProcessNode(*scene->mRootNode, *scene, asset.meshes); + + aiImporter.FreeScene(); } - void SHMeshCompiler::LoadAndCompile(AssetPath path) noexcept + void MeshCompiler::CompileMeshBinary(AssetPath path, MeshAsset const& asset) noexcept { - std::vector meshes; - std::vector anims; + std::string newPath{ path.string().substr(0, path.string().find_last_of('.')) }; + newPath += MESH_EXTENSION; - LoadFromFile(path, meshes, anims); - - for (auto const& mesh : meshes) + std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc }; + if (!file.is_open()) { - CompileMeshBinary(*mesh, path.parent_path().string() + '/'); + std::cout << "Unable to open file for write: " << newPath << std::endl; + return; } + + file.write( + reinterpret_cast(&asset.header), + sizeof(asset.header) + ); + + for (auto i {0}; i < asset.headers.size(); ++i) + { + WriteMeshHeader(file, asset.headers[i]); + WriteMeshData(file, asset.headers[i], asset.meshes[i]); + } + + file.close(); + } + + void MeshCompiler::LoadAndCompile(AssetPath path) noexcept + { + auto const asset = new MeshAsset(); + + LoadFromFile(path, *asset); + BuildHeaders(*asset); + CompileMeshBinary(path, *asset); + + delete asset; } } diff --git a/src/Libraries/SHMeshCompiler.h b/src/Libraries/MeshCompiler.h similarity index 52% rename from src/Libraries/SHMeshCompiler.h rename to src/Libraries/MeshCompiler.h index 46fb9d1..a224898 100644 --- a/src/Libraries/SHMeshCompiler.h +++ b/src/Libraries/MeshCompiler.h @@ -2,7 +2,7 @@ * \file SHMeshCompiler.h * \author Loh Xiao Qi * \date 30 September 2022 - * \brief Library to write data in SHMeshAsset into binary file for faster + * \brief Library to write data in MeshAsset into binary file for faster * loading in the future * * @@ -16,24 +16,30 @@ #include #include -#include "Types/SHAnimationAsset.h" -#include "Types/SHMeshAsset.h" -#include "SHAssetMacros.h" +#include "Types/AnimationAsset.h" +#include "Types/MeshAsset.h" +#include "AssetMacros.h" -namespace SHADE +namespace SH_COMP { - class SHMeshCompiler - { + class MeshCompiler + { - using MeshVectorRef = std::vector&; - using AnimVectorRef = std::vector&; + using MeshVectorRef = std::vector&; + using AnimVectorRef = std::vector&; static Assimp::Importer aiImporter; + static void ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept; static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept; - static SHMeshAsset* ProcessMesh(aiMesh const& mesh) noexcept; - static void LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept; - static std::optional CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept; + static void GetMesh(aiMesh const& mesh, MeshData& meshData) noexcept; + static void BuildHeaders(MeshAsset& asset) noexcept; + + static void WriteMeshHeader(std::ofstream& file, MeshDataHeader const& header); + static void WriteMeshData(std::ofstream& file, MeshDataHeader const& header, MeshData const& data); + + static void LoadFromFile(AssetPath path, MeshAsset& asset) noexcept; + static void CompileMeshBinary(AssetPath path, MeshAsset const& asset) noexcept; public: static void LoadAndCompile(AssetPath path) noexcept; diff --git a/src/Types/SHAnimationAsset.h b/src/Types/AnimationAsset.h similarity index 94% rename from src/Types/SHAnimationAsset.h rename to src/Types/AnimationAsset.h index 38b2e11..773237f 100644 --- a/src/Types/SHAnimationAsset.h +++ b/src/Types/AnimationAsset.h @@ -13,9 +13,9 @@ #include #include -namespace SHADE +namespace SH_COMP { - struct SHAnimationAsset + struct AnimationAsset { std::string name; diff --git a/src/Types/SHMeshAsset.h b/src/Types/MeshAsset.h similarity index 77% rename from src/Types/SHMeshAsset.h rename to src/Types/MeshAsset.h index 52d5c59..827e3b8 100644 --- a/src/Types/SHMeshAsset.h +++ b/src/Types/MeshAsset.h @@ -13,8 +13,9 @@ #pragma once #include +#include -namespace SHADE +namespace SH_COMP { struct SHVec2 @@ -27,24 +28,32 @@ namespace SHADE float x, y, z; }; - struct SHMeshAssetHeader + struct MeshDataHeader { uint32_t vertexCount; uint32_t indexCount; - std::string name; + uint32_t charCount; }; - struct SHMeshAsset + struct MeshData { - bool compiled; - bool changed; - - SHMeshAssetHeader header; - + std::string name; std::vector vertexPosition; std::vector vertexTangent; std::vector vertexNormal; std::vector texCoords; std::vector indices; }; + + struct MeshAssetHeader + { + size_t meshCount; + }; + + struct MeshAsset + { + MeshAssetHeader header; + std::vector headers; + std::vector meshes; + }; } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index de1ab95..c15daa5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,7 +8,7 @@ * or disclosure of this file or its contents without the prior * written consent of Digipen Institute of Technology is prohibited. ******************************************************************************/ -#include "Libraries/SHMeshCompiler.h" +#include "Libraries/MeshCompiler.h" #include #include