Beispiel #1
0
        private unsafe void FillUVFloat(ref Vector2 dest, ref FLVER.Vertex v, byte index)
        {
            var uv = v.GetUV(index);

            dest.X = uv.X;
            dest.Y = uv.Y;
        }
Beispiel #2
0
 public static void EnsureLayoutMembers(this FLVER.Vertex v, Dictionary <FLVER.LayoutSemantic, int> members)
 {
     foreach (var m in members)
     {
         if (m.Key == FLVER.LayoutSemantic.Tangent)
         {
             while (v.Tangents.Count < m.Value)
             {
                 v.Tangents.Add(v.Tangents.Count > 0 ? v.Tangents[0] : System.Numerics.Vector4.Zero);
             }
         }
         else if (m.Key == FLVER.LayoutSemantic.VertexColor)
         {
             while (v.Colors.Count < m.Value)
             {
                 v.Colors.Add(v.Colors.Count > 0 ? v.Colors[0] : new FLVER.VertexColor(0, 0, 0, 0));
             }
         }
         else if (m.Key == FLVER.LayoutSemantic.UV)
         {
             while (v.UVs.Count <= m.Value)
             {
                 v.UVs.Add(v.UVs.Count > 0 ? v.UVs[0] : NVector3.Zero);
             }
         }
     }
 }
Beispiel #3
0
        private unsafe void FillUVShort(short *dest, ref FLVER.Vertex v, byte index)
        {
            var uv = v.GetUV(index);

            dest[0] = (short)(uv.X * 2048.0f);
            dest[1] = (short)(uv.Y * 2048.0f);
        }
Beispiel #4
0
        private unsafe void FillNormalSNorm8(sbyte *dest, ref FLVER.Vertex v)
        {
            var n = Vector3.Normalize(new Vector3(v.Normal.X, v.Normal.Y, v.Normal.Z));

            dest[0] = (sbyte)(n.X * 127.0f);
            dest[1] = (sbyte)(n.Y * 127.0f);
            dest[2] = (sbyte)(n.Z * 127.0f);
        }
Beispiel #5
0
        static FLVER.Vertex generateVertex2tan(Vector3 pos, Vector3 uv1, Vector3 uv2, Vector3 normal, Vector3 tangets, Vector3 tangets2, int tangentW = -1)
        {
            FLVER.Vertex ans = new FLVER.Vertex();
            ans.Positions = new List <Vector3>();
            ans.Positions.Add(pos);
            ans.BoneIndices = new int[4] {
                0, 0, 0, 0
            };
            ans.BoneWeights = new float[4] {
                1, 0, 0, 0
            };
            ans.UVs = new List <Vector3>();
            ans.UVs.Add(uv1);
            ans.UVs.Add(uv2);
            ans.Normals = new List <Vector4>();
            ans.Normals.Add(new Vector4(normal.X, normal.Y, normal.Z, -1f));
            ans.Tangents = new List <Vector4>();
            ans.Tangents.Add(new Vector4(tangets.X, tangets.Y, tangets.Z, tangentW));
            ans.Tangents.Add(new Vector4(tangets2.X, tangets2.Y, tangets2.Z, tangentW));
            ans.Colors = new List <FLVER.Vertex.Color>();
            ans.Colors.Add(new FLVER.Vertex.Color(255, 255, 255, 255));

            return(ans);
        }
