- fbx: bone bind matrix now includes mesh world transformation.

pull/14/head
Alexander Gessler 2012-07-27 22:36:40 +02:00
parent d5d6df36e3
commit 3899fc5257
1 changed files with 29 additions and 18 deletions

View File

@ -154,7 +154,7 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// collect and assign child nodes // 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<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(id, "Model"); const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(id, "Model");
@ -182,6 +182,8 @@ private:
if(model) { if(model) {
nodes_chain.clear(); nodes_chain.clear();
aiMatrix4x4 new_abs_transform = parent_transform;
// even though there is only a single input node, the design of // even though there is only a single input node, the design of
// assimp (or rather: the complicated transformation chain that // assimp (or rather: the complicated transformation chain that
// is employed by fbx) means that we may need multiple aiNode's // is employed by fbx) means that we may need multiple aiNode's
@ -221,13 +223,15 @@ private:
prenode->mParent = last_parent; prenode->mParent = last_parent;
last_parent = prenode; last_parent = prenode;
new_abs_transform *= prenode->mTransformation;
} }
// attach geometry // attach geometry
ConvertModel(*model, *nodes_chain.back()); ConvertModel(*model, *nodes_chain.back(), new_abs_transform);
// attach sub-nodes // 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.push_back(nodes_chain.front());
nodes_chain.clear(); 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<const Geometry*>& geos = model.GetGeometry(); const std::vector<const Geometry*>& geos = model.GetGeometry();
@ -538,7 +542,7 @@ private:
const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*>(geo); const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*>(geo);
if(mesh) { if(mesh) {
const std::vector<unsigned int>& indices = ConvertMesh(*mesh, model); const std::vector<unsigned int>& indices = ConvertMesh(*mesh, model, node_global_transform);
std::copy(indices.begin(),indices.end(),std::back_inserter(meshes) ); std::copy(indices.begin(),indices.end(),std::back_inserter(meshes) );
} }
else { else {
@ -557,7 +561,7 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh, const Model& model) std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh,const Model& model, const aiMatrix4x4& node_global_transform)
{ {
std::vector<unsigned int> temp; std::vector<unsigned int> temp;
@ -581,13 +585,13 @@ private:
const unsigned int base = mindices[0]; const unsigned int base = mindices[0];
BOOST_FOREACH(unsigned int index, mindices) { BOOST_FOREACH(unsigned int index, mindices) {
if(index != base) { if(index != base) {
return ConvertMeshMultiMaterial(mesh, model); return ConvertMeshMultiMaterial(mesh, model, node_global_transform);
} }
} }
} }
// faster codepath, just copy the data // faster codepath, just copy the data
temp.push_back(ConvertMeshSingleMaterial(mesh, model)); temp.push_back(ConvertMeshSingleMaterial(mesh, model, node_global_transform));
return temp; 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<unsigned int>& mindices = mesh.GetMaterialIndices(); const std::vector<unsigned int>& mindices = mesh.GetMaterialIndices();
aiMesh* const out_mesh = SetupEmptyMesh(mesh,mindices.size() ? mindices[0] : static_cast<unsigned int>(-1)); aiMesh* const out_mesh = SetupEmptyMesh(mesh,mindices.size() ? mindices[0] : static_cast<unsigned int>(-1));
@ -733,7 +737,7 @@ private:
} }
if(doc.Settings().readWeights && mesh.DeformerSkin() != NULL) { 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<unsigned int>(meshes.size() - 1); return static_cast<unsigned int>(meshes.size() - 1);
@ -741,7 +745,7 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<unsigned int> ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model) std::vector<unsigned int> ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model, const aiMatrix4x4& node_global_transform)
{ {
const std::vector<unsigned int>& mindices = mesh.GetMaterialIndices(); const std::vector<unsigned int>& mindices = mesh.GetMaterialIndices();
ai_assert(mindices.size()); ai_assert(mindices.size());
@ -752,7 +756,7 @@ private:
BOOST_FOREACH(unsigned int index, mindices) { BOOST_FOREACH(unsigned int index, mindices) {
if(had.find(index) == had.end()) { 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); 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); aiMesh* const out_mesh = SetupEmptyMesh(mesh, index);
@ -927,7 +931,7 @@ private:
ConvertMaterialForMesh(out_mesh,model,mesh,index); ConvertMaterialForMesh(out_mesh,model,mesh,index);
if(process_weights) { if(process_weights) {
ConvertWeights(out_mesh, model, mesh, index, &reverseMapping); ConvertWeights(out_mesh, model, mesh, node_global_transform, index, &reverseMapping);
} }
return static_cast<unsigned int>(meshes.size() - 1); return static_cast<unsigned int>(meshes.size() - 1);
@ -943,6 +947,7 @@ private:
* - outputVertStartIndices is only used when a material index is specified, it gives for * - outputVertStartIndices is only used when a material index is specified, it gives for
* each output vertex the DOM index it maps to. */ * each output vertex the DOM index it maps to. */
void ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo, void ConvertWeights(aiMesh* out, const Model& model, const MeshGeometry& geo,
const aiMatrix4x4& node_global_transform = aiMatrix4x4(),
unsigned int materialIndex = NO_MATERIAL_SEPARATION, unsigned int materialIndex = NO_MATERIAL_SEPARATION,
std::vector<unsigned int>* outputVertStartIndices = NULL) std::vector<unsigned int>* outputVertStartIndices = NULL)
{ {
@ -1024,7 +1029,8 @@ private:
// 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) { 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<aiBone*>& bones, const Cluster& cl, void ConvertCluster(std::vector<aiBone*>& bones, const Model& model, const Cluster& cl,
std::vector<size_t>& out_indices, std::vector<size_t>& out_indices,
std::vector<size_t>& index_out_indices, std::vector<size_t>& index_out_indices,
std::vector<size_t>& count_out_indices std::vector<size_t>& count_out_indices,
) const aiMatrix4x4& node_global_transform)
{ {
aiBone* const bone = new aiBone(); aiBone* const bone = new aiBone();
bones.push_back(bone); bones.push_back(bone);
bone->mName = FixNodeName(cl.TargetNode()->Name()); bone->mName = FixNodeName(cl.TargetNode()->Name());
bone->mOffsetMatrix = cl.TransformLink(); bone->mOffsetMatrix = cl.TransformLink();
bone->mOffsetMatrix.Inverse(); bone->mOffsetMatrix.Inverse();
bone->mOffsetMatrix = bone->mOffsetMatrix * node_global_transform;
bone->mNumWeights = static_cast<unsigned int>(out_indices.size()); bone->mNumWeights = static_cast<unsigned int>(out_indices.size());
aiVertexWeight* cursor = bone->mWeights = new aiVertexWeight[out_indices.size()]; aiVertexWeight* cursor = bone->mWeights = new aiVertexWeight[out_indices.size()];