Parse and build all animation data and headers for write
Added functions for writing animation headers and data [NOT YET IMPLEMENTED]
This commit is contained in:
parent
03c17ca5d4
commit
7cc7c51fd9
|
@ -148,17 +148,42 @@ namespace SH_COMP
|
||||||
|
|
||||||
void MeshCompiler::BuildHeaders(ModelAsset& asset) noexcept
|
void MeshCompiler::BuildHeaders(ModelAsset& asset) noexcept
|
||||||
{
|
{
|
||||||
for (auto const& mesh : asset.meshes)
|
// Mesh Headers
|
||||||
|
asset.meshHeaders.resize(asset.meshes.size());
|
||||||
|
asset.header.meshCount = asset.meshes.size();
|
||||||
|
for (auto i{0}; i < asset.header.meshCount; ++i)
|
||||||
{
|
{
|
||||||
asset.headers.emplace_back();
|
auto const& mesh = asset.meshes[i];
|
||||||
auto& head = asset.headers.back();
|
auto& head = asset.meshHeaders[i];
|
||||||
|
|
||||||
head.charCount = mesh.name.size();
|
head.charCount = mesh.name.size();
|
||||||
head.indexCount = mesh.indices.size();
|
head.indexCount = mesh.indices.size();
|
||||||
head.vertexCount = mesh.vertexPosition.size();
|
head.vertexCount = mesh.vertexPosition.size();
|
||||||
head.boneCount = mesh.bonesInfo.size();
|
head.boneCount = mesh.bonesInfo.size();
|
||||||
|
}
|
||||||
|
|
||||||
asset.header.meshCount++;
|
// Anim Headers
|
||||||
|
asset.animHeaders.resize(asset.anims.size());
|
||||||
|
asset.header.animCount = asset.anims.size();
|
||||||
|
for (auto i{0}; i < asset.header.animCount; ++i)
|
||||||
|
{
|
||||||
|
auto const& anim = asset.anims[i];
|
||||||
|
auto& head = asset.animHeaders[i];
|
||||||
|
|
||||||
|
head.charCount = anim.name.size();
|
||||||
|
head.animNodeCount = anim.nodeChannels.size();
|
||||||
|
head.nodeHeaders.resize(head.animNodeCount);
|
||||||
|
|
||||||
|
for (auto j{0}; i < head.animNodeCount; ++j)
|
||||||
|
{
|
||||||
|
auto const& animNode = anim.nodeChannels[j];
|
||||||
|
auto& nodeHeader = head.nodeHeaders[j];
|
||||||
|
|
||||||
|
nodeHeader.charCount = animNode.name.size();
|
||||||
|
nodeHeader.posKeyCount = animNode.positionKeys.size();
|
||||||
|
nodeHeader.rotKeyCount = animNode.rotationKeys.size();
|
||||||
|
nodeHeader.scaKeyCount = animNode.scaleKeys.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,89 +231,25 @@ namespace SH_COMP
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshCompiler::LoadFromFile(AssetPath path, ModelAsset& asset) noexcept
|
void MeshCompiler::WriteAnimHeader(FileReference file, AnimDataHeader const& header)
|
||||||
{
|
{
|
||||||
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_FindInvalidData // detect invalid model data, such as invalid normal vectors
|
|
||||||
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
|
|
||||||
| aiProcess_ValidateDataStructure
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!scene || !scene->HasMeshes())
|
|
||||||
{
|
|
||||||
std::cout << "ERROR in GLTF::ASSIMP: " << aiImporter.GetErrorString() << "\nFile: " << path.string() << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<AnimationAsset> anims;
|
|
||||||
|
|
||||||
ParseAnimations(*scene, anims);
|
|
||||||
|
|
||||||
ProcessNode(*scene->mRootNode, *scene, asset.meshes, asset.rig.root);
|
|
||||||
|
|
||||||
aiImporter.FreeScene();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshCompiler::CompileMeshBinary(AssetPath path, ModelAsset const& asset) noexcept
|
void MeshCompiler::WriteAnimData(FileReference file, AnimDataHeader const& header, AnimData& data)
|
||||||
{
|
{
|
||||||
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)
|
|
||||||
);
|
|
||||||
|
|
||||||
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::BuildArmature(aiNode const& baseNode, RigNode*& root) noexcept
|
void MeshCompiler::WriteHeaders(FileReference file, ModelConstRef asset)
|
||||||
{
|
{
|
||||||
RigNode* start = new RigNode();
|
|
||||||
|
|
||||||
CopyNode(baseNode, start);
|
|
||||||
|
|
||||||
root = start->children[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshCompiler::CopyNode(aiNode const& source, RigNode* parent) noexcept
|
void MeshCompiler::WriteData(FileReference file, ModelConstRef asset)
|
||||||
{
|
{
|
||||||
RigNode* current = new RigNode();
|
|
||||||
current->name = source.mName.C_Str();
|
|
||||||
std::memcpy(¤t->transform, &source.mTransformation, sizeof(SHMat4));
|
|
||||||
|
|
||||||
for (auto i {0}; i < source.mNumChildren; ++i)
|
|
||||||
{
|
|
||||||
CopyNode(*source.mChildren[i], current);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent)
|
|
||||||
{
|
|
||||||
parent->children.push_back(current);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshCompiler::ParseAnimations(aiScene const& scene, std::vector<AnimationAsset>& anims) noexcept
|
void MeshCompiler::ParseAnimations(aiScene const& scene, std::vector<AnimData>& anims) noexcept
|
||||||
{
|
{
|
||||||
|
|
||||||
// Size and read for number of animation clips
|
// Size and read for number of animation clips
|
||||||
anims.resize(scene.mNumAnimations);
|
anims.resize(scene.mNumAnimations);
|
||||||
for (auto i {0}; i < scene.mNumAnimations; ++i)
|
for (auto i {0}; i < scene.mNumAnimations; ++i)
|
||||||
|
@ -352,6 +313,86 @@ namespace SH_COMP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MeshCompiler::LoadFromFile(AssetPath path, ModelAsset& 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_FindInvalidData // detect invalid model data, such as invalid normal vectors
|
||||||
|
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
|
||||||
|
| aiProcess_ValidateDataStructure
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!scene || !scene->HasMeshes())
|
||||||
|
{
|
||||||
|
std::cout << "ERROR in GLTF::ASSIMP: " << aiImporter.GetErrorString() << "\nFile: " << path.string() << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseAnimations(*scene, asset.anims);
|
||||||
|
|
||||||
|
ProcessNode(*scene->mRootNode, *scene, asset.meshes, asset.rig.root);
|
||||||
|
|
||||||
|
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)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Write Meshes
|
||||||
|
for (auto i {0}; i < asset.meshHeaders.size(); ++i)
|
||||||
|
{
|
||||||
|
WriteMeshHeader(file, asset.meshHeaders[i]);
|
||||||
|
WriteMeshData(file, asset.meshHeaders[i], asset.meshes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshCompiler::BuildArmature(aiNode const& baseNode, RigNode*& root) noexcept
|
||||||
|
{
|
||||||
|
RigNode* start = new RigNode();
|
||||||
|
|
||||||
|
CopyNode(baseNode, start);
|
||||||
|
|
||||||
|
root = start->children[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshCompiler::CopyNode(aiNode const& source, RigNode* parent) noexcept
|
||||||
|
{
|
||||||
|
RigNode* current = new RigNode();
|
||||||
|
current->name = source.mName.C_Str();
|
||||||
|
std::memcpy(¤t->transform, &source.mTransformation, sizeof(SHMat4));
|
||||||
|
|
||||||
|
for (auto i {0}; i < source.mNumChildren; ++i)
|
||||||
|
{
|
||||||
|
CopyNode(*source.mChildren[i], current);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent)
|
||||||
|
{
|
||||||
|
parent->children.push_back(current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MeshCompiler::LoadAndCompile(AssetPath path) noexcept
|
void MeshCompiler::LoadAndCompile(AssetPath path) noexcept
|
||||||
{
|
{
|
||||||
auto const asset = new ModelAsset();
|
auto const asset = new ModelAsset();
|
||||||
|
|
|
@ -26,25 +26,35 @@ namespace SH_COMP
|
||||||
{
|
{
|
||||||
|
|
||||||
using MeshVectorRef = std::vector<MeshData>&;
|
using MeshVectorRef = std::vector<MeshData>&;
|
||||||
using AnimVectorRef = std::vector<AnimationAsset>&;
|
using AnimVectorRef = std::vector<AnimData>&;
|
||||||
|
|
||||||
|
using FileReference = std::ofstream&;
|
||||||
|
using ModelConstRef = ModelAsset const&;
|
||||||
|
using ModelRef = ModelAsset&;
|
||||||
|
|
||||||
static Assimp::Importer aiImporter;
|
static Assimp::Importer aiImporter;
|
||||||
|
|
||||||
static void ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes, RigNode*& root) noexcept;
|
static void ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes, RigNode*& root) noexcept;
|
||||||
//static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept;
|
//static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept;
|
||||||
static void GetMesh(aiMesh const& mesh, MeshData& meshData) noexcept;
|
static void GetMesh(aiMesh const& mesh, MeshData& meshData) noexcept;
|
||||||
static void BuildHeaders(ModelAsset& asset) noexcept;
|
static void BuildHeaders(ModelRef asset) noexcept;
|
||||||
|
|
||||||
static void WriteMeshHeader(std::ofstream& file, MeshDataHeader const& header);
|
static void WriteMeshHeader(FileReference file, MeshDataHeader const& header);
|
||||||
static void WriteMeshData(std::ofstream& file, MeshDataHeader const& header, MeshData const& asset);
|
static void WriteMeshData(FileReference file, MeshDataHeader const& header, MeshData const& asset);
|
||||||
|
|
||||||
static void LoadFromFile(AssetPath path, ModelAsset& asset) noexcept;
|
static void WriteAnimHeader(FileReference file, AnimDataHeader const& header);
|
||||||
static void CompileMeshBinary(AssetPath path, ModelAsset const& asset) noexcept;
|
static void WriteAnimData(FileReference file, AnimDataHeader const& header, AnimData cosnt& data);
|
||||||
|
|
||||||
|
static void WriteHeaders(FileReference file, ModelConstRef asset);
|
||||||
|
static void WriteData(FileReference file, ModelConstRef asset);
|
||||||
|
|
||||||
|
static void LoadFromFile(AssetPath path, ModelRef asset) noexcept;
|
||||||
|
static void CompileMeshBinary(AssetPath path, ModelConstRef asset) noexcept;
|
||||||
|
|
||||||
static void BuildArmature(aiNode const& node, RigNode*& root) noexcept;
|
static void BuildArmature(aiNode const& node, RigNode*& root) noexcept;
|
||||||
static void CopyNode(aiNode const& source, RigNode* parent) noexcept;
|
static void CopyNode(aiNode const& source, RigNode* parent) noexcept;
|
||||||
|
|
||||||
static void ParseAnimations(aiScene const& scene, std::vector<AnimationAsset>& anims) 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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,24 +16,66 @@
|
||||||
|
|
||||||
namespace SH_COMP
|
namespace SH_COMP
|
||||||
{
|
{
|
||||||
struct AnimationKey
|
enum class AnimationBehaviour : uint8_t
|
||||||
|
{
|
||||||
|
DEFAULT = 0x0,
|
||||||
|
CONSTNAT = 0x1,
|
||||||
|
LINEAR = 0x2,
|
||||||
|
REPEAT = 0x3
|
||||||
|
};
|
||||||
|
|
||||||
|
// Smallest data containers
|
||||||
|
struct PositionKey
|
||||||
|
{
|
||||||
|
float time;
|
||||||
|
SHVec3 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RotationKey
|
||||||
{
|
{
|
||||||
float time;
|
float time;
|
||||||
SHVec4 value;
|
SHVec4 value;
|
||||||
};
|
};
|
||||||
struct AnimationNode
|
|
||||||
|
struct ScaleKey
|
||||||
{
|
{
|
||||||
std::string name;
|
float time;
|
||||||
std::vector<AnimationKey> positionKeys;
|
SHVec3 value;
|
||||||
std::vector<AnimationKey> rotationKeys;
|
|
||||||
std::vector<AnimationKey> scaleKeys;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AnimationAsset
|
// Headers for read/write
|
||||||
|
struct AnimNodeInfo
|
||||||
|
{
|
||||||
|
uint32_t charCount;
|
||||||
|
uint32_t posKeyCount;
|
||||||
|
uint32_t rotKeyCount;
|
||||||
|
uint32_t scaKeyCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AnimDataHeader
|
||||||
|
{
|
||||||
|
uint32_t charCount;
|
||||||
|
uint32_t animNodeCount;
|
||||||
|
std::vector<AnimNodeInfo> nodeHeaders;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Main data containers
|
||||||
|
struct AnimNode
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::vector<PositionKey> positionKeys;
|
||||||
|
std::vector<RotationKey> rotationKeys;
|
||||||
|
std::vector<ScaleKey> scaleKeys;
|
||||||
|
|
||||||
|
AnimationBehaviour pre;
|
||||||
|
AnimationBehaviour post;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AnimData
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
std::vector<AnimationNode> nodeChannels;
|
std::vector<AnimNode> nodeChannels;
|
||||||
//std::vector<aiMeshAnim*> meshChannels;
|
//std::vector<aiMeshAnim*> meshChannels;
|
||||||
//std::vector<aiMeshMorphAnim*> morphMeshChannels;
|
//std::vector<aiMeshMorphAnim*> morphMeshChannels;
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "MeshAsset.h"
|
#include "MeshAsset.h"
|
||||||
|
#include "AnimationAsset.h"
|
||||||
|
|
||||||
namespace SH_COMP
|
namespace SH_COMP
|
||||||
{
|
{
|
||||||
|
@ -35,13 +36,18 @@ namespace SH_COMP
|
||||||
struct ModelAssetHeader
|
struct ModelAssetHeader
|
||||||
{
|
{
|
||||||
size_t meshCount;
|
size_t meshCount;
|
||||||
|
size_t animCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ModelAsset
|
struct ModelAsset
|
||||||
{
|
{
|
||||||
ModelAssetHeader header;
|
ModelAssetHeader header;
|
||||||
RigData rig;
|
RigData rig;
|
||||||
std::vector<MeshDataHeader> headers;
|
|
||||||
|
std::vector<MeshDataHeader> meshHeaders;
|
||||||
|
std::vector<AnimDataHeader> animHeaders;
|
||||||
|
|
||||||
std::vector<MeshData> meshes;
|
std::vector<MeshData> meshes;
|
||||||
|
std::vector<AnimData> anims;
|
||||||
};
|
};
|
||||||
}
|
}
|
Loading…
Reference in New Issue