void patchSkins(FbxNode* currentRoot, const std::map<std::string, FbxNode*>& animatedNodes, const std::string& prefix){ auto mesh = currentRoot->GetMesh(); if (mesh){ auto skinCount = mesh->GetDeformerCount(FbxDeformer::EDeformerType::eSkin); for (auto ix = 0; ix < skinCount; ++ix){ auto skin = (FbxSkin*) mesh->GetDeformer(ix, FbxDeformer::EDeformerType::eSkin); if (skin){ std::vector<FbxCluster*> replacements; auto clusterCount = skin->GetClusterCount(); for (auto clusterIx = 0; clusterIx < clusterCount; ++clusterIx){ auto cluster = skin->GetCluster(clusterIx); if (cluster){ auto linkNode = cluster->GetLink(); if (linkNode){ auto candidateName = prefix; candidateName.append(linkNode->GetName()); auto found = animatedNodes.find(candidateName); if (found != animatedNodes.end()){ FbxCluster* newCluster = FbxCluster::Create(currentRoot->GetScene(), ""); newCluster->SetLink(found->second); newCluster->SetLinkMode(cluster->GetLinkMode()); FbxAMatrix mat; newCluster->SetTransformAssociateModelMatrix(cluster->GetTransformAssociateModelMatrix(mat)); newCluster->SetAssociateModel(cluster->GetAssociateModel()); newCluster->SetTransformLinkMatrix(cluster->GetTransformLinkMatrix(mat)); newCluster->SetTransformMatrix(cluster->GetTransformMatrix(mat)); newCluster->SetTransformParentMatrix(cluster->GetTransformParentMatrix(mat)); auto indicesAndWeightsCount = cluster->GetControlPointIndicesCount(); for (auto ix = 0; ix < indicesAndWeightsCount; ++ix){ newCluster->AddControlPointIndex(cluster->GetControlPointIndices()[ix], cluster->GetControlPointWeights()[ix]); } replacements.push_back(newCluster); } } } } if (replacements.size() == clusterCount){ while (skin->GetClusterCount()>0){ auto oldCluster = skin->GetCluster(skin->GetClusterCount() - 1); skin->RemoveCluster(oldCluster); oldCluster->Destroy(); } for (auto c : replacements){ skin->AddCluster(c); } } else{ for (auto c : replacements){ c->Destroy(); } } } } } for (auto ix = 0; ix < currentRoot->GetChildCount(); ++ix){ patchSkins(currentRoot->GetChild(ix), animatedNodes, prefix); } }
void FBXConverter::LoadSkin(FbxMesh* fbxMesh, std::vector<BoneConnector>& bcs, std::vector<Vertex>& vs) { vs.resize(fbxMesh->GetControlPointsCount()); auto skinCount = fbxMesh->GetDeformerCount(FbxDeformer::eSkin); for (auto skinInd = 0; skinInd < skinCount; skinInd++) { auto skin = (FbxSkin*)fbxMesh->GetDeformer(skinInd, FbxDeformer::eSkin); auto clusterCount = skin->GetClusterCount(); for (auto clusterInd = 0; clusterInd < clusterCount; clusterInd++) { auto cluster = skin->GetCluster(clusterInd); if (cluster->GetLink() == nullptr) continue; // ボーン取得 auto name = cluster->GetLink()->GetName(); FbxAMatrix m1, m2; cluster->GetTransformMatrix(m1); cluster->GetTransformLinkMatrix(m2); int32_t id = bcs.size(); BoneConnector connector; connector.Name = name; auto m2_inv = m2.Inverse(); auto m = m2_inv * m1; connector.OffsetMatrix = m; bcs.push_back(connector); auto indexCount = cluster->GetControlPointIndicesCount(); auto vindices = cluster->GetControlPointIndices(); auto vweights = cluster->GetControlPointWeights(); for (auto ind = 0; ind < indexCount; ind++) { Weight data; data.Index = id; data.Value = (float)vweights[ind]; vs[vindices[ind]].Weights.push_back(data); } } } // Calculate weight for (auto& v : vs) { if (v.Weights.size() == 0) { Weight w; w.Index = -1; w.Value = 1.0; v.Weights.push_back(w); v.Weights.push_back(Weight()); v.Weights.push_back(Weight()); v.Weights.push_back(Weight()); } else { v.Weights.push_back(Weight()); v.Weights.push_back(Weight()); v.Weights.push_back(Weight()); std::sort(v.Weights.begin(), v.Weights.end(), Weight()); float fSum = 0.0f; for (auto ind = 0; ind < 4; ind++) { fSum += v.Weights[ind].Value; } v.Weights[0].Value += 1.0f - fSum; v.Weights.resize(4); } } }