Matrix GetParentBoneMatrix(FLVER2 f, FLVER.Bone bone)
        {
            FLVER.Bone parent = bone;

            var boneParentMatrix = Matrix.Identity;

            do
            {
                boneParentMatrix *= Matrix.CreateScale(parent.Scale.X, parent.Scale.Y, parent.Scale.Z);
                boneParentMatrix *= Matrix.CreateRotationX(parent.Rotation.X);
                boneParentMatrix *= Matrix.CreateRotationZ(parent.Rotation.Z);
                boneParentMatrix *= Matrix.CreateRotationY(parent.Rotation.Y);

                //boneParentMatrix *= Matrix.CreateRotationY(parent.EulerRadian.Y);
                //boneParentMatrix *= Matrix.CreateRotationZ(parent.EulerRadian.Z);
                //boneParentMatrix *= Matrix.CreateRotationX(parent.EulerRadian.X);
                boneParentMatrix *= Matrix.CreateTranslation(parent.Translation.X, parent.Translation.Y, parent.Translation.Z);
                //boneParentMatrix *= Matrix.CreateScale(parent.Scale);

                if (parent.ParentIndex >= 0)
                {
                    parent = f.Bones[parent.ParentIndex];
                }
                else
                {
                    parent = null;
                }
            }while (parent != null);

            return(boneParentMatrix);
        }
예제 #2
0
 public static NMatrix GetNMatrix(this FLVER.Bone b)
 {
     return(NMatrix.CreateScale(b.Scale) *
            NMatrix.CreateRotationX(b.Rotation.X) *
            NMatrix.CreateRotationZ(b.Rotation.Z) *
            NMatrix.CreateRotationY(b.Rotation.Y) *
            NMatrix.CreateTranslation(b.Translation));
 }
예제 #3
0
        public DsBone(FLVER.Bone flverBone, FLVER2 flver)
        {
            HkxBoneIndex = -1;

            Name = flverBone.Name;

            ParentName = flverBone.ParentIndex > 0 ? flver.Bones[flverBone.ParentIndex].Name : null;
        }
예제 #4
0
 public static FLVER.Bone GetParent(this FLVER.Bone b, List <FLVER.Bone> bones)
 {
     if (b.ParentIndex >= 0 && b.ParentIndex < bones.Count)
     {
         return(bones[b.ParentIndex]);
     }
     else
     {
         return(null);
     }
 }
예제 #5
0
        public DsBoneData(DsBone bone, FLVER.Bone flverBone, FbxScene scene)
        {
            FbxSkeleton fbxBone = FbxSkeleton.Create(scene, bone.Name + "Bone");

            fbxBone.SetSkeletonType(flverBone.ChildIndex >= 0 ? FbxSkeleton.EType.eLimbNode : FbxSkeleton.EType.eEffector);

            fbxBone.Size.Set(flverBone.Translation.Length());

            exportData = fbxBone.CreateExportDataWithScene(bone, scene);

            this.flverBone = flverBone;
        }