Beispiel #6
0
    static void ExportModel(MenuCommand menuCommand)
    {
        if (Selection.activeObject == null)
        {
            return;
        }
        var assetPath = AssetDatabase.GetAssetPath(Selection.activeObject);

        if (!assetPath.ToUpper().EndsWith(".FBX"))
        {
            EditorUtility.DisplayDialog("Invalid asset", "Please select an fbx asset", "Ok");
        }

        // Load the FBX as a prefab
        //GameObject obj = PrefabUtility.LoadPrefabContents(assetPath);
        GameObject obj = AssetDatabase.LoadAssetAtPath <GameObject>(assetPath);

        // Go through everything and strip the prefixes fbx exporters love to add
        Stack <GameObject> gameObjects = new Stack <GameObject>();
        GameObject         bonesRoot   = null;
        GameObject         meshesRoot  = null;

        gameObjects.Push(obj);
        while (gameObjects.Count > 0)
        {
            var o = gameObjects.Pop();
            o.name = o.name.Split(':').Last();
            if (o.name == "Bones")
            {
                bonesRoot = o;
            }
            if (o.name == "Meshes")
            {
                meshesRoot = o;
            }
            for (int i = 0; i < o.transform.childCount; i++)
            {
                gameObjects.Push(o.transform.GetChild(i).gameObject);
            }
        }

        // Load the source c0000 and target flvers

        /*var sourceBnd = BND4.Read($@"{DarkSoulsTools.Interroot}\chr\c0000.chrbnd.dcx");
         * var sourceFlver = FLVER.Read(sourceBnd.Files.Where(x => x.Name.ToUpper().EndsWith(".FLVER")).First().Bytes);
         * var targetBnd = BND4.Read($@"{DarkSoulsTools.Interroot}\parts\lg_m_9000.partsbnd.dcx");
         * var targetFlver = FLVER.Read(targetBnd.Files.Where(x => x.Name.ToUpper().EndsWith(".FLVER")).First().Bytes);*/
        var sourceBnd   = BND4.Read($@"{DarkSoulsTools.Interroot}\chr\c4033.chrbnd.dcx");
        var sourceFlver = FLVER.Read(sourceBnd.Files.Where(x => x.Name.ToUpper().EndsWith(".FLVER")).First().Bytes);
        var targetBnd   = BND4.Read($@"{DarkSoulsTools.Interroot}\chr\c4033.chrbnd.dcx");
        var targetFlver = FLVER.Read(targetBnd.Files.Where(x => x.Name.ToUpper().EndsWith(".FLVER")).First().Bytes);

        // Build a bone reindexing table
        Dictionary <string, int> SourceBoneTable = new Dictionary <string, int>();

        for (int i = 0; i < sourceFlver.Bones.Count; i++)
        {
            if (!SourceBoneTable.ContainsKey(sourceFlver.Bones[i].Name))
            {
                SourceBoneTable.Add(sourceFlver.Bones[i].Name, i);
            }
        }

        if (meshesRoot == null)
        {
            throw new Exception("Could not find Meshes group for this FBX");
        }

        if (bonesRoot == null)
        {
            throw new Exception("Could not find Bones group for this FBX");
        }

        //sourceFlver.Bones.Add(targetFlver.Bones[29]);
        var templateMesh = targetFlver.Meshes.First();

        targetFlver.Bones = sourceFlver.Bones;
        targetFlver.Meshes.Clear();
        //targetFlver.SekiroUnk = sourceFlver.SekiroUnk;

        for (var meshIdx = 0; meshIdx < meshesRoot.transform.childCount; meshIdx++)
        {
            // Get the mesh object
            var meshObj = meshesRoot.transform.GetChild(meshIdx).gameObject;

            // Get the skin and mesh
            var meshSkin = meshObj.GetComponent <SkinnedMeshRenderer>();
            var bones    = meshSkin.bones;
            var mesh     = meshSkin.sharedMesh;

            // Remap table to recover source bone indices
            var boneRemap = new int[bones.Length];
            for (int i = 0; i < bones.Length; i++)
            {
                var name = bones[i].gameObject.name;
                if (SourceBoneTable.ContainsKey(name))
                {
                    boneRemap[i] = SourceBoneTable[name];
                }
                else
                {
                    boneRemap[i] = 0;
                }
            }

            // Build the submesh's bone table
            HashSet <int> usedBones = new HashSet <int>();
            foreach (var weight in mesh.boneWeights)
            {
                if (weight.boneIndex0 >= 0)
                {
                    usedBones.Add(boneRemap[weight.boneIndex0]);
                }
                if (weight.boneIndex1 >= 0)
                {
                    usedBones.Add(boneRemap[weight.boneIndex1]);
                }
                if (weight.boneIndex2 >= 0)
                {
                    usedBones.Add(boneRemap[weight.boneIndex2]);
                }
                if (weight.boneIndex3 >= 0)
                {
                    usedBones.Add(boneRemap[weight.boneIndex3]);
                }
            }

            // Bad hack
            for (int i = 0; i < targetFlver.Bones.Count(); i++)
            {
                usedBones.Add(i);
            }

            var submeshBones      = usedBones.OrderBy(x => x).ToArray();
            var meshToSubmeshBone = new Dictionary <int, int>();
            for (int i = 0; i < submeshBones.Count(); i++)
            {
                meshToSubmeshBone.Add(submeshBones[i], i);
            }

            // Finally port the mesh to the target
            //var fmesh = targetFlver.Meshes[0];
            var fmesh = new FLVER.Mesh(templateMesh);
            fmesh.BoneIndices = sourceFlver.Meshes[0].BoneIndices; //submeshBones.ToList();
            var min = mesh.bounds.min;
            var max = mesh.bounds.max;
            //fmesh.BoundingBoxMax = sourceFlver.Header.BoundingBoxMax;
            //fmesh.BoundingBoxMin = new System.Numerics.Vector3(max.x*100, max.y*100, max.z*100);
            //fmesh.BoundingBoxMin = sourceFlver.Header.BoundingBoxMin;
            //fmesh.MaterialIndex = 0;
            //targetFlver.Header.BoundingBoxMin = sourceFlver.Header.BoundingBoxMin;
            //targetFlver.Header.BoundingBoxMax = sourceFlver.Header.BoundingBoxMax;

            /*foreach (var b in usedBones)
             * {
             *  targetFlver.Bones[b].Unk3C = 8;
             * }*/
            foreach (var b in targetFlver.Bones)
            {
                if (b.Unk3C == 2)
                {
                    b.Unk3C = 8;
                }
            }
            //targetFlver.Bones[140].Unk3C = 4;
            //targetFlver.Bones[140].Name = "LG_M_9000";

            // Port vertices
            fmesh.Vertices.Clear();
            fmesh.Vertices.Capacity = mesh.vertexCount;

            var mverts = mesh.vertices;
            var mnorms = mesh.normals;
            var mtangs = mesh.tangents;
            var muvs   = mesh.uv;
            var mbones = mesh.boneWeights;

            for (int i = 0; i < mesh.vertexCount; i++)
            {
                var vert = new FLVER.Vertex();
                var pos  = mverts[i];
                vert.Positions.Add(new System.Numerics.Vector3(pos.x, pos.y, pos.z));
                var normal = mnorms[i];
                vert.Normals.Add(new System.Numerics.Vector4(-normal.x, -normal.y, -normal.z, -1.0f));
                var tangent = mtangs[i];
                vert.Tangents.Add(new System.Numerics.Vector4(-tangent.x, -tangent.y, -tangent.z, -tangent.w));
                vert.Tangents.Add(new System.Numerics.Vector4(-tangent.x, -tangent.y, -tangent.z, -tangent.w));
                var color = new Color32(0xFF, 0xFF, 0x00, 0xFF); //mesh.colors32[i];
                vert.Colors.Add(new FLVER.Vertex.Color(color.a, color.r, color.g, color.b));

                /*vert.UVs.Add(new System.Numerics.Vector3(0.0f, 0.0f, 0.0f));
                *  vert.UVs.Add(new System.Numerics.Vector3(0.0f, 0.0f, 0.0f));
                *  vert.UVs.Add(new System.Numerics.Vector3(0.0f, 0.0f, 0.0f));
                *  vert.UVs.Add(new System.Numerics.Vector3(0.0f, 0.0f, 0.0f));*/
                var uv = muvs[i];
                vert.UVs.Add(new System.Numerics.Vector3(uv.x, 1.0f - uv.y, 0.0f));
                vert.UVs.Add(new System.Numerics.Vector3(uv.x, 1.0f - uv.y, 0.0f));
                vert.UVs.Add(new System.Numerics.Vector3(uv.x, 1.0f - uv.y, 0.0f));
                vert.UVs.Add(new System.Numerics.Vector3(uv.x, 1.0f - uv.y, 0.0f));
                vert.BoneIndices = new int[4];
                vert.BoneWeights = new float[4];
                var bone = mbones[i];
                //vert.Tangents.Add(new System.Numerics.Vector4(bone.weight0, bone.weight1, bone.weight2, bone.weight3));
                vert.BoneWeights[0] = bone.weight0;
                vert.BoneWeights[1] = bone.weight1;
                vert.BoneWeights[2] = bone.weight2;
                vert.BoneWeights[3] = bone.weight3;
                vert.BoneIndices[0] = meshToSubmeshBone[boneRemap[bone.boneIndex0]];
                vert.BoneIndices[1] = meshToSubmeshBone[boneRemap[bone.boneIndex1]];
                vert.BoneIndices[2] = meshToSubmeshBone[boneRemap[bone.boneIndex2]];
                vert.BoneIndices[3] = meshToSubmeshBone[boneRemap[bone.boneIndex3]];
                for (int b = 0; b < 3; b++)
                {
                    if (vert.BoneIndices[b] == -1)
                    {
                        vert.BoneIndices[b] = 0;
                    }
                }

                fmesh.Vertices.Add(vert);
            }

            // Port faceset
            var fset  = new FLVER.FaceSet(fmesh.FaceSets[0]);
            var tris  = new uint[mesh.triangles.Count()];
            var mtris = mesh.triangles;
            for (int i = 0; i < tris.Count(); i++)
            {
                tris[i] = ((uint)mtris[i]);
            }
            fset.Vertices      = tris;
            fset.CullBackfaces = false;
            fset.TriangleStrip = false;

            fmesh.FaceSets.Clear();
            var fset2 = new FLVER.FaceSet(FLVER.FaceSet.FSFlags.LodLevel1, false, false, fset.Unk06, fset.Unk07, fset.IndexSize, fset.Vertices);
            var fset3 = new FLVER.FaceSet(FLVER.FaceSet.FSFlags.LodLevel2, false, false, fset.Unk06, fset.Unk07, fset.IndexSize, fset.Vertices);
            var fset4 = new FLVER.FaceSet(FLVER.FaceSet.FSFlags.Unk80000000, false, false, fset.Unk06, fset.Unk07, fset.IndexSize, fset.Vertices);
            fmesh.FaceSets.Add(fset);
            fmesh.FaceSets.Add(fset2);
            fmesh.FaceSets.Add(fset3);
            fmesh.FaceSets.Add(fset4);
            fmesh.MaterialIndex = meshIdx;
            //fmesh.MaterialIndex = 0;

            targetFlver.Meshes.Add(fmesh);
            //targetFlver.BufferLayouts
        }

        //targetFlver.Materials[0].MTD = $@"M[ARSN].mtd";

        targetFlver.Materials[0].MTD = "C[ARSN].mtd";
        targetFlver.Materials[0].Textures[0].Type = "g_DiffuseTexture";
        targetFlver.Materials[0].Textures[0].Path = "c5020_shrek_a.dds";
        targetFlver.Materials[0].Textures[1].Path = "";
        targetFlver.Materials[0].Textures[2].Path = "";
        targetFlver.Materials[0].Textures[3].Type = "g_BumpmapTexture";
        targetFlver.Materials[0].Textures[3].Path = "SYSTEX_DummyNormal.tga";
        targetFlver.Materials.Add(new FLVER.Material("shrek2", "C[ARSN].mtd", targetFlver.Materials[0].Flags, targetFlver.Materials[0].GXBytes));
        targetFlver.Materials[1].MTD = "C[ARSN].mtd";
        targetFlver.Materials[1].Textures.Add(new FLVER.Texture(targetFlver.Materials[0].Textures[0]));
        targetFlver.Materials[1].Textures.Add(new FLVER.Texture(targetFlver.Materials[0].Textures[1]));
        targetFlver.Materials[1].Textures.Add(new FLVER.Texture(targetFlver.Materials[0].Textures[2]));
        targetFlver.Materials[1].Textures.Add(new FLVER.Texture(targetFlver.Materials[0].Textures[3]));
        targetFlver.Materials[1].Textures[0].Type = "g_DiffuseTexture";
        targetFlver.Materials[1].Textures[0].Path = "c5020_shrekshirt_a.dds";
        targetFlver.Materials[1].Textures[1].Path = "";
        targetFlver.Materials[1].Textures[2].Path = "";
        targetFlver.Materials[1].Textures[3].Type = "g_BumpmapTexture";
        targetFlver.Materials[1].Textures[3].Path = "SYSTEX_DummyNormal.tga";

        // Finally save
        targetBnd.Files.Where(x => x.Name.ToUpper().EndsWith(".FLVER")).First().Bytes = targetFlver.Write();
        //targetBnd.Write($@"{DarkSoulsTools.ModProjectDirectory}\parts\lg_m_9000.partsbnd.dcx", DCX.Type.SekiroDFLT);
        targetBnd.Write($@"{DarkSoulsTools.ModProjectDirectory}\chr\c4033.chrbnd.dcx", DCX.Type.DarkSouls3);
    }
