// key - control point index public static Dictionary <int, BoneAssignment> GetBoneAssignments(FbxMesh mesh, Skeleton skeleton) { var boneAssignments = new Dictionary <int, BoneAssignment>(); var weightLists = new Dictionary <int, List <(int, double)> >(); int skinCount = mesh.GetDeformerCount(FbxDeformer.EDeformerType.eSkin); if (skinCount == 0) { return(null); } if (1 < skinCount) { FbxImportLog.LogMessage(mesh.GetNode(), "Warning! Multiple skins for the mesh"); //??? Может ли быть в одном Mesh несколько Skins? Скорее всего нет, хоть API позволяет. } FbxSkin pSkin = FbxSkin.Cast(mesh.GetDeformer(0, FbxDeformer.EDeformerType.eSkin)); int clusterCount = pSkin.GetClusterCount(); for (int iCluster = 0; iCluster < clusterCount; iCluster++) { FbxCluster pCluster = pSkin.GetCluster(iCluster); FbxNode pLink = pCluster.GetLink(); if (pLink == null) { continue; } int weightCount = pCluster.GetControlPointIndicesCount(); if (weightCount == 0) { continue; } int boneIndex = skeleton.GetBoneIndexByNode(pLink); var weightIndices = IntArray.frompointer(pCluster.GetControlPointIndices()); var weightValues = DoubleArray.frompointer(pCluster.GetControlPointWeights()); for (int i = 0; i < weightCount; i++) { int vertexIndex = weightIndices.getitem(i); double weight = weightValues.getitem(i); if (!weightLists.TryGetValue(vertexIndex, out var lst)) { lst = new List <(int, double)>(); weightLists[vertexIndex] = lst; } lst.Add((boneIndex, weight)); } } foreach (var pair in weightLists) { boneAssignments[pair.Key] = ConvertBoneWeightListToBoneAssignment(pair.Value); } return(boneAssignments); }
static void ReadMeshElements(MeshData data, ImportOptions importOptions, ref Matrix4 transform) { ReadUvSets(data); //flip with disabled FlipUVs, no flip when enabled if (!importOptions.ImportPostProcessFlags.HasFlag(ImportPostProcessFlags.FlipUVs)) { CalcMiscProcess.FlipUVs(data.Vertices, data.VertexComponents); //ToDo : !!! Доделать FlipUV для Materials - там тоже Flip для Transform текстуры .... tex->UVScaling(); tex->UVTranslation(); } ReadColor(data); TransformVertices(data, transform); int uvSetIndexForNormalsAndTangents = 0; //ToDo : пока 0, может не всегда? if (3 <= data.PolygonSize) { ReadNormals(data, importOptions, uvSetIndexForNormalsAndTangents, data.CalcCache, ref transform); if (importOptions.ImportPostProcessFlags.HasFlag(ImportPostProcessFlags.FixInfacingNormals) && data.NormalsSource != TangentsAndNormalsSource.None) { if (CalcNormalsProcess.FixInfacingNormals(data.Vertices)) { FbxImportLog.LogMessage(data.Node, "Infacing Normals Fixed"); } } ReadTangents(data, importOptions, uvSetIndexForNormalsAndTangents, data.CalcCache, ref transform); } }
//Find the cluster that links to the skeleton bone node public static FbxCluster FindCluster(FbxNode boneNode, FbxSkin[] skins, out FbxSkin skin) { for (int i = 0; i < skins.Length; i++) { skin = skins[i]; int nClusterCount = skin.GetClusterCount(); for (int j = 0; j < nClusterCount; j++) { FbxCluster fbxCluster = skin.GetCluster(j); if (fbxCluster == null) { continue; } if (fbxCluster.GetLinkMode() == FbxCluster.ELinkMode.eAdditive && fbxCluster.GetAssociateModel() != null) { FbxImportLog.LogMessage(boneNode, "Warning! Associated model."); } if (fbxCluster.GetLink()?.GetUniqueID() == boneNode.GetUniqueID()) { return(fbxCluster); } } } skin = null; return(null); }