- 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
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");
@ -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<const Geometry*>& geos = model.GetGeometry();
@ -538,7 +542,7 @@ private:
const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*>(geo);
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) );
}
else {
@ -557,7 +561,7 @@ private:
// ------------------------------------------------------------------------------------------------
// 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;
@ -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<unsigned int>& mindices = mesh.GetMaterialIndices();
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) {
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);
@ -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();
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<unsigned int>(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<unsigned int>* 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<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>& 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();
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<unsigned int>(out_indices.size());
aiVertexWeight* cursor = bone->mWeights = new aiVertexWeight[out_indices.size()];