Beispiel #7
0
        //Current, best version can load FBX, OBJ, DAE etc.
        //Use assimp library
        static void importFBX()
        {
            AssimpContext importer = new AssimpContext();

            // importer.SetConfig(new NormalSmoothingAngleConfig(66.0f));

            //m_model.Meshes[0].Bones[0].VertexWeights[0].
            var    openFileDialog2 = new OpenFileDialog();
            string res             = "";

            if (openFileDialog2.ShowDialog() != DialogResult.OK)
            {
                return;
            }
            res = openFileDialog2.FileName;


            //Prepare bone name convertion table:
            string assemblyPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            string convertStr   = File.ReadAllText(assemblyPath + "\\boneConvertion.ini");

            //Console.WriteLine("Test reading" + convertStr);
            string[] convertStrlines = convertStr.Split(
                new[] { "\r\n", "\r", "\n" },
                StringSplitOptions.None
                );
            Dictionary <string, string> convertionTable = new Dictionary <string, string>();

            for (int i2 = 0; i2 + 1 < convertStrlines.Length; i2++)
            {
                string target = convertStrlines[i2];
                if (target == null)
                {
                    continue;
                }
                if (target.IndexOf('#') == 0)
                {
                    continue;
                }
                Console.WriteLine(target + "->" + convertStrlines[i2 + 1]);
                convertionTable.Add(target, convertStrlines[i2 + 1]);
                i2++;
            }

            //Table prepartion finished

            Scene md = importer.ImportFile(res, PostProcessSteps.CalculateTangentSpace);// PostProcessPreset.TargetRealTimeMaximumQuality

            MessageBox.Show("Meshes count:" + md.Meshes.Count + "Material count:" + md.MaterialCount + "");

            boneParentList = new Dictionary <String, String>();
            //Build the parent list of bones.

            printNodeStruct(md.RootNode);

            //First, added a custom default layout.
            int layoutCount = targetFlver.BufferLayouts.Count;

            FLVER.BufferLayout newBL = new FLVER.BufferLayout();

            newBL.Add(new FLVER.BufferLayout.Member(0, 0, FLVER.BufferLayout.MemberType.Float3, FLVER.BufferLayout.MemberSemantic.Position, 0));
            newBL.Add(new FLVER.BufferLayout.Member(0, 12, FLVER.BufferLayout.MemberType.Byte4B, FLVER.BufferLayout.MemberSemantic.Normal, 0));
            newBL.Add(new FLVER.BufferLayout.Member(0, 16, FLVER.BufferLayout.MemberType.Byte4B, FLVER.BufferLayout.MemberSemantic.Tangent, 0));
            newBL.Add(new FLVER.BufferLayout.Member(0, 20, FLVER.BufferLayout.MemberType.Byte4B, FLVER.BufferLayout.MemberSemantic.Tangent, 1));

            newBL.Add(new FLVER.BufferLayout.Member(0, 24, FLVER.BufferLayout.MemberType.Byte4B, FLVER.BufferLayout.MemberSemantic.BoneIndices, 0));
            newBL.Add(new FLVER.BufferLayout.Member(0, 28, FLVER.BufferLayout.MemberType.Byte4C, FLVER.BufferLayout.MemberSemantic.BoneWeights, 0));
            newBL.Add(new FLVER.BufferLayout.Member(0, 32, FLVER.BufferLayout.MemberType.Byte4C, FLVER.BufferLayout.MemberSemantic.VertexColor, 1));
            newBL.Add(new FLVER.BufferLayout.Member(0, 36, FLVER.BufferLayout.MemberType.UVPair, FLVER.BufferLayout.MemberSemantic.UV, 0));

            targetFlver.BufferLayouts.Add(newBL);

            int     materialCount       = targetFlver.Materials.Count;
            Boolean flipYZ              = false;
            Boolean setTexture          = false;
            Boolean setAmbientAsDiffuse = false;
            Boolean setLOD              = false;

            var confirmResult = MessageBox.Show("Do you want to switch YZ axis values? \n It may help importing some fbx files.",
                                                "Set",
                                                MessageBoxButtons.YesNo);

            if (confirmResult == DialogResult.Yes)
            {
                flipYZ = true;
            }

            var confirmResult2 = MessageBox.Show("Auto set texture pathes?",
                                                 "Set",
                                                 MessageBoxButtons.YesNo);

            if (confirmResult2 == DialogResult.Yes)
            {
                setTexture = true;


                /* var res3 = MessageBox.Show("Auto ambient texture as diffuse texture?",
                 *                  "Set",
                 *                  MessageBoxButtons.YesNo);
                 *
                 * if (res3 == DialogResult.Yes)
                 * {
                 *   setAmbientAsDiffuse = true;
                 * }*/
            }

            var confirmResult3 = MessageBox.Show("Set LOD level? (Only neccssary if this model need to be viewed far away)",
                                                 "Set",
                                                 MessageBoxButtons.YesNo);

            if (confirmResult3 == DialogResult.Yes)
            {
                setLOD = true;
            }



            foreach (var mat in md.Materials)
            {
                FLVER.Material matnew = new JavaScriptSerializer().Deserialize <FLVER.Material>(new JavaScriptSerializer().Serialize(targetFlver.Materials[0]));
                matnew.Name = res.Substring(res.LastIndexOf('\\') + 1) + "_" + mat.Name;
                // mat.HasTextureDiffuse

                if (setTexture)
                {
                    if (setAmbientAsDiffuse)
                    {
                        if (mat.HasTextureEmissive)
                        {
                            SetFlverMatPath(matnew, "g_DiffuseTexture", FindFileName(mat.TextureEmissive.FilePath) + ".tif");
                        }
                    }
                    else
                    if (mat.HasTextureDiffuse) //g_DiffuseTexture
                    {
                        //  MessageBox.Show("Diffuse mat is" + FindFileName( mat.TextureDiffuse.FilePath));
                        SetFlverMatPath(matnew, "g_DiffuseTexture", FindFileName(mat.TextureDiffuse.FilePath) + ".tif");
                    }
                    if (mat.HasTextureNormal)//g_BumpmapTexture
                    {
                        //MessageBox.Show("Diffuse mat is" + FindFileName(mat.TextureNormal.FilePath));
                        SetFlverMatPath(matnew, "g_BumpmapTexture", FindFileName(mat.TextureNormal.FilePath) + ".tif");
                    }
                    if (mat.HasTextureSpecular)//g_SpecularTexture
                    {
                        /// MessageBox.Show("Specualr mat is" + FindFileName(mat.TextureSpecular.FilePath));
                        SetFlverMatPath(matnew, "g_SpecularTexture", FindFileName(mat.TextureSpecular.FilePath) + ".tif");
                    }
                }
                targetFlver.Materials.Add(matnew);
            }


            //mn.MaterialIndex = materialCount;

            foreach (var m in md.Meshes)
            {
                /* MessageBox.Show("Name:" + m.Name + "\nHas bones:" + m.HasBones + "\nHas normal:" + m.HasNormals + "\nHas tangent" + m.HasTangentBasis +
                 *   "\nVrtices count: " + m.VertexCount
                 *   );*/


                FLVER.Mesh mn = new FLVER.Mesh();
                mn.MaterialIndex = 0;
                mn.BoneIndices   = new List <int>();
                mn.BoneIndices.Add(0);
                mn.BoneIndices.Add(1);
                mn.BoundingBoxMax   = new Vector3(1, 1, 1);
                mn.BoundingBoxMin   = new Vector3(-1, -1, -1);
                mn.BoundingBoxUnk   = new Vector3();
                mn.Unk1             = 0;
                mn.DefaultBoneIndex = 0;
                mn.Dynamic          = true;
                mn.VertexBuffers    = new List <FLVER.VertexBuffer>();
                mn.VertexBuffers.Add(new FLVER.VertexBuffer(0, layoutCount, -1));
                mn.Vertices = new List <FLVER.Vertex>();

                List <List <int> >   verticesBoneIndices = new List <List <int> >();
                List <List <float> > verticesBoneWeights = new List <List <float> >();


                //If it has bones, then record the bone weight info
                if (m.HasBones)
                {
                    for (int i2 = 0; i2 < m.VertexCount; i2++)
                    {
                        verticesBoneIndices.Add(new List <int>());
                        verticesBoneWeights.Add(new List <float>());
                    }

                    for (int i2 = 0; i2 < m.BoneCount; i2++)
                    {
                        string boneName  = m.Bones[i2].Name;
                        int    boneIndex = 0;

                        if (convertionTable.ContainsKey(m.Bones[i2].Name))
                        {
                            boneName = convertionTable[boneName];
                            // m.Bones[i2].Name = convertionTable[m.Bones[i2].Name];
                            boneIndex = findFLVER_Bone(targetFlver, boneName);
                        }
                        else
                        {
                            Console.WriteLine("Cannot find ->" + boneName);
                            //If cannot find a corresponding boneName in convertion.ini then
                            //Try to find org bone's parent, check if it
                            boneIndex = findFLVER_Bone(targetFlver, boneName);


                            //if such bone can not be found in flver, then check its parent to see if it can be convert to its parent bone.
                            //check up to 5th grand parent.
                            for (int bp = 0; bp < boneFindParentTimes; bp++)
                            {
                                if (boneIndex == -1)
                                {
                                    if (boneParentList.ContainsValue(boneName))
                                    {
                                        if (boneParentList[boneName] != null)
                                        {
                                            boneName = boneParentList[boneName];
                                            if (convertionTable.ContainsKey(boneName))
                                            {
                                                boneName = convertionTable[boneName];
                                            }
                                            boneIndex = findFLVER_Bone(targetFlver, boneName);
                                        }
                                    }
                                }
                            }
                        }


                        if (boneIndex == -1)
                        {
                            boneIndex = 0;
                        }
                        for (int i3 = 0; i3 < m.Bones[i2].VertexWeightCount; i3++)
                        {
                            var vw = m.Bones[i2].VertexWeights[i3];

                            verticesBoneIndices[vw.VertexID].Add(boneIndex);
                            verticesBoneWeights[vw.VertexID].Add(vw.Weight);
                        }
                    }
                }

                // m.Bones[0].VertexWeights[0].
                for (int i = 0; i < m.Vertices.Count; i++)
                {
                    var vit = m.Vertices[i];
                    //m.TextureCoordinateChannels[0]
                    var channels = m.TextureCoordinateChannels[0];

                    var uv1 = new Vector3D();
                    var uv2 = new Vector3D();

                    if (channels != null && m.TextureCoordinateChannelCount > 0)
                    {
                        uv1   = getMyV3D(channels[i]);
                        uv1.Y = 1 - uv1.Y;
                        uv2   = getMyV3D(channels[i]);
                        uv2.Y = 1 - uv2.Y;
                        if (m.TextureCoordinateChannelCount > 1)
                        {
                            // uv2 = getMyV3D((m.TextureCoordinateChannels[1])[i]);
                        }
                    }

                    var normal = new Vector3D(0, 1, 0);
                    if (m.HasNormals && m.Normals.Count > i)
                    {
                        normal = getMyV3D(m.Normals[i]).normalize();
                    }



                    //Vector3D tangent = new Vector3D( crossPorduct( getMyV3D(m.Tangents[i]).normalize().toXnaV3() , normal.toXnaV3())).normalize();
                    //var tangent = RotatePoint(normal.toNumV3(), 0, (float)Math.PI / 2, 0);
                    var tangent = new Vector3D(1, 0, 0);
                    if (m.Tangents.Count > i)
                    {
                        tangent = getMyV3D(m.Tangents[i]).normalize();
                    }
                    else
                    {
                        //Calculate tanget instead
                        if (m.HasNormals && m.Normals.Count > i)
                        {
                            tangent = new Vector3D(crossPorduct(getMyV3D(m.Normals[i]).normalize().toXnaV3(), normal.toXnaV3())).normalize();
                        }
                    }

                    FLVER.Vertex v = generateVertex(new Vector3(vit.X, vit.Y, vit.Z), uv1.toNumV3(), uv2.toNumV3(), normal.toNumV3(), tangent.toNumV3(), 1);

                    if (flipYZ)
                    {
                        v = generateVertex(new Vector3(vit.X, vit.Z, vit.Y), uv1.toNumV3(), uv2.toNumV3(),
                                           new Vector3(normal.X, normal.Z, normal.Y), new Vector3(tangent.X, tangent.Z, tangent.Y), 1);
                    }


                    if (m.HasBones)
                    {
                        for (int j = 0; j < verticesBoneIndices[i].Count && j < 4; j++)
                        {
                            v.BoneIndices[j] = (verticesBoneIndices[i])[j];
                            v.BoneWeights[j] = (verticesBoneWeights[i])[j];
                        }
                    }
                    mn.Vertices.Add(v);
                }



                List <uint> faceIndexs = new List <uint>();
                for (int i = 0; i < m.FaceCount; i++)
                {
                    if (flipYZ)
                    {
                        if (m.Faces[i].Indices.Count == 3)
                        {
                            faceIndexs.Add((uint)m.Faces[i].Indices[0]);
                            faceIndexs.Add((uint)m.Faces[i].Indices[1]);
                            faceIndexs.Add((uint)m.Faces[i].Indices[2]);
                        }
                        else if (m.Faces[i].Indices.Count == 4)
                        {
                            faceIndexs.Add((uint)m.Faces[i].Indices[0]);
                            faceIndexs.Add((uint)m.Faces[i].Indices[1]);
                            faceIndexs.Add((uint)m.Faces[i].Indices[2]);

                            faceIndexs.Add((uint)m.Faces[i].Indices[2]);
                            faceIndexs.Add((uint)m.Faces[i].Indices[3]);
                            faceIndexs.Add((uint)m.Faces[i].Indices[0]);
                        }
                    }
                    else
                    {
                        if (m.Faces[i].Indices.Count == 3)
                        {
                            faceIndexs.Add((uint)m.Faces[i].Indices[0]);
                            faceIndexs.Add((uint)m.Faces[i].Indices[2]);
                            faceIndexs.Add((uint)m.Faces[i].Indices[1]);
                        }
                        else if (m.Faces[i].Indices.Count == 4)
                        {
                            faceIndexs.Add((uint)m.Faces[i].Indices[0]);
                            faceIndexs.Add((uint)m.Faces[i].Indices[2]);
                            faceIndexs.Add((uint)m.Faces[i].Indices[1]);

                            faceIndexs.Add((uint)m.Faces[i].Indices[2]);
                            faceIndexs.Add((uint)m.Faces[i].Indices[0]);
                            faceIndexs.Add((uint)m.Faces[i].Indices[3]);
                        }
                    }
                }
                //
                mn.FaceSets = new List <FLVER.FaceSet>();
                //FLVER.Vertex myv = new FLVER.Vertex();
                //myv.Colors = new List<FLVER.Vertex.Color>();

                mn.FaceSets.Add(generateBasicFaceSet());
                mn.FaceSets[0].Vertices = faceIndexs.ToArray();
                if (mn.FaceSets[0].Vertices.Length > 65534)
                {
                    MessageBox.Show("There are more than 65535 vertices in a mesh , switch to 32 bits index size mode.");
                    mn.FaceSets[0].IndexSize = 32;
                }


                if (setLOD == true)
                {
                    //Special thanks to Meowmaritus
                    {
                        FLVER.FaceSet fs = generateBasicFaceSet();
                        fs.Flags     = SoulsFormats.FLVER.FaceSet.FSFlags.LodLevel1;
                        fs.IndexSize = mn.FaceSets[0].IndexSize;
                        fs.Vertices  = (uint[])(mn.FaceSets[0].Vertices.Clone());
                        mn.FaceSets.Add(fs);
                    }

                    {
                        FLVER.FaceSet fs = generateBasicFaceSet();
                        fs.Flags     = SoulsFormats.FLVER.FaceSet.FSFlags.LodLevel2;
                        fs.IndexSize = mn.FaceSets[0].IndexSize;
                        fs.Vertices  = (uint[])(mn.FaceSets[0].Vertices.Clone());
                        mn.FaceSets.Add(fs);
                    }
                    //unk8000000000 is the motion blur
                    {
                        FLVER.FaceSet fs = generateBasicFaceSet();
                        fs.Flags     = SoulsFormats.FLVER.FaceSet.FSFlags.Unk80000000;
                        fs.IndexSize = mn.FaceSets[0].IndexSize;
                        fs.Vertices  = (uint[])(mn.FaceSets[0].Vertices.Clone());
                        mn.FaceSets.Add(fs);
                    }

                    {
                        FLVER.FaceSet fs = generateBasicFaceSet();
                        fs.Flags     = SoulsFormats.FLVER.FaceSet.FSFlags.LodLevel1 | SoulsFormats.FLVER.FaceSet.FSFlags.Unk80000000;
                        fs.IndexSize = mn.FaceSets[0].IndexSize;
                        fs.Vertices  = (uint[])(mn.FaceSets[0].Vertices.Clone());
                        mn.FaceSets.Add(fs);
                    }

                    {
                        FLVER.FaceSet fs = generateBasicFaceSet();
                        fs.Flags     = SoulsFormats.FLVER.FaceSet.FSFlags.LodLevel2 | SoulsFormats.FLVER.FaceSet.FSFlags.Unk80000000;
                        fs.IndexSize = mn.FaceSets[0].IndexSize;
                        fs.Vertices  = (uint[])(mn.FaceSets[0].Vertices.Clone());
                        mn.FaceSets.Add(fs);
                    }
                }


                mn.MaterialIndex = materialCount + m.MaterialIndex;


                targetFlver.Meshes.Add(mn);
            }

            MessageBox.Show("Added a custom mesh! PLease click modify to save it!");
            updateVertices();
        }