예제 #6
0
        public static NMatrix GetAbsoluteNMatrix(this FLVER.Bone b, List <FLVER.Bone> bones)
        {
            NMatrix result     = NMatrix.Identity;
            var     parentBone = b;

            while (parentBone != null)
            {
                var m = parentBone.GetNMatrix();
                result    *= m;
                parentBone = parentBone.GetParent(bones);
            }
            return(result);
        }
            public FlverBoneInfo(FLVER.Bone bone, List <FLVER.Bone> boneList)
            {
                Matrix GetBoneMatrix(SoulsFormats.FLVER.Bone b)
                {
                    SoulsFormats.FLVER.Bone parentBone = b;

                    var result = Matrix.Identity;

                    do
                    {
                        result *= Matrix.CreateScale(parentBone.Scale.X, parentBone.Scale.Y, parentBone.Scale.Z);
                        result *= Matrix.CreateRotationX(parentBone.Rotation.X);
                        result *= Matrix.CreateRotationZ(parentBone.Rotation.Z);
                        result *= Matrix.CreateRotationY(parentBone.Rotation.Y);
                        result *= Matrix.CreateTranslation(parentBone.Translation.X, parentBone.Translation.Y, parentBone.Translation.Z);

                        if (parentBone.ParentIndex >= 0)
                        {
                            parentBone = boneList[parentBone.ParentIndex];
                        }
                        else
                        {
                            parentBone = null;
                        }
                    }while (parentBone != null);

                    return(result);
                }

                ReferenceMatrix = GetBoneMatrix(bone);
                Name            = bone.Name;

                if (bone.Unk3C == 0)
                {
                    BonePrim = new DbgPrimWireBone(bone.Name, new Transform(ReferenceMatrix), DBG.COLOR_FLVER_BONE)
                    {
                        Category = DbgPrimCategory.FlverBone,
                    };

                    BoundingBoxPrim = new DbgPrimWireBox(Transform.Default,
                                                         new Vector3(bone.BoundingBoxMin.X, bone.BoundingBoxMin.Y, bone.BoundingBoxMin.Z),
                                                         new Vector3(bone.BoundingBoxMax.X, bone.BoundingBoxMax.Y, bone.BoundingBoxMax.Z),
                                                         DBG.COLOR_FLVER_BONE_BBOX)
                    {
                        Category = DbgPrimCategory.FlverBoneBoundingBox,
                    };
                }
            }
        private void SetBoneBoundingBox(FLVER2 f, FLVER.Bone b)
        {
            var bb = GetBoundingBox(GetVerticesParentedToBone(f, b).Select(v => new Vector3(v.Position.X, v.Position.Y, v.Position.Z)).ToList());

            if (bb.Max.LengthSquared() != 0 || bb.Min.LengthSquared() != 0)
            {
                var matrix = GetParentBoneMatrix(f, b);
                b.BoundingBoxMin = Vector3.Transform(bb.Min, Matrix.Invert(matrix)).ToNumerics();
                b.BoundingBoxMax = Vector3.Transform(bb.Max, Matrix.Invert(matrix)).ToNumerics();
            }
            else
            {
                b.BoundingBoxMin = new System.Numerics.Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
                b.BoundingBoxMax = new System.Numerics.Vector3(float.MinValue, float.MinValue, float.MinValue);
            }
        }
        private List <FLVER.Vertex> GetVerticesParentedToBone(FLVER2 f, FLVER.Bone b)
        {
            var result = new List <FLVER.Vertex>();

            foreach (var sm in f.Meshes)
            {
                foreach (var v in sm.Vertices)
                {
                    var bonesReferencedByThisShit = GetAllBonesReferencedByVertex(f, sm, v);
                    if (bonesReferencedByThisShit.Contains(b))
                    {
                        result.Add(v);
                    }
                }
            }
            return(result);
        }
예제 #10
0
        public static void UpdateBoundingBox(this FLVER.Bone b, List <FLVER.Bone> bones, NVector3 vertexPos)
        {
            var boneAbsoluteMatrix = b.GetAbsoluteNMatrix(bones);

            if (NMatrix.Invert(boneAbsoluteMatrix, out NMatrix invertexBoneMat))
            {
                var posForBBox = NVector3.Transform(vertexPos, invertexBoneMat);

                var minX = Math.Min(b.BoundingBoxMin.X, posForBBox.X);
                var minY = Math.Min(b.BoundingBoxMin.Y, posForBBox.Y);
                var minZ = Math.Min(b.BoundingBoxMin.Z, posForBBox.Z);
                var maxX = Math.Max(b.BoundingBoxMax.X, posForBBox.X);
                var maxY = Math.Max(b.BoundingBoxMax.Y, posForBBox.Y);
                var maxZ = Math.Max(b.BoundingBoxMax.Z, posForBBox.Z);

                b.BoundingBoxMin = new NVector3(minX, minY, minZ);
                b.BoundingBoxMax = new NVector3(maxX, maxY, maxZ);
            }
            //ErrorTODO: when this fails, else {}
        }
예제 #11
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));
        }
예제 #12
0
        public DsBone(FLVER.Bone flverBone, FLVER2 flver, HKX.Bone hkxBone, HKX.HKASkeleton hkaSkeleton) : this(flverBone, flver)
        {
            HkxBoneIndex = hkaSkeleton.Bones.GetArrayData().Elements.IndexOf(hkxBone);

            ParentName = InitializeHkxParentName(hkxBone, hkaSkeleton);
        }
