Ported all mesh and animation asset related file into repo

Created premake to build solution and project 
Changed loader and compiler to be self contained and take in paths relative to "local"
This commit is contained in:
Xiao Qi 2022-10-19 18:37:27 +08:00
parent 5ba06db572
commit 70b6045453
13 changed files with 615 additions and 0 deletions

10
.gitignore vendored
View File

@ -348,3 +348,13 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
*.vcxproj
*.filters
Premake/
Dependencies/assimp
*.sln

View File

@ -0,0 +1,47 @@
#include "Types/SHAnimationAsset.h"
#include "Types/SHMeshAsset.h"
#include "Libraries/SHAssimpLibrary.h"
#include "Libraries/SHMeshCompiler.h"
#include <vector>
#include <filesystem>
int main(int argc, char* argv[])
{
SHADE::MeshVector meshes;
SHADE::AnimVector anims;
std::vector<std::string> paths;
if (argc == 1)
{
for (auto const& dir : std::filesystem::recursive_directory_iterator{"./Assets/"})
{
if (dir.path().extension().string() == GLTF_EXTENSION)
{
paths.push_back(dir.path().string());
}
}
}
else if (argc > 1)
{
for (int i { 1 }; i < argc; ++i)
{
paths.emplace_back(argv[i]);
}
}
for (auto const& path : paths)
{
SHADE::SHAssimpLibrary::LoadFromFile(path, meshes, anims);
}
for (auto const& mesh : meshes)
{
SHADE::SHMeshCompiler::CompileMeshBinary(mesh);
}
return 0;
}

View File

@ -0,0 +1,60 @@
project "Assimp Compile Library"
kind "ConsoleApp"
language "C++"
cppdialect "C++20"
targetdir (outputdir)
objdir (interdir)
systemversion "latest"
files
{
"%{prj.location}/src/**.h",
"%{prj.location}/src/**.cpp",
}
externalincludedirs
{
"%{IncludeDir.assimp}\\include"
}
includedirs
{
"%{prj.location}/src",
}
externalwarnings "Off"
libdirs
{
"%{IncludeDir.assimp}/lib/Debug",
"%{IncludeDir.assimp}/lib/Release"
}
flags
{
"MultiProcessorCompile"
}
filter "configurations:Debug"
postbuildcommands
{
"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Debug\\assimp-vc142-mtd.dll\" \"$(OutDir)\""
}
filter "configurations:Release"
postbuildcommands
{
"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\""
}
warnings 'Extra'
filter "configurations:Debug"
symbols "On"
defines {"_DEBUG", "SHEDITOR"}
links{"assimp-vc142-mtd.lib"}
filter "configurations:Release"
optimize "On"
defines{"_RELEASE", "SHEDITOR"}
links{"assimp-vc142-mt.lib"}

View File