Beispiel #8
0
        public ImportedFLVER2Model ImportFromAssimpScene(Scene scene, FLVER2ImportSettings settings)
        {
            LoadMaterialInfoBankForGame(settings.Game);

            var result = new ImportedFLVER2Model();
            var flver  = result.Flver = new FLVER2();

            flver.Header.BigEndian      = settings.FlverHeader.BigEndian;
            flver.Header.BoundingBoxMax = new NVector3(float.MinValue);
            flver.Header.BoundingBoxMin = new NVector3(float.MaxValue);
            flver.Header.Unicode        = settings.FlverHeader.Unicode;
            flver.Header.Unk4A          = settings.FlverHeader.Unk4A;
            flver.Header.Unk4C          = settings.FlverHeader.Unk4C;
            flver.Header.Unk5C          = settings.FlverHeader.Unk5C;
            flver.Header.Unk5D          = settings.FlverHeader.Unk5D;
            flver.Header.Unk68          = settings.FlverHeader.Unk68;
            flver.Header.Version        = settings.FlverHeader.Version;

            var flverSceneMatrix = NMatrix.CreateScale(NVector3.One * settings.SceneScale);



            if (settings.ConvertFromZUp)
            {
                flverSceneMatrix *= SapMath.ZUpToYUpNMatrix;
            }

            //flverSceneMatrix *= NMatrix.CreateRotationY(SapMath.Pi);

            flverSceneMatrix *= settings.SceneCorrectMatrix;



            flverSceneMatrix *= NMatrix.CreateScale(1, 1, -1);


            var coordMat = AssimpUtilities.GetSceneCoordSystemMatrix(scene);

            scene.RootNode.Transform *= coordMat;

            var skeletonRootNode = AssimpUtilities.FindRootNode(scene, settings.RootNodeName, out Matrix4x4 skeletonRootNodeMatrix);


            var metaskeleton = FLVERImportHelpers.GenerateFlverMetaskeletonFromRootNode(
                skeletonRootNode, skeletonRootNodeMatrix, settings.SceneScale);

            flver.Bones   = metaskeleton.Bones;
            flver.Dummies = metaskeleton.DummyPoly;

            foreach (var b in flver.Bones)
            {
                // Mark as dummied-out bone until iterating over them later and seeing which are weighted to meshes.
                if (b.ParentIndex == -1)
                {
                    b.Unk3C = 1;
                }
            }

            var usesIndirectBones = flver.Header.Version <= 0x20010;

            if (settings.SkeletonTransformsOverride != null)
            {
                flver.Bones = settings.SkeletonTransformsOverride;
            }



            //var flverMaterialList = new List<FLVER2.Material>();

            foreach (var material in scene.Materials)
            {
                string[] materialNameSplit = material.Name.Split('|');
                string   mtd = materialNameSplit.Length > 1 ? materialNameSplit[1].Trim() + ".mtd" : null;

                // If MTD doesn't exist, use original
                mtd = MaterialInfoBankPerGame[settings.Game].FallbackToDefaultMtdIfNecessary(mtd, Logger);

                //ErrorTODO: materialNameSplit should be 2 items long.
                var flverMaterial = new FLVER2.Material(materialNameSplit[0].Trim(), mtd, 0);


                void AddTextureSlot(TextureSlot slot, string ingameSlot)
                {
                    flverMaterial.Textures.Add(new FLVER2.Texture(type: ingameSlot,
                                                                  path: slot.FilePath != null ? Path.GetFullPath(slot.FilePath) : "",
                                                                  scale: System.Numerics.Vector2.One,
                                                                  1, true, 0, 0, 0));

                    string texName = Path.GetFileNameWithoutExtension(slot.FilePath);

                    byte[] texData = scene.GetEmbeddedTexture(slot.FilePath)?.CompressedData;

                    if (texData != null)
                    {
                        var ddsFormat = TPFTextureFormatFinder.GetTpfFormatFromDdsBytes(texData);

                        result.Textures.Add(new TPF.Texture(texName, format: ddsFormat, flags1: 0, bytes: texData));
                    }
                }

                var materialDefinition = MaterialInfoBankPerGame[settings.Game].MaterialDefs[mtd.ToLower()];
                var texChanDefs        = materialDefinition.TextureChannels;
                foreach (var kvp in texChanDefs)
                {
                    if (kvp.Key.Index == 0)
                    {
                        if (kvp.Key.Semantic == TextureChannelSemantic.Diffuse)
                        {
                            AddTextureSlot(material.TextureDiffuse, kvp.Value);
                        }
                        else if (kvp.Key.Semantic == TextureChannelSemantic.Specular)
                        {
                            AddTextureSlot(material.TextureSpecular, kvp.Value);
                        }
                        else if (kvp.Key.Semantic == TextureChannelSemantic.Normals)
                        {
                            AddTextureSlot(material.TextureNormal, kvp.Value);
                        }
                        else if (kvp.Key.Semantic == TextureChannelSemantic.Emissive)
                        {
                            AddTextureSlot(material.TextureEmissive, kvp.Value);
                        }
                        else
                        {
                            flverMaterial.Textures.Add(new FLVER2.Texture(type: kvp.Value,
                                                                          path: string.Empty,
                                                                          scale: System.Numerics.Vector2.One,
                                                                          0, false, 0, 0, 0));
                        }
                    }
                }

                if (materialDefinition.GXItems.Count > 0)
                {
                    flverMaterial.GXIndex = flver.GXLists.Count;
                    var gxList = new FLVER2.GXList();

                    for (int i = 0; i < materialDefinition.GXItems.Count; i++)
                    {
                        var    gxid  = materialDefinition.GXItems[i].GXID;
                        var    unk04 = materialDefinition.GXItems[i].Unk04;
                        byte[] data  = MaterialInfoBankPerGame[settings.Game].DefaultGXItemDataExamples[mtd][i];
                        gxList.Add(new FLVER2.GXItem(gxid, unk04, data));
                    }
                    flver.GXLists.Add(gxList);
                }

                flver.Materials.Add(flverMaterial);
                //flverMaterialList.Add(flverMaterial);
            }

            //var properBoneParentRegistry = new Dictionary<Bone, string>();

            //foreach (var mesh in scene.Meshes)
            //{
            //    foreach (var b in mesh.Bones)
            //    {
            //        bool alreadyRegistered = false;
            //        foreach (var bone in properBoneParentRegistry.Keys)
            //        {
            //            if (bone.Name == b.Name)
            //            {
            //                alreadyRegistered = true;
            //                break;
            //            }
            //        }
            //        if (alreadyRegistered)
            //            continue;
            //        mesh.
            //        properBoneParentRegistry.Add(b, b.)
            //    }
            //}

            if (settings.BoneNameRemapper != null)
            {
                foreach (var bn in settings.BoneNameRemapper)
                {
                    var bone = flver.Bones.FindIndex(b => b.Name == bn.Key);
                    if (bone >= 0)
                    {
                        flver.Bones[bone].Name = bn.Value;
                    }
                }
            }

            foreach (var mesh in scene.Meshes)
            {
                var flverMesh = new FLVER2.Mesh();

                flverMesh.BoundingBox = new FLVER2.Mesh.BoundingBoxes();

                //TODO: ACTUALLY READ FROM THINGS
                flverMesh.Dynamic = 1;



                // Register mesh transform bone:
                //flverMesh.DefaultBoneIndex = flver.Bones.Count;
                //int flverLastRootBoneIndex = flver.Bones.FindLastIndex(b => b.ParentIndex == -1);
                //// Register this new bone as a sibling.
                //if (flverLastRootBoneIndex >= 0)
                //    flver.Bones[flverLastRootBoneIndex].NextSiblingIndex = (short)flverMesh.DefaultBoneIndex;
                //flver.Bones.Add(new FLVER.Bone()
                //{
                //    Name = mesh.Name,
                //    Translation = NVector3.Zero,
                //    Rotation = NVector3.Zero,
                //    Scale = NVector3.One,
                //    BoundingBoxMin = NVector3.One * -0.05f,
                //    BoundingBoxMax = NVector3.One * 0.05f,
                //    // Cross-register sibling from above.
                //    PreviousSiblingIndex = (short)flverLastRootBoneIndex,
                //    NextSiblingIndex = -1,
                //    ParentIndex = -1,
                //    ChildIndex = -1,
                //    Unk3C = 1,
                //});



                int meshUVCount = 0;
                for (int i = 0; i < mesh.UVComponentCount.Length; i++)
                {
                    if (mesh.UVComponentCount[i] > 0)
                    {
                        meshUVCount++;
                    }
                }
                if (mesh.PrimitiveType != PrimitiveType.Triangle)
                {
                    Console.WriteLine();
                }

                var flverFaceSet = new FLVER2.FaceSet();

                //flverFaceSet.TriangleStrip = true;

                // Handle vertex buffers / layouts:
                flverMesh.MaterialIndex = mesh.MaterialIndex;
                //var newMat = flverMaterialList[mesh.MaterialIndex];
                //var indexOfNewMat = flver.Materials.IndexOf(newMat);
                //if (indexOfNewMat >= 0)
                //{
                //    flverMesh.MaterialIndex = indexOfNewMat;
                //}
                //else
                //{
                //    flverMesh.MaterialIndex = flver.Materials.Count;
                //    flver.Materials.Add(newMat);
                //}


                var flverMaterial            = flver.Materials[flverMesh.MaterialIndex];
                var matDefinition            = MaterialInfoBankPerGame[settings.Game].MaterialDefs[flverMaterial.MTD.ToLower()];
                var defaultBufferDeclaration = matDefinition.AcceptableVertexBufferDeclarations[0];

                Dictionary <FLVER.LayoutSemantic, int> requiredVertexBufferMembers =
                    new Dictionary <FLVER.LayoutSemantic, int>();

                foreach (var buff in defaultBufferDeclaration.Buffers)
                {
                    foreach (var m in buff)
                    {
                        if (!requiredVertexBufferMembers.ContainsKey(m.Semantic))
                        {
                            requiredVertexBufferMembers.Add(m.Semantic, 0);
                        }
                        requiredVertexBufferMembers[m.Semantic]++;
                    }

                    int nextLayoutIndex = flver.BufferLayouts.Count;
                    flver.BufferLayouts.Add(buff);
                    var vertBuffer = new FLVER2.VertexBuffer(nextLayoutIndex);
                    flverMesh.VertexBuffers.Add(vertBuffer);
                }



                flverMesh.Vertices = new List <FLVER.Vertex>(mesh.VertexCount);

                for (int i = 0; i < mesh.VertexCount; i++)
                {
                    var newVert = new FLVER.Vertex(uvCapacity: meshUVCount,
                                                   //TODO: Figure out what multiple tangents are used for etc and implement all
                                                   //      of that into the XML vert layout system stuff etc etc.
                                                   tangentCapacity: mesh.HasTangentBasis ? 1 : 0,
                                                   colorCapacity: mesh.VertexColorChannelCount);

                    newVert.Position = NVector3.Transform(mesh.Vertices[i].ToNumerics(), flverSceneMatrix);

                    flver.Header.UpdateBoundingBox(newVert.Position);
                    if (flverMesh.BoundingBox != null)
                    {
                        flverMesh.UpdateBoundingBox(newVert.Position);
                    }

                    newVert.Normal = NVector3.Normalize(NVector3.TransformNormal(mesh.Normals[i].ToNumerics(), flverSceneMatrix));

                    //TODO: TEST THIS AGAINST OTHER GAMES ETC
                    //newVert.NormalW = 127;

                    if (mesh.HasTangentBasis)
                    {
                        //ErrorTODO: Throw error if mesh somehow has tangents but not normals.
                        var tan      = mesh.Tangents[i];
                        var bitanXYZ = mesh.BiTangents[i];
                        //TODO: Check Bitangent W calculation
                        var bitanW = Vector3D.Dot(Vector3D.Cross(tan, mesh.Normals[i]), bitanXYZ) >= 0 ? 1 : -1;
                        var bitanXYZTransformed = NVector3.Normalize(NVector3.TransformNormal(bitanXYZ.ToNumerics(), flverSceneMatrix));
                        newVert.Tangents.Add(new System.Numerics.Vector4(bitanXYZTransformed, bitanW));
                        //TODO: CHECK THIS AND SEE WTF IT EVEN IS SUPPOSED TO BE
                        newVert.Bitangent = new System.Numerics.Vector4(
                            NVector3.TransformNormal(tan.ToNumerics(), flverSceneMatrix), 0);
                    }

                    for (int j = 0; j < meshUVCount; j++)
                    {
                        var uv = mesh.TextureCoordinateChannels[j][i];
                        newVert.UVs.Add(new NVector3(uv.X, 1 - uv.Y, uv.Z));
                    }

                    for (int j = 0; j < mesh.VertexColorChannelCount; j++)
                    {
                        newVert.Colors.Add(mesh.VertexColorChannels[j][i].ToFlverVertexColor());
                    }

                    for (int j = 0; j < 4; j++)
                    {
                        newVert.BoneIndices[j] = -1;
                    }

                    newVert.EnsureLayoutMembers(requiredVertexBufferMembers);

                    flverMesh.Vertices.Add(newVert);
                }

                if (usesIndirectBones)
                {
                    var bonesInMesh = mesh.Bones.OrderByDescending(mb => mb.VertexWeightCount).ToList();
                    foreach (var bone in bonesInMesh)
                    {
                        var boneIndex = flver.Bones.FindIndex(b => b.Name == bone.Name);

                        if (!flverMesh.BoneIndices.Contains(boneIndex))
                        {
                            flverMesh.BoneIndices.Add(boneIndex);
                        }
                    }

                    flverMesh.BoneIndices = flverMesh.BoneIndices.OrderBy(idx => idx).ToList();
                }



                foreach (var bone in mesh.Bones)
                {
                    var boneIndex = flver.Bones.FindIndex(b => b.Name == bone.Name);

                    if (boneIndex == -1)
                    {
                        Logger.LogWarning($"No bone with exact name '{bone.Name}' found. Looking for a bone that starts with that name");
                        boneIndex = flver.Bones.FindIndex(b => b.Name.StartsWith(bone.Name));
                    }

                    var boneDoesNotExist = false;

                    // Mark bone as not-dummied-out since there is geometry skinned to it.
                    if (boneIndex >= 0 && boneIndex < flver.Bones.Count)
                    {
                        flver.Bones[boneIndex].Unk3C = 0;
                    }
                    else
                    {
                        Logger.LogWarning($"Vertex skinned to bone '{bone.Name}' which does NOT exist in the skeleton.");
                        boneDoesNotExist = true;
                    }

                    int GetNextAvailableBoneSlotOfVert(int vertIndex)
                    {
                        if (flverMesh.Vertices[vertIndex].BoneIndices[0] < 0)
                        {
                            return(0);
                        }
                        else if (flverMesh.Vertices[vertIndex].BoneIndices[1] < 0)
                        {
                            return(1);
                        }
                        else if (flverMesh.Vertices[vertIndex].BoneIndices[2] < 0)
                        {
                            return(2);
                        }
                        else if (flverMesh.Vertices[vertIndex].BoneIndices[3] < 0)
                        {
                            return(3);
                        }
                        else
                        {
                            return(-1);
                        }
                    }

                    foreach (var weight in bone.VertexWeights)
                    {
                        int boneSlot = GetNextAvailableBoneSlotOfVert(weight.VertexID);
                        if (boneSlot >= 0)
                        {
                            var indexToAssign = usesIndirectBones ? flverMesh.BoneIndices.IndexOf(boneIndex) : boneIndex;
                            if (indexToAssign == -1)
                            {
                                Console.WriteLine("fatcat");
                            }
                            flverMesh.Vertices[weight.VertexID].BoneIndices[boneSlot] = boneDoesNotExist ? 0 : indexToAssign;
                            flverMesh.Vertices[weight.VertexID].BoneWeights[boneSlot] = boneDoesNotExist ? 0 : weight.Weight;
                            if (!boneDoesNotExist)
                            {
                                flver.Bones[boneIndex].UpdateBoundingBox(flver.Bones, flverMesh.Vertices[weight.VertexID].Position);
                            }
                        }
                    }
                }

                for (int i = 0; i < flverMesh.Vertices.Count; i++)
                {
                    float weightMult = 1 / (
                        flverMesh.Vertices[i].BoneWeights[0] +
                        flverMesh.Vertices[i].BoneWeights[1] +
                        flverMesh.Vertices[i].BoneWeights[2] +
                        flverMesh.Vertices[i].BoneWeights[3]);

                    for (int j = 0; j < 4; j++)
                    {
                        //flverMesh.Vertices[i].BoneWeights[j] = flverMesh.Vertices[i].BoneWeights[j] * weightMult;
                        if (flverMesh.Vertices[i].BoneIndices[j] < 0)
                        {
                            flverMesh.Vertices[i].BoneIndices[j] = 0;
                        }
                    }

                    //TODO: TEST THIS AGAINST OTHER GAMES ETC
                    if (!requiredVertexBufferMembers.ContainsKey(FLVER.LayoutSemantic.BoneIndices))
                    {
                        flverMesh.Vertices[i].NormalW = flverMesh.Vertices[i].BoneIndices[0];
                    }
                }

                //foreach (var face in mesh.Faces)
                //{
                //    //TODO: See if resets need to be added inbetween or anything.
                //    flverFaceSet.Indices.AddRange(face.Indices);
                //}

                flverFaceSet.Indices.AddRange(mesh.GetIndices());

                flverMesh.FaceSets.Add(flverFaceSet);
                GenerateLodAndMotionBlurFacesets(flverMesh);

                flver.Meshes.Add(flverMesh);
            }

            // DEBUGGING

            //flver.Bones.RemoveAt(0);
            //foreach (var mm in flver.Meshes)
            //    for (int mbi = 0; mbi < mm.BoneIndices.Count; mbi++)
            //        mm.BoneIndices[mbi] = mm.BoneIndices[mbi] - 1;
            //foreach (var b in flver.Bones)
            //{
            //    if (b.ParentIndex >= 0)
            //        b.ParentIndex--;
            //    if (b.ChildIndex >= 0)
            //        b.ChildIndex--;
            //    if (b.NextSiblingIndex >= 0)
            //        b.NextSiblingIndex--;
            //    if (b.PreviousSiblingIndex >= 0)
            //        b.PreviousSiblingIndex--;
            //}

            ///////////////////

            foreach (var b in flver.Bones)
            {
                if (settings.SkeletonTransformsOverride != null)
                {
                    var match = settings.SkeletonTransformsOverride.FindIndex(bn => bn.Name == b.Name);
                    if (match >= 0)
                    {
                        b.Translation = settings.SkeletonTransformsOverride[match].Translation;
                        b.Rotation    = settings.SkeletonTransformsOverride[match].Rotation;
                        b.Scale       = settings.SkeletonTransformsOverride[match].Scale;
                    }
                }

                if (float.IsInfinity(b.BoundingBoxMin.X) || float.IsInfinity(b.BoundingBoxMin.Y) || float.IsInfinity(b.BoundingBoxMin.Z) ||
                    float.IsInfinity(b.BoundingBoxMax.X) || float.IsInfinity(b.BoundingBoxMax.Y) || float.IsInfinity(b.BoundingBoxMax.Z))
                {
                    b.BoundingBoxMin = NVector3.One * -0.1f;
                    b.BoundingBoxMax = NVector3.One * 0.1f;
                }
            }

            return(result);
        }
        private List <FLVER.Bone> GetAllBonesReferencedByVertex(FLVER2 f, FLVER2.Mesh m, FLVER.Vertex v)
        {
            if (!PrecalculatedBoneLists.ContainsKey(v))
            {
                List <FLVER.Bone> result = new List <FLVER.Bone>();

                for (var i = 0; i < v.BoneIndices.Length; i++)
                {
                    var vertBoneIndex = v.BoneIndices[i];
                    if (vertBoneIndex >= 0)
                    {
                        if (Importer.JOBCONFIG.UseDirectBoneIndices)
                        {
                            result.Add(f.Bones[vertBoneIndex]);
                        }
                        else
                        {
                            if (m.BoneIndices[vertBoneIndex] >= 0)
                            {
                                result.Add(f.Bones[m.BoneIndices[vertBoneIndex]]);
                            }
                        }
                    }
                }

                PrecalculatedBoneLists.Add(v, result);
            }

            return(PrecalculatedBoneLists[v]);
        }
