From 3899fc525713ac3b19e4cf2e2a0486a0bb0f3419 Mon Sep 17 00:00:00 2001 From: Alexander Gessler Date: Fri, 27 Jul 2012 22:36:40 +0200 Subject: [PATCH] - fbx: bone bind matrix now includes mesh world transformation. --- code/FBXConverter.cpp | 47 ++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index f596aad05..0e357bf66 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -154,7 +154,7 @@ private: // ------------------------------------------------------------------------------------------------ // collect and assign child nodes - void ConvertNodes(uint64_t id, aiNode& parent) + void ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4()) { const std::vector& conns = doc.GetConnectionsByDestinationSequenced(id, "Model"); @@ -182,6 +182,8 @@ private: if(model) { nodes_chain.clear(); + aiMatrix4x4 new_abs_transform = parent_transform; + // even though there is only a single input node, the design of // assimp (or rather: the complicated transformation chain that // is employed by fbx) means that we may need multiple aiNode's @@ -221,13 +223,15 @@ private: prenode->mParent = last_parent; last_parent = prenode; + + new_abs_transform *= prenode->mTransformation; } // attach geometry - ConvertModel(*model, *nodes_chain.back()); + ConvertModel(*model, *nodes_chain.back(), new_abs_transform); // attach sub-nodes - ConvertNodes(model->ID(), *nodes_chain.back()); + ConvertNodes(model->ID(), *nodes_chain.back(), new_abs_transform); nodes.push_back(nodes_chain.front()); nodes_chain.clear(); @@ -527,7 +531,7 @@ private: // ------------------------------------------------------------------------------------------------ - void ConvertModel(const Model& model, aiNode& nd) + void ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform) { const std::vector& geos = model.GetGeometry(); @@ -538,7 +542,7 @@ private: const MeshGeometry* const mesh = dynamic_cast(geo); if(mesh) { - const std::vector& indices = ConvertMesh(*mesh, model); + const std::vector& indices = ConvertMesh(*mesh, model, node_global_transform); std::copy(indices.begin(),indices.end(),std::back_inserter(meshes) ); } else { @@ -557,7 +561,7 @@ private: // ------------------------------------------------------------------------------------------------ // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed - std::vector ConvertMesh(const MeshGeometry& mesh, const Model& model) + std::vector ConvertMesh(const MeshGeometry& mesh,const Model& model, const aiMatrix4x4& node_global_transform) { std::vector temp; @@ -581,13 +585,13 @@ private: const unsigned int base = mindices[0]; BOOST_FOREACH(unsigned int index, mindices) { if(index != base) { - return ConvertMeshMultiMaterial(mesh, model); + return ConvertMeshMultiMaterial(mesh, model, node_global_transform); } } } // faster codepath, just copy the data - temp.push_back(ConvertMeshSingleMaterial(mesh, model)); + temp.push_back(ConvertMeshSingleMaterial(mesh, model, node_global_transform)); return temp; } @@ -614,7 +618,7 @@ private: // ------------------------------------------------------------------------------------------------ - unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model) + unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model, const aiMatrix4x4& node_global_transform) { const std::vector& mindices = mesh.GetMaterialIndices(); aiMesh* const out_mesh = SetupEmptyMesh(mesh,mindices.size() ? mindices[0] : static_cast(-1)); @@ -733,7 +737,7 @@ private: } if(doc.Settings().readWeights && mesh.DeformerSkin() != NULL) { - ConvertWeights(out_mesh, model, mesh, NO_MATERIAL_SEPARATION); + ConvertWeights(out_mesh, model, mesh, node_global_transform, NO_MATERIAL_SEPARATION); } return static_cast(meshes.size() - 1); @@ -741,7 +745,7 @@ private: // ------------------------------------------------------------------------------------------------ - std::vector ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model) + std::vector ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, const aiMatrix4x4& node_global_transform) { const std::vector& mindices = mesh.GetMaterialIndices(); ai_assert(mindices.size()); @@ -752,7 +756,7 @@ private: BOOST_FOREACH(unsigned int index, mindices) { if(had.find(index) == had.end()) { - indices.push_back(ConvertMeshMultiMaterial(mesh, model, index)); + indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, node_global_transform)); had.insert(index); } } @@ -762,7 +766,7 @@ private: // ------------------------------------------------------------------------------------------------ - unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, unsigned int index) + unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, unsigned int index, const aiMatrix4x4& node_global_transform) { aiMesh* const out_mesh = SetupEmptyMesh(mesh, index); @@ -927,7 +931,7 @@ private: ConvertMaterialForMesh(out_mesh,model,mesh,index); if(process_weights) { - ConvertWeights(out_mesh, model, mesh, index, &reverseMapping); + ConvertWeights(out_mesh, model, mesh, node_global_transform, index, &reverseMapping); } return static_cast(meshes.size() - 1); @@ -943,6 +947,7 @@ private: * - outputVertStartIndices is only used when a material index is specified, it gives for * each output vertex the DOM index it maps to. */ void ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo, + const aiMatrix4x4& node_global_transform = aiMatrix4x4(), unsigned int materialIndex = NO_MATERIAL_SEPARATION, std::vector* outputVertStartIndices = NULL) { @@ -1024,7 +1029,8 @@ private: // XXX this could be heavily simplified by collecting the bone // data in a single step. if (ok) { - ConvertCluster(bones, *cluster, out_indices, index_out_indices, count_out_indices); + ConvertCluster(bones, model, *cluster, out_indices, index_out_indices, + count_out_indices, node_global_transform); } } } @@ -1044,20 +1050,25 @@ private: } + // ------------------------------------------------------------------------------------------------ - void ConvertCluster(std::vector& bones, const Cluster& cl, + void ConvertCluster(std::vector& bones, const Model& model, const Cluster& cl, std::vector& out_indices, std::vector& index_out_indices, - std::vector& count_out_indices - ) + std::vector& count_out_indices, + const aiMatrix4x4& node_global_transform) { + aiBone* const bone = new aiBone(); bones.push_back(bone); bone->mName = FixNodeName(cl.TargetNode()->Name()); + bone->mOffsetMatrix = cl.TransformLink(); bone->mOffsetMatrix.Inverse(); + bone->mOffsetMatrix = bone->mOffsetMatrix * node_global_transform; + bone->mNumWeights = static_cast(out_indices.size()); aiVertexWeight* cursor = bone->mWeights = new aiVertexWeight[out_indices.size()];