@ -0,0 +1,148 @@
/*************************************************************************//**
* \file SHAssimpLibrary.cpp
* \author Loh Xiao Qi
* \date October 2022
* \brief
*
* Copyright (C) 2022 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 "SHAssimpLibrary.h"
#include <assimp/postprocess.h>
#include <iostream>
#include <algorithm>
namespace SHADE
{
Assimp::Importer SHAssimpLibrary::aiImporter;
void SHAssimpLibrary::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.emplace_back();
ProcessMesh(*mesh, meshes.back());
}
for (size_t i{ 0 }; i < node.mNumChildren; ++i)
{
ProcessNode(*node.mChildren[i], scene, meshes);
}
}
void SHAssimpLibrary::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept
{
if (scene.HasAnimations())
{
std::vector<SHAnimationAsset> anims(scene.mNumAnimations);
for (auto i{0}; i < scene.mNumAnimations; ++i)
{
auto const& anim {*scene.mAnimations[i]};
anims[i].name = anim.mName.C_Str();
anims[i].duration = anim.mDuration;
anims[i].ticksPerSecond = anim.mTicksPerSecond;
std::copy_n(anim.mChannels, anim.mNumChannels, anims[i].nodeChannels.data());
std::copy_n(anim.mMeshChannels, anim.mNumMeshChannels, anims[i].meshChannels.data());
std::copy_n(anim.mMorphMeshChannels, anim.mNumMorphMeshChannels, anims[i].morphMeshChannels.data());
}
}
}
void SHAssimpLibrary::ProcessMesh(aiMesh const& mesh, SHMeshAsset& meshDest) noexcept
{
meshDest.compiled = false;
meshDest.changed = false;
for (size_t i{0}; i < mesh.mNumVertices; ++i)
{
// Vertex position
SHVec3 vertex;
vertex.x = mesh.mVertices[i].x;
vertex.y = mesh.mVertices[i].y;
vertex.z = mesh.mVertices[i].z;
meshDest.vertexPosition.push_back(vertex);
// Tex coords
SHVec2 texCoord{0.f, 0.f};
if (mesh.mTextureCoords[0])
{
texCoord.x = mesh.mTextureCoords[0][i].x;
texCoord.y = mesh.mTextureCoords[0][i].y;
}
meshDest.texCoords.push_back(texCoord);
// Normals
SHVec3 normal{0.f, 0.f, 0.f};
if (mesh.mNormals)
{
normal.x = mesh.mNormals[i].x;
normal.y = mesh.mNormals[i].y;
normal.z = mesh.mNormals[i].z;
}
meshDest.vertexNormal.push_back(normal);
// Tangent
SHVec3 tangent{0.f, 0.f, 0.f};
if (mesh.mTangents)
{
tangent.x = mesh.mTangents[i].x;
tangent.y = mesh.mTangents[i].y;
tangent.z = mesh.mTangents[i].z;
}
meshDest.vertexTangent.push_back(tangent);
}
for (size_t i {0}; i < mesh.mNumFaces; ++i)
{
aiFace face = mesh.mFaces[i];
for (size_t j{0}; j < face.mNumIndices; ++j)
{
meshDest.indices.push_back(face.mIndices[j]);
}
}
meshDest.header.vertexCount = static_cast<uint32_t>(meshDest.vertexPosition.size());
meshDest.header.indexCount = static_cast<uint32_t>(meshDest.indices.size());
meshDest.header.meshName = mesh.mName.C_Str();
}
void SHAssimpLibrary::LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) 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())
{
std::cout << "ERROR in GLTF::ASSIMP: " << aiImporter.GetErrorString() << "\nFile: " << path.string() << std::endl;
return;
}
ExtractAnimations(*scene, anims);
MeshVector localMesh(scene->mNumMeshes);
ProcessNode(*scene->mRootNode, *scene, localMesh);
for (auto& mesh : localMesh)
{
mesh.parentPath = path.parent_path().string();
}
std::ranges::move(localMesh.begin(), localMesh.end(), meshes.end());
aiImporter.FreeScene();
}
}

View File

@ -0,0 +1,39 @@
/*************************************************************************//**
* \file SHAssimpLibrary.h
* \author Loh Xiao Qi
* \date October 2022
* \brief
*
* Copyright (C) 2022 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 <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <vector>
#include "../SHAssetMacros.h"
#include "../Types/SHMeshAsset.h"
#include "../Types/SHAnimationAsset.h"
namespace SHADE
{
using MeshVector = std::vector<SHMeshAsset>;
using AnimVector = std::vector<SHAnimationAsset>;
class SHAssimpLibrary
{
private:
using MeshVectorRef = std::vector<SHMeshAsset>&;
using AnimVectorRef = std::vector<SHAnimationAsset>&;
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 void ProcessMesh(aiMesh const& mesh, SHMeshAsset& meshDest) noexcept;
public:
static void LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept;
};
}

View File

@ -0,0 +1,70 @@
/*************************************************************************//**
* \file SHMeshCompiler.cpp
* \author Loh Xiao Qi
* \date 30 September 2022
* \brief Library to write data in SHMeshAsset into binary file for faster
* loading in the future
*
*
* Copyright (C) 2022 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 "SHMeshCompiler.h"
#include <fstream>
#include <iostream>
std::string SHADE::SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset) noexcept
{
std::string newPath{ asset.parentPath };
newPath += asset.header.meshName + MESH_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 writing mesh file: " << asset.parentPath << std::endl;
}
file.write(
reinterpret_cast<char const*>(&(asset.header.vertexCount)),
sizeof(uint32_t)
);
file.write(
reinterpret_cast<const char*>(&(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<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) * asset.header.indexCount
);
file.close();
return newPath;
}

View File

@ -0,0 +1,26 @@
/*************************************************************************//**
* \file SHMeshCompiler.h
* \author Loh Xiao Qi
* \date 30 September 2022
* \brief Library to write data in SHMeshAsset into binary file for faster
* loading in the future
*
*
* Copyright (C) 2022 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 "../Types/SHMeshAsset.h"
#include "../SHAssetMacros.h"
namespace SHADE
{
class SHMeshCompiler
{
private:
public:
static std::string CompileMeshBinary(SHMeshAsset const& asset) noexcept;
};
}

View File

@ -0,0 +1,105 @@
/******************************************************************************
* \file SHAssetMacros.h
* \author Loh Xiao Qi
* \brief Macros and typedefs for assets
*
* \copyright Copyright (c) 2022 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
******************************************************************************/
#ifndef SH_ASSET_MACROS_H
#define SH_ASSET_MACROS_H
#include <cstdint>
#include <string>
#include <filesystem>
// FMOD Fwd Declare
namespace FMOD
{
class Sound;
class System;
class ChannelGroup;
class Channel;
}
enum FMOD_RESULT : int;
enum FMOD_SPEAKERMODE : int;
// Typedefs
typedef uint32_t AssetID;
typedef std::string AssetName;
typedef std::filesystem::path AssetPath;
typedef unsigned char* AssetData;
typedef std::string AssetMetaVersion;
typedef std::string AssetExtension;
typedef unsigned char AssetTypeMeta;
typedef FMOD::Sound* SHSound;
// Asset Meta Version
#define ASSET_META_VER "1.0"
// Asset type enum
enum class AssetType : AssetTypeMeta
{
INVALID = 0,
AUDIO = 1,
SHADER,
MATERIAL,
IMAGE,
TEXTURE,
MESH,
SCRIPT,
SCENE,
PREFAB,
AUDIO_WAV,
DDS
};
//Directory
#ifdef _PUBLISH
#define ASSET_ROOT "Assets"
#else
#define ASSET_ROOT "../../Assets"
#endif
// ASSET EXTENSIONS
#define META_EXTENSION ".shmeta"
#define IMAGE_EXTENSION ".png"
#define AUDIO_EXTENSION ".ogg"
#define AUDIO_WAV_EXTENSION ".wav"
#define SHADER_EXTENSION ".glsl"
#define SCRIPT_EXTENSION ".cs"
#define SCENE_EXTENSION ".SHADE"
#define PREFAB_EXTENSION ".SHPrefab"
#define MATERIAL_EXTENSION ".SHMat"
#define TEXTURE_EXTENSION ".shtex"
#define DDS_EXTENSION ".dds"
#define FBX_EXTENSION ".fbx"
#define GLTF_EXTENSION ".gltf"
#define MESH_EXTENSION ".shmesh"
std::string const EXTENSIONS[] = {
AUDIO_EXTENSION,
SHADER_EXTENSION,
MATERIAL_EXTENSION,
IMAGE_EXTENSION,
TEXTURE_EXTENSION,
DDS_EXTENSION,
MESH_EXTENSION,
SCRIPT_EXTENSION,
SCENE_EXTENSION,
PREFAB_EXTENSION,
AUDIO_WAV_EXTENSION,
FBX_EXTENSION,
GLTF_EXTENSION
};
// Error flags
#define FILE_NOT_FOUND_ERR "FILE NOT FOUND"
#define META_NOT_FOUND_ERR "META NOT FOUND"
#define ASSET_NOT_FOUND_ERR "ASSET NOT FOUND"
#define EXT_DOES_NOT_EXIST "TYPE DOES NOT HAVE EXTENSION DEFINED"
#endif // !SH_ASSET_MACROS_H