Beispiel #10
0
 private unsafe void FillColorUNorm(byte *dest, ref FLVER.Vertex v)
 {
 }
Beispiel #11
0
        private unsafe void FillBinormalBitangentSNorm8(sbyte *destBinorm, sbyte *destBitan, ref FLVER.Vertex v, byte index)
        {
            var tan = v.GetTangent(index);
            var t   = Vector3.Normalize(new Vector3(tan.X, tan.Y, tan.Z));

            destBitan[0] = (sbyte)(t.X * 127.0f);
            destBitan[1] = (sbyte)(t.Y * 127.0f);
            destBitan[2] = (sbyte)(t.Z * 127.0f);
            destBitan[3] = (sbyte)(tan.W * 127.0f);

            var bn = Vector3.Cross(Vector3.Normalize(v.Normal), Vector3.Normalize(new Vector3(t.X, t.Y, t.Z))) * tan.W;

            destBinorm[0] = (sbyte)(bn.X * 127.0f);
            destBinorm[1] = (sbyte)(bn.Y * 127.0f);
            destBinorm[2] = (sbyte)(bn.Z * 127.0f);
        }
Beispiel #12
0
 private void FillVertex(ref Vector3 dest, ref FLVER.Vertex v)
 {
     dest = v.Position;
 }