예제 #13
0
        public static FLVERMetaskeleton GenerateFlverMetaskeletonFromRootNode(
            Node rootNode, Matrix4x4 rootNodeAbsoluteMatrix, float importScale)
        {
            var bonesAssimp          = new List <Node>();
            var skel                 = new FLVERMetaskeleton();
            var dummyAttachBoneNames = new List <string>();

            NMatrix matrixScale = NMatrix.CreateScale(importScale, importScale, importScale);

            // Returns index of bone in master bone list if boneNode is a bone.
            // Returns -1 if boneNode is a DummyPoly (denoted with a node name starting with "DUMMY_POLY").
            int AddBone(Node boneNode, Node parentBoneNode, Matrix4x4 parentAbsoluteMatrix)
            {
                short parentBoneIndex = (short)(bonesAssimp.IndexOf(parentBoneNode));

                var thisBoneMatrix         = boneNode.Transform;
                var thisNodeAbsoluteMatrix = thisBoneMatrix * parentAbsoluteMatrix;


                var boneTrans = FLVERBoneTransform.FromMatrix4x4(
                    (parentBoneIndex == -1 ? thisNodeAbsoluteMatrix : thisBoneMatrix), true);

                if (boneNode.Name.StartsWith("DUMMY_POLY"))
                {
                    // TODO

                    thisNodeAbsoluteMatrix.Decompose(out Vector3D dummyScale, out Quaternion dummyQuat, out Vector3D dummyTranslation);
                    var dmy = new FLVER.Dummy();
                    dmy.ParentBoneIndex = parentBoneIndex;
                    dmy.Position        = dummyTranslation.ToNumerics();

                    // Format: "DUMMY_POLY|<RefID>|<AttachBoneName>"
                    // Example: "DUMMY_POLY|220|Spine1"
                    string[] dummyNameParts = boneNode.Name.Split('|');

                    //ErrorTODO: TryParse
                    dmy.ReferenceID = short.Parse(dummyNameParts[1].Trim());

                    if (dummyNameParts.Length == 3)
                    {
                        dummyAttachBoneNames.Add(dummyNameParts[2]);
                    }
                    else
                    {
                        dummyAttachBoneNames.Add(null);
                    }

                    //NOTE: Maybe this should be specifiable? I forget what the point of false is here.
                    dmy.UseUpwardVector = true;

                    var sceneRotation = NMatrix.CreateRotationX(boneTrans.Rotation.X) *
                                        NMatrix.CreateRotationZ(boneTrans.Rotation.Z) *
                                        NMatrix.CreateRotationY(boneTrans.Rotation.Y);

                    dmy.Upward = NVector3.Transform(new NVector3(0, 1, 0), sceneRotation);
                    //TODO: Check if forward vector3 should be 1 or -1;
                    dmy.Forward = NVector3.Transform(new NVector3(0, 0, 1), sceneRotation);

                    skel.DummyPoly.Add(dmy);

                    return(-1);
                }
                else
                {
                    bonesAssimp.Add(boneNode);

                    int thisBoneIndex = bonesAssimp.Count - 1;

                    var flverBone = new FLVER.Bone();

                    if (parentBoneNode != null)
                    {
                        flverBone.ParentIndex = parentBoneIndex;
                    }

                    flverBone.Name           = boneNode.Name;
                    flverBone.BoundingBoxMin = new NVector3(float.MaxValue, float.MaxValue, float.MaxValue);
                    flverBone.BoundingBoxMax = new NVector3(float.MinValue, float.MinValue, float.MinValue);
                    flverBone.Translation    = boneTrans.Translation * importScale;
                    flverBone.Rotation       = boneTrans.Rotation;
                    flverBone.Scale          = boneTrans.Scale;

                    skel.Bones.Add(flverBone);

                    List <int> childBoneIndices = new List <int>();

                    foreach (var c in boneNode.Children)
                    {
                        int cIndex = AddBone(c, boneNode, thisNodeAbsoluteMatrix);

                        //cIndex will be -1 if the child node was a DummyPoly instead of a bone.
                        if (cIndex >= 0)
                        {
                            childBoneIndices.Add(cIndex);
                        }
                    }

                    if (childBoneIndices.Count > 0)
                    {
                        flverBone.ChildIndex = (short)childBoneIndices[0];

                        for (int i = 0; i < childBoneIndices.Count; i++)
                        {
                            var thisChildBone = skel.Bones[childBoneIndices[i]];
                            if (i == 0)
                            {
                                thisChildBone.PreviousSiblingIndex = -1;
                            }
                            else
                            {
                                thisChildBone.PreviousSiblingIndex = (short)(childBoneIndices[i - 1]);
                            }

                            if (i == childBoneIndices.Count - 1)
                            {
                                thisChildBone.NextSiblingIndex = -1;
                            }
                            else
                            {
                                thisChildBone.NextSiblingIndex = (short)(childBoneIndices[i + 1]);
                            }
                        }
                    }

                    return(thisBoneIndex);
                }
            }

            //if (rootNode.Children == null)
            //    throw new InvalidDataException("Assimp scene has no heirarchy.");

            var root = rootNode;

            //var master = root.Children[0];
            //foreach (var c in root.Children)
            //{
            //    AddBone(c, null, root.Transform * rootNodeAbsoluteMatrix);
            //}
            AddBone(root, null, rootNodeAbsoluteMatrix);
            // Apply parent bone transforms to DummyPoly
            foreach (var d in skel.DummyPoly)
            {
                if (d.ParentBoneIndex >= 0)
                {
                    var parentMat = skel.Bones[d.ParentBoneIndex].GetAbsoluteNMatrix(skel.Bones);
                    d.Position = NVector3.Transform(d.Position, parentMat);
                    d.Upward   = NVector3.TransformNormal(d.Upward, parentMat);
                    d.Forward  = NVector3.TransformNormal(d.Forward, parentMat);
                }
            }

            return(skel);
        }
예제 #14
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);
        }