View File

@ -0,0 +1,29 @@
/*************************************************************************//**
* \file SHAnimationAsset.h
* \author Loh Xiao Qi
* \date October 2022
* \brief
*
* Copyright (C) 2022 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 <vector>
#include <assimp/anim.h>
namespace SHADE
{
struct SHAnimationAsset
{
std::string name;
std::vector<aiNodeAnim*> nodeChannels;
std::vector<aiMeshAnim*> meshChannels;
std::vector<aiMeshMorphAnim*> morphMeshChannels;
double duration;
double ticksPerSecond;
};
}

View File

@ -0,0 +1,52 @@
/*************************************************************************//**
* \file SHMeshAsset.h
* \author Loh Xiao Qi
* \date 30 September 2022
* \brief Struct to contain ready data for loading into GPU. Also used for
* compilation into binary files
*
*
* Copyright (C) 2022 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 <vector>
#include <string>
#include <cstdint>
namespace SHADE
{
struct SHVec3
{
float x, y, z;
};
struct SHVec2
{
float x, y;
};
struct SHMeshAssetHeader
{
uint32_t vertexCount;
uint32_t indexCount;
std::string meshName;
};
struct SHMeshAsset
{
std::string parentPath;
bool compiled;
bool changed;
SHMeshAssetHeader header;
std::vector<SHVec3> vertexPosition;
std::vector<SHVec3> vertexTangent;
std::vector<SHVec3> vertexNormal;
std::vector<SHVec2> texCoords;
std::vector<uint32_t> indices;
};
}

2
Dependencies.bat Normal file
View File

@ -0,0 +1,2 @@
rmdir "Dependencies/assimp" /S /Q
git clone https://github.com/SHADE-DP/assimp.git "Dependencies/assimp"

5
generate.bat Normal file
View File

@ -0,0 +1,5 @@
erase /s /q *.vcxproj
erase /s /q *.vcxproj.filters
call Premake\premake5 vs2019
PAUSE

22
premake5.lua Normal file
View File

@ -0,0 +1,22 @@
IncludeDir = {}
IncludeDir["assimp"] = "%{wks.location}\\Dependencies\\assimp"
workspace "Assimp Compile Library"
architecture "x64"
startproject "Assimp Compile Application"
configurations
{
"Debug",
"Release"
}
flags
{
"MultiProcessorCompile"
}
outputdir = "%{wks.location}/bin/%{cfg.buildcfg}"
interdir = "%{wks.location}/bin_int"
include "Assimp Compile Application"