Beispiel #13
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);
        }
Beispiel #14
0
        protected override FbxMesh GenerateFbx()
        {
            string meshName = (Souls.meshRoot != null ? Souls.meshRoot.Name : "") + "_Mesh";

            FbxMesh mesh = FbxMesh.Create(Scene, meshName);

            mesh.InitControlPoints(Souls.mesh.Vertices.Count);

            int layerIndex = mesh.CreateLayer();

            FbxLayer layer = mesh.GetLayer(layerIndex);

            FbxLayerContainer layerContainer = FbxLayerContainer.Create(Scene, meshName + "_LayerContainer");

            FbxLayerElementUV uv = FbxLayerElementUV.Create(layerContainer, "Diffuse");

            layer.SetUVs(uv);

            FbxLayerElementNormal normal = FbxLayerElementNormal.Create(layerContainer, "Normal");

            layer.SetNormals(normal);
            normal.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect);
            normal.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint);

            FbxLayerElementBinormal binormal = FbxLayerElementBinormal.Create(layerContainer, "Binormal");

            layer.SetBinormals(binormal);

            FbxLayerElementTangent tangent = FbxLayerElementTangent.Create(layerContainer, "Tangent");

            layer.SetTangents(tangent);
            tangent.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect);
            tangent.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint);

            for (int vertexIndex = 0; vertexIndex < Souls.mesh.Vertices.Count; ++vertexIndex)
            {
                FLVER.Vertex vertex = Souls.mesh.Vertices[vertexIndex];

                Vector3 position = vertex.Position;

                // this fixes vertex positions since otherwise the model is turned inside out
                // and it appears like it holds weapons in the left hand
                position.Z = -position.Z;

                normal.GetDirectArray().Add(vertex.Normal.ToFbxVector4());

                tangent.GetDirectArray().Add(new FbxVector4(vertex.Tangents[0].X, vertex.Tangents[0].Y, vertex.Tangents[0].Z));

                Vector2 uvValue = new Vector2(0);

                if (vertex.UVs.Count > 0)
                {
                    uvValue.X = vertex.UVs[0].X;
                    uvValue.Y = vertex.UVs[0].Y;
                }

                uv.GetDirectArray().Add(uvValue.ToFbxVector2());

                mesh.SetControlPointAt(position.ToFbxVector4(), vertexIndex);
            }

            for (int faceSetIndex = 0; faceSetIndex < Souls.mesh.FaceSets.Count; ++faceSetIndex)
            {
                FLVER2.FaceSet faceSet = Souls.mesh.FaceSets[faceSetIndex];

                if (faceSet.Flags != FLVER2.FaceSet.FSFlags.None)
                {
                    continue;
                }

                for (int faceStartIndex = 0; faceStartIndex < faceSet.Indices.Count; faceStartIndex += 3)
                {
                    mesh.AddCompletePolygon(
                        faceSet.Indices[faceStartIndex],
                        faceSet.Indices[faceStartIndex + 1],
                        faceSet.Indices[faceStartIndex + 2]
                        );
                    //mesh.AddCompletePolygon(
                    //    faceSet.Indices[faceStartIndex + 2],
                    //    faceSet.Indices[faceStartIndex + 1],
                    //    faceSet.Indices[faceStartIndex]
                    //);
                }
            }

            mesh.BuildMeshEdgeArray();

            FbxGeometryConverter converter = new FbxGeometryConverter(Scene.GetFbxManager());

            converter.ComputeEdgeSmoothingFromNormals(mesh);
            converter.ComputePolygonSmoothingFromEdgeSmoothing(mesh);

            return(mesh);
        }