internal void SetParent(DsBoneData parentBoneData) { parent = parentBoneData; if (parentBoneData != null) { parentBoneData.exportData.FbxNode.AddChild(exportData.FbxNode); } }
private static Matrix4x4 CalculateGlobalTransform(DsBoneData boneData, FLVER2 flver, HKX.HKASkeleton hkaSkeleton) { if (boneData.exportData.SoulsData.HkxBoneIndex >= 0) { System.Diagnostics.Debug.Assert(hkaSkeleton != null); System.Console.WriteLine("Using HKA transform"); return(CalculateGlobalTransformHka(boneData.exportData.SoulsData.HkxBoneIndex, hkaSkeleton)); } if (flver != null) { System.Console.WriteLine("Using FLVER transform"); return(CalculateGlobalTransformFlver(boneData.flverBone, flver)); } throw new System.ArgumentException("Can't calculate transform " + nameof(boneData)); }
public DsSkeleton ParseSkeleton() { List <DsBoneData> boneDatas = bones.Select( bone => { FLVER.Bone flverBone = Flver.Bones.Single(flverBone => flverBone.Name == bone.Name); return(new DsBoneData(bone, flverBone, Scene)); } ).ToList(); //exportData.FbxNode.LclTranslation.Set(flverBone.Translation.ToFbxDouble3()); //exportData.FbxNode.LclRotation.Set(flverBone.Rotation.ToFbxDouble3()); //exportData.FbxNode.LclScaling.Set(flverBone.Scale.ToFbxDouble3()); for (int boneIndex = 0; boneIndex < bones.Count; ++boneIndex) { DsBoneData boneData = boneDatas[boneIndex]; DsBoneData parentBoneData = boneDatas.Find(parentBoneData => parentBoneData.exportData.SoulsData.Name == boneData.exportData.SoulsData.ParentName); boneData.SetParent(parentBoneData); } Func <DsBoneData, Matrix4x4> calculateTransform = (boneData) => { Matrix4x4 rawGlobalTransform = CalculateGlobalTransform(boneData, Flver, hkaSkeleton); var preFixupMatrix = Matrix4x4.CreateRotationZ((float)(-Math.PI / 2)); // Matrix4x4.CreateScale(new Vector3(1, 1, 1)); // * Matrix4x4.CreateRotationX((float)(-Math.PI)) * Matrix4x4.CreateRotationY((float)(-Math.PI / 2)) * Matrix4x4.CreateRotationZ((float)(Math.PI / 2)); var postFixupMatrix = Matrix4x4.CreateScale(1, 1, 1); // Matrix4x4.CreateRotationZ((float)(Math.PI / 2)); // Matrix4x4.CreateScale(new Vector3(1, 1, 1));// * Matrix4x4.CreateRotationX((float)(-Math.PI / 2)) * Matrix4x4.CreateRotationZ((float)(Math.PI / 2)); if (boneData.parent == null) { Matrix4x4 preFixupParent = Matrix4x4.Identity; Matrix4x4 postFixupParent = Matrix4x4.Identity; // * Matrix4x4.CreateRotationX((float)(-Math.PI / 2)) * Matrix4x4.CreateRotationZ((float)(Math.PI / 2)); ; //* Matrix4x4.CreateScale(1,1,-1); preFixupMatrix *= preFixupParent; postFixupMatrix *= postFixupParent; } else { } //var t = rawGlobalTransform.Translation; //t.Z = -t.Z; //rawGlobalTransform.Translation = t; var fixedTransform = preFixupMatrix * rawGlobalTransform * postFixupMatrix; var btr = new NewBlendableTransform(fixedTransform); btr.Translation.Z = -btr.Translation.Z; btr.Rotation.X = -btr.Rotation.X; btr.Rotation.Y = -btr.Rotation.Y; return(btr.GetMatrix()); }; //Func<DsBoneData, Matrix4x4> calculateParentTransform = (boneData) => //{ // Matrix4x4 rawGlobalTransform = CalculateGlobalTransform(boneData, Flver, hkaSkeleton); // var preFixupMatrix = Matrix4x4.CreateScale(new Vector3(1, 1, 1)); // * Matrix4x4.CreateRotationX((float)(-Math.PI)) * Matrix4x4.CreateRotationY((float)(-Math.PI / 2)) * Matrix4x4.CreateRotationZ((float)(Math.PI / 2)); // var postFixupMatrix = Matrix4x4.CreateScale(new Vector3(1, 1, 1)); // * Matrix4x4.CreateRotationX((float)(-Math.PI / 2)) * Matrix4x4.CreateRotationZ((float)(Math.PI / 2)); // if (boneData.parent == null) // { // postFixupMatrix *= Matrix4x4.CreateRotationX((float)(-Math.PI / 2)) * Matrix4x4.CreateRotationZ((float)(Math.PI / 2)); // } // else // { // //postFixupMatrix *= Matrix4x4.CreateScale(1, 1, -1); // } // return preFixupMatrix * rawGlobalTransform * postFixupMatrix; //}; foreach (var boneData in boneDatas) { var globalTransform = calculateTransform(boneData); if (boneData.parent != null) { var globalParentTransform = calculateTransform(boneData.parent); Matrix4x4 invertedGlobalParentTransform; if (Matrix4x4.Invert(globalParentTransform, out invertedGlobalParentTransform)) { globalTransform *= invertedGlobalParentTransform; } else { throw new Exception(); } } else { } Vector3 scale; Quaternion rotation; Vector3 translation; if (Matrix4x4.Decompose(globalTransform, out scale, out rotation, out translation)) { boneData.exportData.FbxNode.LclTranslation.Set(translation.ToFbxDouble3()); Vector3 euler = rotation.QuaternionToEuler(); boneData.exportData.FbxNode.LclRotation.Set(euler.ToFbxDouble3()); boneData.exportData.FbxNode.LclScaling.Set(scale.ToFbxDouble3()); } else { throw new Exception(); } } //FbxSkeleton skeletonRoot = FbxSkeleton.Create(Scene, "ActualRoot"); //FbxNode skeletonRootNode = skeletonRoot.CreateNode(); foreach (var root in boneDatas.Where(bone => bone.parent == null)) { Scene.GetRootNode().AddChild(root.exportData.FbxNode); } return(new DsSkeleton(null, boneDatas)); }
protected override FbxSkin GenerateFbx() { MeshExportData meshData = Souls.meshData.SoulsData; ICollection <BoneIndexToWeightPair> rawBoneDeformerData = new List <BoneIndexToWeightPair>(); for (int vertexIndex = 0; vertexIndex < meshData.mesh.Vertices.Count; ++vertexIndex) { FLVER.Vertex vertex = meshData.mesh.Vertices[vertexIndex]; const int maxVertexDeformations = 4; for (int vertexDeformationIndex = 0; vertexDeformationIndex < maxVertexDeformations; ++vertexDeformationIndex) { BoneIndexToWeightPair weightData = new BoneIndexToWeightPair() { flverBoneIndex = vertex.BoneIndices[vertexDeformationIndex], boneWeight = vertex.BoneWeights[vertexDeformationIndex], vertexIndex = vertexIndex }; if (weightData.flverBoneIndex > 0 && weightData.boneWeight > 0) { rawBoneDeformerData.Add(weightData); } } } foreach (var ddd in rawBoneDeformerData.GroupBy(boneDeformerData => boneDeformerData.vertexIndex).Select(boneDeformedGroup => (vertexIndex: boneDeformedGroup.Key, affectingBonesCount: boneDeformedGroup.Count())).Where((ddd) => ddd.affectingBonesCount > 4)) { System.Console.WriteLine($"Vertex {ddd.vertexIndex} : {ddd.affectingBonesCount}"); } foreach (var ddd in rawBoneDeformerData.GroupBy(boneDeformedData => boneDeformedData.flverBoneIndex).Select(boneDeformerGroup => (boneIndex: boneDeformerGroup.Key, affectingVerticesCount: boneDeformerGroup.Count(), uniqueAffectingVerticesCount: boneDeformerGroup.Select(boneDeformerData => boneDeformerData.vertexIndex).Distinct().Count()))) { if (ddd.affectingVerticesCount != ddd.uniqueAffectingVerticesCount) { System.Console.WriteLine($"Bone {ddd.boneIndex} : vertices {ddd.affectingVerticesCount} : unique {ddd.uniqueAffectingVerticesCount}"); } } FbxSkin skin = FbxSkin.Create(Owner, meshData.meshRoot.Name + "_Skin"); System.Console.WriteLine($"Generating {meshData.meshRoot.Name}"); foreach (var deformerData in rawBoneDeformerData.ToLookup(boneDeformerData => boneDeformerData.flverBoneIndex)) { FLVER2 flver = Souls.flver; FLVER.Bone flverBone = flver.Bones[deformerData.Key]; DsBoneData boneData = Souls.skeleton.boneDatas.Single(boneData => boneData.flverBone == flverBone); //System.Console.WriteLine($"Exporting {deformerData.Key} : {flverBone.Name} with {deformerData.Count(weight=>weight.boneWeight > 0)} vertices"); FbxCluster boneCluster = FbxCluster.Create(skin, meshData.meshRoot.Name + "_" + boneData.exportData.SoulsData.Name + "_Cluster"); boneCluster.SetLink(boneData.exportData.FbxNode); boneCluster.SetLinkMode(FbxCluster.ELinkMode.eTotalOne); boneCluster.SetControlPointIWCount(deformerData.Count()); boneCluster.SetTransformMatrix(Souls.meshData.FbxNode.EvaluateGlobalTransform()); boneCluster.SetTransformLinkMatrix(boneData.exportData.FbxNode.EvaluateGlobalTransform()); foreach (BoneIndexToWeightPair boneWeightPair in deformerData) { boneCluster.AddControlPointIndex(boneWeightPair.vertexIndex, boneWeightPair.boneWeight); //Console.WriteLine("Bone {0} has vertex {1} with weight {2}", flverBone.Name, boneWeightPair.vertexIndex, boneWeightPair.boneWeight); } skin.AddCluster(boneCluster); } //foreach (var dd in rawBoneDeformerData.GroupBy(biwp => biwp.vertexIndex).Where(group => group.Count() > 2)) //{ //System.Console.WriteLine($"Vertex {dd.Key} : {dd.Count()}"); //} //var set = new HashSet<int>(); //for (int vertexIndex = 0; vertexIndex < meshData.mesh.Vertices.Count; ++vertexIndex) //{ // if (!rawBoneDeformerData.Any(x=>x.vertexIndex == vertexIndex)) // { // set.Add(vertexIndex); // } //} //System.Console.WriteLine($"Total {set.Count} unweighted nodes"); return(skin); }