Merge pull request #2585 from RevoluPowered/feature/fix-armature-and-root-node

FBX importer armature fixes and root bone fixes - animations should now work for more models.
pull/2574/head^2
Kim Kulling 2019-08-08 21:56:08 +02:00 committed by GitHub
commit 1097f47ff5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 5 additions and 65 deletions

View File

@ -90,7 +90,6 @@ namespace Assimp {
, anim_fps() , anim_fps()
, out(out) , out(out)
, doc(doc) , doc(doc)
, mRemoveEmptyBones( removeEmptyBones )
, mCurrentUnit(FbxUnit::cm) { , mCurrentUnit(FbxUnit::cm) {
// animations need to be converted first since this will // animations need to be converted first since this will
// populate the node_anim_chain_bits map, which is needed // populate the node_anim_chain_bits map, which is needed
@ -1462,14 +1461,8 @@ namespace Assimp {
const WeightIndexArray& indices = cluster->GetIndices(); const WeightIndexArray& indices = cluster->GetIndices();
if (indices.empty() && mRemoveEmptyBones ) {
continue;
}
const MatIndexArray& mats = geo.GetMaterialIndices(); const MatIndexArray& mats = geo.GetMaterialIndices();
bool ok = false;
const size_t no_index_sentinel = std::numeric_limits<size_t>::max(); const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
count_out_indices.clear(); count_out_indices.clear();
@ -1509,8 +1502,7 @@ namespace Assimp {
out_indices.push_back(std::distance(outputVertStartIndices->begin(), it)); out_indices.push_back(std::distance(outputVertStartIndices->begin(), it));
} }
++count_out_indices.back(); ++count_out_indices.back();
ok = true;
} }
} }
} }
@ -1518,10 +1510,8 @@ namespace Assimp {
// if we found at least one, generate the output bones // if we found at least one, generate the output bones
// XXX this could be heavily simplified by collecting the bone // XXX this could be heavily simplified by collecting the bone
// data in a single step. // data in a single step.
if (ok && mRemoveEmptyBones) { ConvertCluster(bones, model, *cluster, out_indices, index_out_indices,
ConvertCluster(bones, model, *cluster, out_indices, index_out_indices,
count_out_indices, node_global_transform); count_out_indices, node_global_transform);
}
} }
} }
catch (std::exception&) { catch (std::exception&) {

View File

@ -470,9 +470,6 @@ private:
aiScene* const out; aiScene* const out;
const FBX::Document& doc; const FBX::Document& doc;
bool mRemoveEmptyBones;
FbxUnit mCurrentUnit; FbxUnit mCurrentUnit;
}; };

View File

@ -90,14 +90,6 @@ const Object* LazyObject::Get(bool dieOnError)
return object.get(); return object.get();
} }
// if this is the root object, we return a dummy since there
// is no root object int he fbx file - it is just referenced
// with id 0.
if(id == 0L) {
object.reset(new Object(id, element, "Model::RootNode"));
return object.get();
}
const Token& key = element.KeyToken(); const Token& key = element.KeyToken();
const TokenList& tokens = element.Tokens(); const TokenList& tokens = element.Tokens();

View File

@ -1706,8 +1706,7 @@ void FBXExporter::WriteObjects ()
} }
if (end) { break; } if (end) { break; }
} }
limbnodes.insert(parent);
skeleton.insert(parent);
// if it was the skeleton root we can finish here // if it was the skeleton root we can finish here
if (end) { break; } if (end) { break; }
} }
@ -1848,46 +1847,10 @@ void FBXExporter::WriteObjects ()
inverse_bone_xform.Inverse(); inverse_bone_xform.Inverse();
aiMatrix4x4 tr = inverse_bone_xform * mesh_xform; aiMatrix4x4 tr = inverse_bone_xform * mesh_xform;
// this should be the same as the bone's mOffsetMatrix. sdnode.AddChild("Transform", tr);
// if it's not the same, the skeleton isn't in the bind pose.
float epsilon = 1e-4f; // some error is to be expected
float epsilon_custom = mProperties->GetPropertyFloat("BINDPOSE_EPSILON", -1);
if(epsilon_custom > 0) {
epsilon = epsilon_custom;
}
bool bone_xform_okay = true;
if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) {
not_in_bind_pose.insert(b);
bone_xform_okay = false;
}
// if we have a bone we should use the mOffsetMatrix,
// otherwise try to just use the calculated transform.
if (b) {
sdnode.AddChild("Transform", b->mOffsetMatrix);
} else {
sdnode.AddChild("Transform", tr);
}
// note: it doesn't matter if we mix these,
// because if they disagree we'll throw an exception later.
// it could be that the skeleton is not in the bone pose
// but all bones are still defined,
// in which case this would use the mOffsetMatrix for everything
// and a correct skeleton would still be output.
// transformlink should be the position of the bone in world space. sdnode.AddChild("TransformLink", bone_xform);
// if the bone is in the bind pose (or nonexistent),
// we can just use the matrix we already calculated
if (bone_xform_okay) {
sdnode.AddChild("TransformLink", bone_xform);
// otherwise we can only work it out using the mesh position.
} else {
aiMatrix4x4 trl = b->mOffsetMatrix;
trl.Inverse();
trl *= mesh_xform;
sdnode.AddChild("TransformLink", trl);
}
// note: this means we ALWAYS rely on the mesh node transform // note: this means we ALWAYS rely on the mesh node transform
// being unchanged from the time the skeleton was bound. // being unchanged from the time the skeleton was bound.
// there's not really any way around this at the moment. // there's not really any way around this at the moment.

View File

@ -115,7 +115,6 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
if(tempVerts.empty()) { if(tempVerts.empty()) {
FBXImporter::LogWarn("encountered mesh with no vertices"); FBXImporter::LogWarn("encountered mesh with no vertices");
return;
} }
std::vector<int> tempFaces; std::vector<int> tempFaces;
@ -123,7 +122,6 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
if(tempFaces.empty()) { if(tempFaces.empty()) {
FBXImporter::LogWarn("encountered mesh with no faces"); FBXImporter::LogWarn("encountered mesh with no faces");
return;
} }
m_vertices.reserve(tempFaces.size()); m_vertices.reserve(tempFaces.size());