Example #1
0
        internal void SetParent(DsBoneData parentBoneData)
        {
            parent = parentBoneData;

            if (parentBoneData != null)
            {
                parentBoneData.exportData.FbxNode.AddChild(exportData.FbxNode);
            }
        }
Example #2
0
        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));
        }
Example #3
0
        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));
        }
Example #4
0
        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);
        }