Merge pull request #2430 from Hugo-Pereira/fix_assimp_export_consistency

[FBX Export] fixed ordering of skin indices and weights, to be consistent between systems
pull/2435/head^2
Kim Kulling 2019-05-04 21:16:34 +02:00 committed by GitHub
commit 4a6b9d716a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 14 additions and 3 deletions

View File

@ -1575,11 +1575,22 @@ void FBXExporter::WriteObjects ()
// one sticky point is that the number of vertices may not match,
// because assimp splits vertices by normal, uv, etc.
// functor for aiNode sorting
struct SortNodeByName
{
bool operator()(const aiNode *lhs, const aiNode *rhs) const
{
return strcmp(lhs->mName.C_Str(), rhs->mName.C_Str()) < 0;
}
};
// first we should mark the skeleton for each mesh.
// the skeleton must include not only the aiBones,
// but also all their parent nodes.
// anything that affects the position of any bone node must be included.
std::vector<std::set<const aiNode*>> skeleton_by_mesh(mScene->mNumMeshes);
// Use SorNodeByName to make sure the exported result will be the same across all systems
// Otherwise the aiNodes of the skeleton would be sorted based on the pointer address, which isn't consistent
std::vector<std::set<const aiNode*, SortNodeByName>> skeleton_by_mesh(mScene->mNumMeshes);
// at the same time we can build a list of all the skeleton nodes,
// which will be used later to mark them as type "limbNode".
std::unordered_set<const aiNode*> limbnodes;
@ -1587,7 +1598,7 @@ void FBXExporter::WriteObjects ()
std::map<std::string,aiNode*> node_by_bone;
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
const aiMesh* m = mScene->mMeshes[mi];
std::set<const aiNode*> skeleton;
std::set<const aiNode*, SortNodeByName> skeleton;
for (size_t bi =0; bi < m->mNumBones; ++bi) {
const aiBone* b = m->mBones[bi];
const std::string name(b->mName.C_Str());
@ -1728,7 +1739,7 @@ void FBXExporter::WriteObjects ()
aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene);
// now make a subdeformer for each bone in the skeleton
const std::set<const aiNode*> &skeleton = skeleton_by_mesh[mi];
const std::set<const aiNode*, SortNodeByName> skeleton= skeleton_by_mesh[mi];
for (const aiNode* bone_node : skeleton) {
// if there's a bone for this node, find it
const aiBone* b = nullptr;