|
@@ -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;
|