Exemplo n.º 1
0
        public Model(FLVER flver)
        {
            Submeshes = new List <FlverSubmeshRenderer>();
            var subBoundsPoints = new List <Vector3>();

            foreach (var submesh in flver.Meshes)
            {
                var smm = new FlverSubmeshRenderer(flver, submesh);
                Submeshes.Add(smm);
                subBoundsPoints.Add(smm.Bounds.Min);
                subBoundsPoints.Add(smm.Bounds.Max);
            }

            //DEBUG//
            //Console.WriteLine($"{flver.Meshes[0].DefaultBoneIndex}");
            //Console.WriteLine();
            //Console.WriteLine();
            //foreach (var mat in flver.Materials)
            //{
            //    Console.WriteLine($"{mat.Name}: {mat.MTD}");
            //}
            /////////

            if (Submeshes.Count == 0)
            {
                Bounds    = new BoundingBox();
                IsVisible = false;
            }
            else
            {
                Bounds = BoundingBox.CreateFromPoints(subBoundsPoints);
            }
        }
Exemplo n.º 2
0
        private void RegisterFLVER(int ffxid, FLVER flver)
        {
            if (!FFXs.ContainsKey(ffxid))
            {
                FFXs.Add(ffxid, new FFXData());
            }

            FFXs[ffxid].Model = flver;
        }
Exemplo n.º 3
0
        public Model(FLVER flver)
        {
            Type = ModelType.ModelTypeFlver;

            Submeshes = new List <FlverSubmeshRenderer>();
            var subBoundsPoints = new List <Vector3>();

            foreach (var submesh in flver.Meshes)
            {
                // Blacklist some materials that don't have good shaders and just make the viewer look like a mess
                var mtd = InterrootLoader.GetMTD(Path.GetFileName(flver.Materials[submesh.MaterialIndex].MTD));
                if (mtd != null)
                {
                    if (mtd.ShaderPath.Contains("FRPG_Water_Env"))
                    {
                        continue;
                    }
                    if (mtd.ShaderPath.Contains("FRPG_Water_Reflect.spx"))
                    {
                        continue;
                    }
                }
                var smm = new FlverSubmeshRenderer(this, flver, submesh);
                Submeshes.Add(smm);
                subBoundsPoints.Add(smm.Bounds.Min);
                subBoundsPoints.Add(smm.Bounds.Max);
            }

            //DEBUG//
            //Console.WriteLine($"{flver.Meshes[0].DefaultBoneIndex}");
            //Console.WriteLine();
            //Console.WriteLine();
            //foreach (var mat in flver.Materials)
            //{
            //    Console.WriteLine($"{mat.Name}: {mat.MTD}");
            //}
            /////////

            if (Submeshes.Count == 0)
            {
                Bounds    = new BoundingBox();
                IsVisible = false;
            }
            else
            {
                Bounds = BoundingBox.CreateFromPoints(subBoundsPoints);
            }
        }
Exemplo n.º 4
0
        private void SetBoneBoundingBox(FLVER f, FlverBone b)
        {
            var bb = GetBoundingBox(GetVerticesParentedToBone(f, b).Select(v => (Vector3)v.Position).ToList());

            if (bb.Max.LengthSquared() != 0 || bb.Min.LengthSquared() != 0)
            {
                var matrix = GetParentBoneMatrix(b);
                b.BoundingBoxMin = Vector3.Transform(bb.Min, Matrix.Invert(matrix));
                b.BoundingBoxMax = Vector3.Transform(bb.Max, Matrix.Invert(matrix));
            }
            else
            {
                b.BoundingBoxMin = null;
                b.BoundingBoxMax = null;
            }
        }
Exemplo n.º 5
0
        private List <FlverVertex> GetVerticesParentedToBone(FLVER f, FlverBone b)
        {
            var result = new List <FlverVertex>();

            foreach (var sm in f.Submeshes)
            {
                foreach (var v in sm.Vertices)
                {
                    var bones = v.BoneIndices.GetBones();
                    if (bones.Contains(b))
                    {
                        result.Add(v);
                    }
                }
            }
            return(result);
        }
Exemplo n.º 6
0
        public void FixAllBoundingBoxes(FLVER f)
        {
            foreach (var b in f.Bones)
            {
                SetBoneBoundingBox(f, b);
                if (b.Name == "Dummy")
                {
                    b.Name = "dymmy";
                }
                else if (b.Name == "SFX")
                {
                    b.Name = "SFX用";
                }
            }


            var submeshBBs = new List <BoundingBox>();

            foreach (var sm in f.Submeshes)
            {
                var bb = GetBoundingBox(sm.Vertices.Select(v => (Vector3)v.Position).ToList());
                if (bb.Max.LengthSquared() != 0 || bb.Min.LengthSquared() != 0)
                {
                    submeshBBs.Add(bb);
                }
            }

            if (submeshBBs.Count > 0)
            {
                var finalBB = submeshBBs[0];
                for (int i = 1; i < submeshBBs.Count; i++)
                {
                    finalBB = BoundingBox.CreateMerged(finalBB, submeshBBs[i]);
                }

                f.Header.BoundingBoxMin = finalBB.Min;
                f.Header.BoundingBoxMax = finalBB.Max;
            }
            else
            {
                f.Header.BoundingBoxMin = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
                f.Header.BoundingBoxMax = new Vector3(float.MinValue, float.MinValue, float.MinValue);
            }
        }
Exemplo n.º 7
0
    static public void ImportFlver(DarkSoulsTools.GameType gameType, string path, string assetName, string texturePath = null)
    {
        FLVER          flver;
        FLVERAssetLink link = ScriptableObject.CreateInstance <FLVERAssetLink>();

        if (path.Contains(".mapbnd"))
        {
            BND4 bnd = BND4.Read(path);
            link.Type        = FLVERAssetLink.ContainerType.Mapbnd;
            link.ArchivePath = path;
            link.FlverPath   = bnd.Files[0].Name;
            flver            = FLVER.Read(bnd.Files[0].Bytes);
        }
        else
        {
            link.Type      = FLVERAssetLink.ContainerType.None;
            link.FlverPath = path;
            flver          = FLVER.Read(path);
        }

        ImportFlver(flver, link, gameType, assetName, texturePath);
    }
Exemplo n.º 8
0
        void LoadFLVER(string path, FLVER f)
        {
            ClearCurrentShit();
            FlverPath            = path;
            Flver                = f;
            CurrentMaterialIndex = -1;
            CurrentGXItemList.Clear();
            CurrentMaterial = null;
            CurrentMapList  = null;
            ListViewFlverMaterials.Items.Clear();
            int i = 0;

            foreach (var m in f.Materials)
            {
                ListViewFlverMaterials.Items.Add(new Label()
                {
                    Content = $"[{i++}] {m.Name}"
                });
            }
            TabGXItems.IsEnabled = (Flver.Header.Version >= 0x20010);
            SetIsEverythingDisabled(true);
        }
Exemplo n.º 9
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);
    }
Exemplo n.º 10
0
    static public void ImportFlver(FLVER flver, FLVERAssetLink assetLink, DarkSoulsTools.GameType gameType, string assetName, string texturePath = null, bool mapflver = false)
    {
        Material[] materials = new Material[flver.Materials.Count];
        string     gamePath  = DarkSoulsTools.GameFolder(gameType);

        if (!AssetDatabase.IsValidFolder(assetName))
        {
            AssetDatabase.CreateFolder(Path.GetDirectoryName(assetName + ".blah"), Path.GetFileNameWithoutExtension(assetName + ".blah"));
        }

        Shader shader     = AssetDatabase.LoadAssetAtPath <Shader>("Assets/dstools/Shaders/FLVERShader.shadergraph");
        Shader shaderObj  = AssetDatabase.LoadAssetAtPath <Shader>("Assets/dstools/Shaders/ObjFLVERShader.shadergraph");
        Shader shaderDiff = AssetDatabase.LoadAssetAtPath <Shader>("Assets/dstools/Shaders/FLVERShaderDiffuse.shadergraph");
        var    t          = 0;

        foreach (var m in flver.Materials)
        {
            //string name = m.Name;
            //if (name == null || name == "")
            //{
            string name = Path.GetFileNameWithoutExtension(assetName) + $@"_{t}";
            //}
            //bool normalquery = (m.Textures.Where(x => ((x.Type.ToUpper() == "G_BUMPMAPTEXTURE") || (x.Type.ToUpper() == "G_BUMPMAP"))).Count() >= 1);
            bool normalquery = false;

            Texture2D albedo       = null;
            Texture2D specular     = null;
            Texture2D normal       = null;
            bool      IsMapTexture = mapflver;
            var       MTD          = AssetDatabase.LoadAssetAtPath <MTDAssetLink>($@"Assets/{gamePath}/MTD/{Path.GetFileNameWithoutExtension(m.MTD)}.asset");
            if (texturePath != null)
            {
                foreach (var matParam in m.Textures)
                {
                    var paramNameCheck = matParam.Type.ToUpper();
                    if (paramNameCheck == "G_DIFFUSETEXTURE" || paramNameCheck == "G_DIFFUSE" || paramNameCheck.Contains("ALBEDO"))
                    {
                        var texPath = matParam.Path;
                        if (texPath == "")
                        {
                            texPath = MTD.Textures.Find(x => (x.Name == matParam.Type)).TexturePath;
                            if (texPath == "")
                            {
                                continue;
                            }
                        }
                        if (albedo == null)
                        {
                            albedo = AssetDatabase.LoadAssetAtPath <Texture2D>($@"{texturePath}/{Path.GetFileNameWithoutExtension(texPath)}.dds");
                            if (albedo == null)
                            {
                                albedo = FindTexture(texPath, gameType);
                            }
                        }
                    }
                    if (paramNameCheck == "G_SPECULARTEXTURE" || paramNameCheck == "G_SPECULAR")
                    {
                        specular = AssetDatabase.LoadAssetAtPath <Texture2D>($@"{texturePath}/{Path.GetFileNameWithoutExtension(matParam.Path)}.dds");
                        if (specular == null)
                        {
                            specular = FindTexture(matParam.Path, gameType);
                        }
                    }
                    if (paramNameCheck == "G_BUMPMAPTEXTURE" || paramNameCheck == "G_BUMPMAP" || paramNameCheck.Contains("NORMAL"))
                    {
                        var texPath = matParam.Path;
                        if (texPath == "")
                        {
                            texPath = MTD.Textures.Find(x => (x.Name == matParam.Type)).TexturePath;
                            if (texPath == "")
                            {
                                continue;
                            }
                        }
                        if (normal == null)
                        {
                            normal = AssetDatabase.LoadAssetAtPath <Texture2D>($@"{texturePath}/{Path.GetFileNameWithoutExtension(texPath)}.dds");
                            if (normal == null)
                            {
                                normal = FindTexture(texPath, gameType);
                            }
                        }
                        normalquery = true;
                    }
                }
            }
            Material mat;

            /*if (IsMapTexture && specular != null)
             * {
             *  mat = new Material(shader);
             *  mat.SetTexture("_Albedo", albedo);
             *  mat.SetTexture("_Specular", specular);
             *  mat.SetTexture("_Normal", normal);
             * }
             * else */
            if (!normalquery)
            {
                mat = new Material(shaderDiff);
                mat.SetTexture("_MainTex", albedo);
            }
            else
            {
                mat = new Material(shaderObj);
                mat.SetTexture("_MainTex", albedo);
                mat.SetTexture("_Specular", specular);
                mat.SetTexture("_BumpMap", normal);
            }
            mat.name     = name;
            materials[t] = mat;
            t++;
            AssetDatabase.CreateAsset(mat, assetName + "/" + name + ".mat");
        }

        GameObject root      = new GameObject(Path.GetFileNameWithoutExtension(assetName));
        GameObject meshesObj = new GameObject("Meshes");
        GameObject bonesObj  = new GameObject("Bones");

        meshesObj.transform.parent = root.transform;
        bonesObj.transform.parent  = root.transform;

        // import the skeleton
        Transform[] bones     = new Transform[flver.Bones.Count];
        Matrix4x4[] bindPoses = new Matrix4x4[flver.Bones.Count];
        for (int i = 0; i < flver.Bones.Count; i++)
        {
            var fbone = flver.Bones[i];
            bones[i] = new GameObject(fbone.Name).transform;
            EulerToTransform(new Vector3(fbone.Rotation.X, fbone.Rotation.Y, fbone.Rotation.Z), bones[i]);
            bones[i].localPosition = new Vector3(fbone.Translation.X, fbone.Translation.Y, fbone.Translation.Z);
            bones[i].localScale    = new Vector3(fbone.Scale.X, fbone.Scale.Y, fbone.Scale.Z);
            //SetBoneWorldTransform(bones[i], flver.Bones.ToArray(), i);
            //bindPoses[i] = bones[i].worldToLocalMatrix * root.transform.localToWorldMatrix;
        }

        // Skeleton parenting
        for (int i = 0; i < flver.Bones.Count; i++)
        {
            var fbone = flver.Bones[i];
            if (fbone.ParentIndex == -1)
            {
                //bones[i].parent = root.transform;
                bones[i].SetParent(bonesObj.transform, false);
                bindPoses[i] = bones[i].worldToLocalMatrix * root.transform.localToWorldMatrix;
            }
            else
            {
                //bones[i].parent = bones[fbone.ParentIndex];
                bones[i].SetParent(bones[fbone.ParentIndex], false);
                bindPoses[i] = bones[i].worldToLocalMatrix * root.transform.localToWorldMatrix;
            }
        }

        // Import the meshes
        int index = 0;

        foreach (var m in flver.Meshes)
        {
            var mesh = new Mesh();

            var              verts        = new List <Vector3>();
            var              normals      = new List <Vector3>();
            var              tangents     = new List <Vector4>();
            var              boneweights  = new List <BoneWeight>();
            var              smcount      = 0;
            bool             usestangents = false;
            int              uvcount      = m.Vertices[0].UVs.Count;
            List <Vector2>[] uvs          = new List <Vector2> [uvcount];
            List <Material>  matList      = new List <Material>();

            // Add the mesh to the asset link
            FLVERAssetLink.SubmeshInfo info = new FLVERAssetLink.SubmeshInfo();
            info.Name = flver.Materials[m.MaterialIndex].Name;
            var MTD = AssetDatabase.LoadAssetAtPath <MTDAssetLink>($@"Assets/{gamePath}/MTD/{Path.GetFileNameWithoutExtension(flver.Materials[m.MaterialIndex].MTD)}.asset");
            info.Mtd = MTD;
            assetLink.Submeshes.Add(info);

            int lightmapUVIndex = 1;
            // Use MTD to get lightmap uv index
            if (gameType != DarkSoulsTools.GameType.Sekiro)
            {
                if (MTD != null)
                {
                    lightmapUVIndex = (MTD.LightmapUVIndex != -1) ? MTD.LightmapUVIndex : 1;
                    if (lightmapUVIndex >= uvs.Length)
                    {
                        lightmapUVIndex = 1;
                    }
                }
                else
                {
                    // Do a hardcoded lookup of a material's lightmap UV index from a shitty table :fatcat:
                    if (MaterialLightmapUVIndex.ContainsKey(Path.GetFileNameWithoutExtension(flver.Materials[m.MaterialIndex].MTD)))
                    {
                        lightmapUVIndex = MaterialLightmapUVIndex[Path.GetFileNameWithoutExtension(flver.Materials[m.MaterialIndex].MTD)];
                    }
                }
            }
            for (int i = 0; i < uvs.Length; i++)
            {
                uvs[i] = new List <Vector2>();
            }
            bool isSkinned = false;
            foreach (var v in m.Vertices)
            {
                verts.Add(new Vector3(v.Positions[0].X, v.Positions[0].Y, v.Positions[0].Z));
                normals.Add(new Vector3(v.Normals[0].X, v.Normals[0].Y, v.Normals[0].Z));
                if (v.Tangents.Count > 0)
                {
                    tangents.Add(new Vector4(v.Tangents[0].X, v.Tangents[0].Y, v.Tangents[0].Z, v.Tangents[0].W));
                    usestangents = true;
                }
                else
                {
                    tangents.Add(new Vector4(0, 0, 0, 1));
                }
                for (int i = 0; i < uvs.Length; i++)
                {
                    // Swap lightmap uvs with uv index 1 because lmao unity
                    if (i == 1)
                    {
                        uvs[i].Add(new Vector2(v.UVs[lightmapUVIndex].X, 1.0f - v.UVs[lightmapUVIndex].Y));
                    }
                    else if (i == lightmapUVIndex)
                    {
                        uvs[i].Add(new Vector2(v.UVs[1].X, 1.0f - v.UVs[1].Y));
                    }
                    else
                    {
                        uvs[i].Add(new Vector2(v.UVs[i].X, 1.0f - v.UVs[i].Y));
                    }
                }
                if (v.BoneWeights != null && v.BoneWeights.Count() > 0)
                {
                    isSkinned = true;
                    var weight = new BoneWeight();

                    if (m.Unk1 == 0)
                    {
                        weight.boneIndex0 = v.BoneIndices[0];
                        weight.boneIndex1 = v.BoneIndices[1];
                        weight.boneIndex2 = v.BoneIndices[2];
                        weight.boneIndex3 = v.BoneIndices[3];
                    }
                    else
                    {
                        weight.boneIndex0 = m.BoneIndices[v.BoneIndices[0]];
                        weight.boneIndex1 = m.BoneIndices[v.BoneIndices[1]];
                        weight.boneIndex2 = m.BoneIndices[v.BoneIndices[2]];
                        weight.boneIndex3 = m.BoneIndices[v.BoneIndices[3]];
                    }
                    if (v.BoneWeights[0] < 0.0)
                    {
                        weight.weight0 = 1.0f;
                    }
                    else
                    {
                        weight.weight0 = v.BoneWeights[0];
                    }
                    weight.weight1 = v.BoneWeights[1];
                    weight.weight2 = v.BoneWeights[2];
                    weight.weight3 = v.BoneWeights[3];
                    boneweights.Add(weight);
                }
                else
                {
                    boneweights.Add(new BoneWeight());
                }
            }
            foreach (var fs in m.FaceSets)
            {
                if (fs.Vertices.Count() > 0 && fs.Flags == FLVER.FaceSet.FSFlags.None)
                {
                    matList.Add(materials[m.MaterialIndex]);
                    smcount++;
                }
            }

            mesh.indexFormat  = UnityEngine.Rendering.IndexFormat.UInt32;
            mesh.subMeshCount = smcount;
            mesh.SetVertices(verts);
            mesh.SetNormals(normals);
            if (usestangents)
            {
                mesh.SetTangents(tangents);
            }
            if (isSkinned)
            {
                mesh.boneWeights = boneweights.ToArray();
                mesh.bindposes   = bindPoses;
            }

            for (int i = 0; i < uvs.Length; i++)
            {
                mesh.SetUVs(i, uvs[i]);
            }

            var submesh = 0;
            foreach (var fs in m.FaceSets)
            {
                if (fs.Vertices.Count() == 0)
                {
                    continue;
                }
                if (fs.Flags != FLVER.FaceSet.FSFlags.None)
                {
                    continue;
                }

                mesh.SetTriangles(fs.GetFacesArray(), submesh, true, 0);
                submesh++;
            }
            mesh.RecalculateBounds();

            // Setup a game object asset
            GameObject obj = new GameObject(Path.GetFileNameWithoutExtension(assetName) + $@"_{index}");
            if (isSkinned)
            {
                obj.AddComponent <SkinnedMeshRenderer>();
                obj.GetComponent <SkinnedMeshRenderer>().materials  = matList.ToArray();
                obj.GetComponent <SkinnedMeshRenderer>().bones      = bones;
                obj.GetComponent <SkinnedMeshRenderer>().sharedMesh = mesh;
            }
            else
            {
                obj.AddComponent <MeshRenderer>();
                obj.GetComponent <MeshRenderer>().materials = matList.ToArray();
                obj.AddComponent <MeshFilter>();
                obj.GetComponent <MeshFilter>().mesh = mesh;
            }
            obj.AddComponent <FlverSubmesh>();
            obj.GetComponent <FlverSubmesh>().Link       = assetLink;
            obj.GetComponent <FlverSubmesh>().SubmeshIdx = index;
            obj.transform.parent = meshesObj.transform;

            AssetDatabase.CreateAsset(mesh, assetName + $@"/{Path.GetFileNameWithoutExtension(assetName)}_{index}.mesh");
            index++;
        }

        // If there's no meshes, create an empty one to bind the skeleton to so that Maya works
        // when you export the skeleton (like with c0000).
        if (flver.Meshes.Count == 0)
        {
            var mesh = new Mesh();

            var verts       = new List <Vector3>();
            var normals     = new List <Vector3>();
            var tangents    = new List <Vector4>();
            var boneweights = new List <BoneWeight>();
            for (var i = 0; i < 3; i++)
            {
                verts.Add(new Vector3(0.0f, 0.0f, 0.0f));
                normals.Add(new Vector3(0.0f, 1.0f, 0.0f));
                tangents.Add(new Vector4(1.0f, 0.0f, 0.0f, 1.0f));
                var weight = new BoneWeight();
                weight.boneIndex0 = 0;
                weight.weight0    = 1.0f;
                boneweights.Add(weight);
            }

            mesh.indexFormat  = UnityEngine.Rendering.IndexFormat.UInt32;
            mesh.subMeshCount = 1;
            mesh.SetVertices(verts);
            mesh.SetNormals(normals);
            mesh.SetTangents(tangents);
            mesh.boneWeights = boneweights.ToArray();
            mesh.bindposes   = bindPoses;
            mesh.SetTriangles(new int [] { 0, 1, 2 }, 0);

            GameObject obj = new GameObject(Path.GetFileNameWithoutExtension(assetName) + $@"_{index}");
            obj.AddComponent <SkinnedMeshRenderer>();
            obj.GetComponent <SkinnedMeshRenderer>().bones      = bones;
            obj.GetComponent <SkinnedMeshRenderer>().sharedMesh = mesh;
            obj.transform.parent = meshesObj.transform;

            AssetDatabase.CreateAsset(mesh, assetName + $@"/{Path.GetFileNameWithoutExtension(assetName)}_{index}.mesh");
        }

        root.AddComponent <FlverMesh>();
        root.GetComponent <FlverMesh>().Link = assetLink;

        AssetDatabase.CreateAsset(assetLink, assetName + ".asset");
        AssetDatabase.SaveAssets();
        PrefabUtility.SaveAsPrefabAsset(root, assetName + ".prefab");
        Object.DestroyImmediate(root);
    }
Exemplo n.º 11
0
        public void SolveOrientation(FLVER flver, bool solveBones)
        {
            foreach (var flverMesh in flver.Submeshes)
            {
                for (int i = 0; i < flverMesh.Vertices.Count; i++)
                {
                    var m = Matrix.Identity
                            * Matrix.CreateRotationY(Importer.SceneRotation.Y)
                            * Matrix.CreateRotationZ(Importer.SceneRotation.Z)
                            * Matrix.CreateRotationX(Importer.SceneRotation.X)
                    ;

                    flverMesh.Vertices[i].Position = Vector3.Transform(flverMesh.Vertices[i].Position, m);
                    flverMesh.Vertices[i].Normal   = Vector3.Normalize(Vector3.Transform((Vector3)flverMesh.Vertices[i].Normal, m));
                    var rotBitangentVec3 = Vector3.Transform((Vector3)flverMesh.Vertices[i].BiTangent, m);
                    flverMesh.Vertices[i].BiTangent = new Vector4(rotBitangentVec3.X, rotBitangentVec3.Y, rotBitangentVec3.Z, flverMesh.Vertices[i].BiTangent.W);
                }
            }

            //Matrix GetBoneMatrix(FlverBone b)
            //{
            //    return Matrix.CreateScale(b.Scale)
            //    * Matrix.CreateRotationX(b.EulerRadian.X)
            //    * Matrix.CreateRotationZ(b.EulerRadian.Z)
            //    * Matrix.CreateRotationY(b.EulerRadian.Y)
            //    * Matrix.CreateTranslation(b.Translation)
            //    ;
            //}

            //void ApplyBoneMatrix(FlverBone b, Matrix m)
            //{
            //    Matrix orig = GetBoneMatrix(b);
            //    orig *= m;

            //    b.Translation = orig.Translation;
            //    b.Scale = orig.Scale;
            //    b.EulerRadian = Util.GetFlverEulerFromQuaternion(orig.Rotation);
            //}
            //bool anyAdjusted = false;
            //do
            //{
            //anyAdjusted = false;

            //foreach (var b in flver.Bones)
            //{
            //    b.EulerRadian = Vector3.Zero;
            //    //if (b.ParentIndex == -1)
            //    //{
            //    //    b.EulerRadian = Vector3.Zero;
            //    //    //b.Scale = Vector3.One;
            //    //    //b.Translation = Vector3.Zero;
            //    //}
            //}


            //ACTUALY WORKS:

            if (solveBones)
            {
                for (int b = 0; b < flver.Bones.Count; b++)
                {
                    //flver.Bones[b].Scale = Vector3.One;


                    //if (flver.Bones[b].Scale.X < 0)
                    //{
                    //    flver.Bones[b].Scale.X *= -1;
                    //    flver.Bones[b].EulerRadian.Y += MathHelper.Pi;

                    //    foreach (var dmy in flver.Dummies.Where(dm => dm.ParentBoneIndex == b))
                    //    {
                    //        dmy.Position *= new Vector3(-1, 1, 1);
                    //    }
                    //}

                    //if (flver.Bones[b].Scale.Y < 0)
                    //{
                    //    flver.Bones[b].Scale.Y *= -1;
                    //    flver.Bones[b].EulerRadian.X += MathHelper.Pi;

                    //    foreach (var dmy in flver.Dummies.Where(dm => dm.ParentBoneIndex == b))
                    //    {
                    //        dmy.Position *= new Vector3(1, -1, 1);
                    //    }
                    //}

                    //Do this only for parent bones, cuz child bones could be real bones like on a whip...?
                    //if (Importer.OutputType == DSFBXOutputType.Weapon && flver.Bones[b].ParentIndex == -1)
                    //{
                    //    var oldBoneRotMatrix = Matrix.CreateRotationY(flver.Bones[b].EulerRadian.Y)
                    //        * Matrix.CreateRotationZ(flver.Bones[b].EulerRadian.Z)
                    //        * Matrix.CreateRotationX(flver.Bones[b].EulerRadian.X);
                    //    foreach (var dmy in flver.Dummies.Where(d => d.ParentBoneIndex == b))
                    //    {
                    //        dmy.Position = Vector3.Transform(dmy.Position, Matrix.Invert(oldBoneRotMatrix) * Matrix.CreateRotationX(MathHelper.Pi));
                    //    }
                    //    flver.Bones[b].EulerRadian = Vector3.Zero;
                    //    flver.Bones[b].Scale = Vector3.One;
                    //}
                }
            }


            if (Importer.RotateNormalsBackward || Importer.ConvertNormalsAxis)
            {
                foreach (var sm in flver.Submeshes)
                {
                    foreach (var vert in sm.Vertices)
                    {
                        if (vert.Normal != null)
                        {
                            if (Importer.ConvertNormalsAxis)
                            {
                                var x = vert.Normal.X;
                                var y = vert.Normal.Y;
                                var z = vert.Normal.Z;

                                vert.Normal = new Vector3(x, -z, y);
                            }

                            if (Importer.RotateNormalsBackward)
                            {
                                vert.Normal = Vector3.Transform((Vector3)vert.Normal, Matrix.CreateRotationY(MathHelper.Pi));
                            }
                        }
                    }
                }
            }



            //foreach (var m in flver.Submeshes)
            //{
            //    foreach (var v in m.Vertices)
            //    {
            //        var norm = (Vector3)v.Normal;
            //        var tan = (Vector3)v.BiTangent;

            //        v.BiTangent = new Vector4(Vector3.Cross(norm, tan) * v.BiTangent.W, v.BiTangent.W);
            //    }
            //}


            //}
            //while (anyAdjusted);



            //if (solveBones)
            //{
            //    foreach (var bone in flver.Bones.Where(b => b.ParentIndex == -1))
            //    {
            //        var origMatrix = Matrix.CreateTranslation(bone.Translation)
            //            * Matrix.CreateScale(bone.Scale);

            //        var m = Matrix.CreateRotationZ(-MathHelper.PiOver2)
            //            //* Matrix.CreateRotationX(MathHelper.Pi)
            //            ;

            //        if ((origMatrix * m).Decompose(out var scale, out _, out var trans))
            //        {
            //            bone.Translation = trans;
            //            bone.Scale = scale;
            //        }

            //        bone.EulerRadian.Z += -MathHelper.PiOver2;
            //        //bone.EulerRadian.X += MathHelper.Pi;

            //    }
            //}

            foreach (var dmy in flver.Dummies)
            {
                var  m = Matrix.Identity;
                bool wasAnyRotationAppliedFatcat = false;
                if (Importer.SceneRotation.Y != 0)
                {
                    m *= Matrix.CreateRotationY(Importer.SceneRotation.Y);
                    wasAnyRotationAppliedFatcat = true;
                }
                if (Importer.SceneRotation.Z != 0)
                {
                    m *= Matrix.CreateRotationZ(Importer.SceneRotation.Z);
                    wasAnyRotationAppliedFatcat = true;
                }
                if (Importer.SceneRotation.X != 0)
                {
                    m *= Matrix.CreateRotationX(Importer.SceneRotation.X);
                    wasAnyRotationAppliedFatcat = true;
                }

                if (wasAnyRotationAppliedFatcat)
                {
                    dmy.Position = Vector3.Transform(dmy.Position, m);
                }
            }
        }
Exemplo n.º 12
0
        public int SolveBone(FLVER flver,
                             NodeContent fbx,
                             NodeContent boneContent,
                             int parentIndex)
        {
            var newBone = new FlverBone(flver);

            newBone.Name = boneContent.Name;

            //if (parentIndex == -1 && (boneContent.Name.ToUpper().StartsWith("DUMMY") || boneContent.Name.ToUpper().StartsWith("DYMMY")))
            //{
            //    newBone.Name = "dymmy";
            //}
            //else if (parentIndex == -1 && boneContent.Name.ToUpper().StartsWith("SFX"))
            //{
            //    newBone.Name = "SFX用";
            //}

            FbxPipeline.Matrix boneTrans_Xna = boneContent.Transform;// * FbxPipeline.Matrix.CreateScale(Importer.FinalScaleMultiplier);

            //boneTrans_Xna *= FbxPipeline.Matrix.CreateRotationZ(-MathHelper.PiOver2);
            //boneTrans_Xna *= FbxPipeline.Matrix.CreateRotationY(-MathHelper.PiOver2);

            //boneTrans_Xna *= FbxPipeline.Matrix.CreateRotationY(MathHelper.Pi);

            //if (boneContent.Parent != null && boneContent.Parent != fbx)
            //{
            //    boneTrans_Xna *= FbxPipeline.Matrix.Invert(boneContent.Parent.AbsoluteTransform);
            //    //boneTrans_Xna *= FbxPipeline.Matrix.CreateRotationZ(MathHelper.Pi);
            //}

            string parentName     = boneContent.Parent?.Name;
            bool   isMainRootBone = (parentName == null || parentName == "RootNode");

            //bool isRegularChildBone = false;

            //var parentLevel1 = boneContent.Parent;

            //if (parentLevel1 != null)
            //{
            //    var parentLevel2 = parentLevel1.Parent;

            //    if (parentLevel2 != null)
            //    {
            //        if (parentLevel2.Name.Trim().ToUpper() == "ROOT")
            //        {
            //            //boneTrans_Xna *= FbxPipeline.Matrix.Invert(boneContent.Parent.AbsoluteTransform);
            //            //boneTrans_Xna = boneContent.AbsoluteTransform;

            //            //boneTrans_Xna *= FbxPipeline.Matrix.CreateRotationX(MathHelper.PiOver2);

            //            //boneTrans_Xna *= FbxPipeline.Matrix.CreateRotationY(MathHelper.PiOver2);
            //            //boneTrans_Xna *= FbxPipeline.Matrix.CreateRotationZ(MathHelper.PiOver2);
            //            //boneTrans_Xna *= FbxPipeline.Matrix.CreateRotationX(MathHelper.PiOver2);
            //            //boneTrans_Xna *= FbxPipeline.Matrix.CreateRotationZ(MathHelper.PiOver2);

            //            isRegularChildBone = true;
            //            //boneTrans_Xna *= FbxPipeline.Matrix.CreateRotationX(-MathHelper.PiOver4);
            //        }
            //    }


            //}

            //if (isMainRootBone)
            //{
            //    boneTrans_Xna = boneContent.AbsoluteTransform;
            //}

            //if (isRegularChildBone)
            //{
            //    boneTrans_Xna = boneContent.AbsoluteTransform;
            //}
            //else if (isMainRootBone || boneContent.Name.ToUpper() == "ROOT")
            //{
            //    //boneTrans_Xna = FbxPipeline.Matrix.Identity;
            //}



            //if (boneContent.Name.ToUpper() == "ROOT" || isMainRootBone)
            //{
            //    boneTrans_Xna *= FbxPipeline.Matrix.CreateScale(1, 1, -1);
            //}

            //if (!isMainRootBone)
            //{
            //    boneTrans_Xna *= FbxPipeline.Matrix.Invert(boneContent.Parent.AbsoluteTransform);
            //}

            //boneTrans_Xna *= FbxPipeline.Matrix.Invert(boneContent.Parent.Transform);

            //Matrix boneTrans_MonoGame = new Matrix(boneTrans_Xna.M11, boneTrans_Xna.M12, boneTrans_Xna.M13, boneTrans_Xna.M14,
            //    boneTrans_Xna.M21, boneTrans_Xna.M22, boneTrans_Xna.M23, boneTrans_Xna.M24,
            //    boneTrans_Xna.M31, boneTrans_Xna.M32, boneTrans_Xna.M33, boneTrans_Xna.M34,
            //    boneTrans_Xna.M41, boneTrans_Xna.M42, boneTrans_Xna.M43, boneTrans_Xna.M44);

            //boneTrans_MonoGame *= Matrix.CreateScale(Importer.FinalScaleMultiplier);



            //bool boneScaleWarning = false;

            //newBone.Scale = boneTrans_MonoGame.Scale;// / Importer.FinalScaleMultiplier;

            //if (isMainRootBone)
            //{
            //    newBone.Scale.Y *= -1;
            //}

            //newBone.Scale = new FlverVector3(Math.Abs(newBone.Scale.X), Math.Abs(newBone.Scale.Y), Math.Abs(newBone.Scale.Z));

            //Quaternion q = Quaternion.CreateFromRotationMatrix(boneTrans_MonoGame);

            //boneTrans_Xna *= FbxPipeline.Matrix.CreateRotationY(MathHelper.Pi);

            if (boneTrans_Xna.Decompose(out FbxPipeline.Vector3 scale, out FbxPipeline.Quaternion rotation, out FbxPipeline.Vector3 translation))
            {
                newBone.Scale       = new Vector3(scale.X, scale.Y, scale.Z);
                newBone.EulerRadian = Util.GetFlverEulerFromQuaternion_Bone(new Quaternion(-rotation.X, rotation.Y, rotation.Z, -rotation.W)) * new Vector3(1, 1, 1);

                //newBone.EulerRadian.X = MathHelper.WrapAngle(newBone.EulerRadian.X + MathHelper.Pi);

                newBone.Translation = new Vector3(-translation.X, translation.Y, translation.Z) * Importer.FinalScaleMultiplier;
            }
            else
            {
                throw new Exception("FBX Bone Content Transform Matrix " +
                                    "-> Decompose(out Vector3 scale, " +
                                    "out Quaternion rotation, out Vector3 translation) " +
                                    ">>FAILED<<");
            }


            newBone.BoundingBoxMax = Vector3.One * 0.1f;
            newBone.BoundingBoxMin = Vector3.One * -0.1f;

            //var extractedBoneEuler = Util.GetFlverEulerFromQuaternion_Bone(boneTrans_MonoGame.Rotation);

            //newBone.EulerRadian.X = MathHelper.WrapAngle(extractedBoneEuler.X + 0);
            //newBone.EulerRadian.Y = MathHelper.WrapAngle(extractedBoneEuler.Y + 0);
            //newBone.EulerRadian.Z = MathHelper.WrapAngle(extractedBoneEuler.Z + 0);

            //newBone.EulerRadian = new Vector3(newBone.EulerRadian.X, newBone.EulerRadian.Z, newBone.EulerRadian.Y);

            //var extractedBoneTrans = boneTrans_MonoGame.Translation * Importer.FinalScaleMultiplier;

            //newBone.Translation = new Vector3(extractedBoneTrans.X, extractedBoneTrans.Y, extractedBoneTrans.Z);

            //if (boneContent.Name.ToUpper() == "MASTER")
            //{
            //    //newBone.Translation *= new Vector3(1, -1, 1);
            //    //newBone.EulerRadian.X = MathHelper.WrapAngle(newBone.EulerRadian.X + MathHelper.PiOver2);
            //    //newBone.EulerRadian.Y = MathHelper.WrapAngle(newBone.EulerRadian.Y + MathHelper.PiOver2);
            //    //newBone.EulerRadian.Z = MathHelper.WrapAngle(newBone.EulerRadian.Z + MathHelper.PiOver2);
            //}
            //else
            //{

            //}

            //if (boneContent.Parent != null)
            //{
            //    newBone.Translation *= new Vector3(1, -1, 1);
            //}

            //newBone.Translation *= new Vector3(-1, 1, 1);

            //if (newBone.Scale.X < 0)
            //{
            //    newBone.Scale *= new Vector3(-1, 1, 1);
            //    //newBone.EulerRadian *= new Vector3(1, -1, 1);
            //    //newBone.Translation *= new Vector3(1, -1, -1);
            //}



            //newBone.EulerRadian = Util.GetEuler(boneTrans);

            //newBone.EulerRadian.Y -= MathHelper.PiOver2;

            if (newBone.Name.ToUpper().StartsWith("DUMMY") && newBone.Name.Contains("<") && newBone.Name.Contains(">"))
            {
                var dmy = new FlverDummy(flver);
                dmy.ParentBoneIndex = (short)parentIndex;

                //var dmyParentEuler = Util.GetEuler(boneContent.Parent.Transform);

                var parentBoneTrans = boneContent.Parent.AbsoluteTransform;

                Matrix parentBoneTrans_MonoGame = new Matrix(parentBoneTrans.M11, parentBoneTrans.M12, parentBoneTrans.M13, parentBoneTrans.M14,
                                                             parentBoneTrans.M21, parentBoneTrans.M22, parentBoneTrans.M23, parentBoneTrans.M24,
                                                             parentBoneTrans.M31, parentBoneTrans.M32, parentBoneTrans.M33, parentBoneTrans.M34,
                                                             parentBoneTrans.M41, parentBoneTrans.M42, parentBoneTrans.M43, parentBoneTrans.M44);

                dmy.Position = Vector3.Transform(new Vector3(-boneContent.Transform.Translation.X,
                                                             boneContent.Transform.Translation.Y,
                                                             boneContent.Transform.Translation.Z)/*,
                                                                                                  *
                                                                                                  * //Matrix.CreateRotationY(dmyParentEuler.Y)
                                                                                                  * //* Matrix.CreateRotationZ(dmyParentEuler.Z)
                                                                                                  * //* Matrix.CreateRotationX(dmyParentEuler.X)
                                                                                                  *
                                                                                                  * )*/

                                                 * Importer.FinalScaleMultiplier
                                                 ,
                                                 //Matrix.Invert(Matrix.CreateScale(parentBoneTrans_MonoGame.Scale.X, parentBoneTrans_MonoGame.Scale.Y, parentBoneTrans_MonoGame.Scale.Z))
                                                 Matrix.Identity
                                                 );
                var thisScale = new FbxPipeline.Vector3(newBone.Scale.X, newBone.Scale.Y, newBone.Scale.Z);

                var upPoint = FbxPipeline.Vector3.Normalize(boneContent.AbsoluteTransform.Forward) * 0.1f * thisScale;

                var forwardPoint = FbxPipeline.Vector3.Normalize(boneContent.AbsoluteTransform.Up) * 0.05f * thisScale;

                dmy.Row2 = new Vector3(upPoint.X, upPoint.Y, upPoint.Z);
                dmy.Row3 = new Vector3(forwardPoint.X, forwardPoint.Y, forwardPoint.Z);
                var dmyTypeID = int.Parse(Util.GetAngleBracketContents(boneContent.Name));
                dmy.TypeID = (short)dmyTypeID;

                flver.Dummies.Add(dmy);

                foreach (var c in boneContent.Children)
                {
                    if (c is NodeContent n)
                    {
                        Importer.PrintWarning($"Non-dummy node '{n.Name}' is parented " +
                                              $"to a dummy node ('{boneContent.Name}') and will be ignored " +
                                              $"due to Dark Souls engine limitations. To include the node, " +
                                              $"parent it to something that is not a dummy node.");
                    }
                }


                return(-1);
            }
            //else if ((newBone.Name.StartsWith("[") && newBone.Name.EndsWith("]")))
            //{
            //    newBone.Name = newBone.Name.Substring(1, newBone.Name.Length - 2);
            //    newBone.IsNub = true;
            //}
            else if (newBone.Name.ToUpper().EndsWith("NUB"))
            {
                newBone.IsNub = true;
            }

            //float transX = boneContent.Transform.Translation.X;
            //float transY = boneContent.Transform.Translation.Y;
            //float transZ = boneContent.Transform.Translation.Z;

            //if (boneScaleWarning)
            //{
            //    Importer.PrintWarning($"Bone '{boneContent.Name}' has a scale of <{scale.X}, {scale.Y}, {scale.Z}>. " +
            //            $"Any scale different than <1.0, 1.0, 1.0> might cause the game to " +
            //            $"try to \"correct\" the scale and break something.");
            //}

            newBone.ParentIndex = (short)parentIndex;

            flver.Bones.Add(newBone);

            int myIndex = flver.Bones.Count - 1;

            var myChildrenIndices = new List <int>();

            foreach (var childNode in boneContent.Children)
            {
                if (childNode is NodeContent childBone)
                {
                    myChildrenIndices.Add(SolveBone(flver, fbx, childBone, myIndex));
                }
            }

            if (myChildrenIndices.Count > 0)
            {
                newBone.FirstChildIndex = (short)myChildrenIndices[0];

                for (int i = 0; i < myChildrenIndices.Count; i++)
                {
                    if (myChildrenIndices[i] > -1)
                    {
                        var currentChild = flver.Bones[myChildrenIndices[i]];

                        if (i > 0)
                        {
                            currentChild.PreviousSiblingIndex = (short)myChildrenIndices[i - 1];
                        }
                        else
                        {
                            currentChild.PreviousSiblingIndex = (short)-1;
                        }

                        if (i < myChildrenIndices.Count - 1)
                        {
                            currentChild.NextSiblingIndex = (short)myChildrenIndices[i + 1];
                        }
                        else
                        {
                            currentChild.NextSiblingIndex = (short)-1;
                        }
                    }
                }
            }


            return(myIndex);
        }
        public FlverSubmeshRenderer(Model parent, FLVER flvr, FLVER.Mesh mesh)
        {
            Parent = parent;

            var shortMaterialName = MiscUtil.GetFileNameWithoutDirectoryOrExtension(flvr.Materials[mesh.MaterialIndex].MTD);

            if (shortMaterialName.EndsWith("_Alp") ||
                shortMaterialName.Contains("_Edge") ||
                shortMaterialName.Contains("_Decal") ||
                shortMaterialName.Contains("_Cloth") ||
                shortMaterialName.Contains("_al") ||
                shortMaterialName.Contains("BlendOpacity"))
            {
                DrawStep = GFXDrawStep.AlphaEdge;
            }
            else
            {
                DrawStep = GFXDrawStep.Opaque;
            }

            bool hasLightmap = false;

            foreach (var matParam in flvr.Materials[mesh.MaterialIndex].Textures)
            {
                var paramNameCheck = matParam.Type.ToUpper();
                // DS3/BB
                if (paramNameCheck == "G_DIFFUSETEXTURE")
                {
                    TexNameDiffuse = matParam.Path;
                }
                else if (paramNameCheck == "G_SPECULARTEXTURE")
                {
                    TexNameSpecular = matParam.Path;
                }
                else if (paramNameCheck == "G_BUMPMAPTEXTURE")
                {
                    TexNameNormal = matParam.Path;
                }
                else if (paramNameCheck == "G_DOLTEXTURE1")
                {
                    TexNameDOL1 = matParam.Path;
                    hasLightmap = true;
                }
                else if (paramNameCheck == "G_DOLTEXTURE2")
                {
                    TexNameDOL2 = matParam.Path;
                }
                // DS1 params
                else if (paramNameCheck == "G_DIFFUSE")
                {
                    TexNameDiffuse = matParam.Path;
                }
                else if (paramNameCheck == "G_SPECULAR")
                {
                    TexNameSpecular = matParam.Path;
                }
                else if (paramNameCheck == "G_BUMPMAP")
                {
                    TexNameNormal = matParam.Path;
                }
                else if (paramNameCheck == "G_LIGHTMAP")
                {
                    TexNameDOL1 = matParam.Path;
                    hasLightmap = true;
                }
                // Alternate material params that work as diffuse
            }

            // MTD lookup
            MTD mtd = InterrootLoader.GetMTD(flvr.Materials[mesh.MaterialIndex].MTD);

            var MeshVertices = new VertexPositionColorNormalTangentTexture[mesh.Vertices.Count];

            for (int i = 0; i < mesh.Vertices.Count; i++)
            {
                var vert = mesh.Vertices[i];
                MeshVertices[i] = new VertexPositionColorNormalTangentTexture();

                MeshVertices[i].Position = new Vector3(vert.Position.X, vert.Position.Y, vert.Position.Z);

                if (vert.Normal != null && vert.Tangents != null && vert.Tangents.Count > 0)
                {
                    MeshVertices[i].Normal   = Vector3.Normalize(new Vector3(vert.Normal.X, vert.Normal.Y, vert.Normal.Z));
                    MeshVertices[i].Tangent  = Vector3.Normalize(new Vector3(vert.Tangents[0].X, vert.Tangents[0].Y, vert.Tangents[0].Z));
                    MeshVertices[i].Binormal = Vector3.Cross(Vector3.Normalize(MeshVertices[i].Normal), Vector3.Normalize(MeshVertices[i].Tangent)) * vert.Tangents[0].W;
                }

                if (vert.UVs.Count > 0)
                {
                    MeshVertices[i].TextureCoordinate = new Vector2(vert.UVs[0].X, vert.UVs[0].Y);
                    if (vert.UVs.Count > 1 && hasLightmap)
                    {
                        if (mtd == null)
                        {
                            // Really stupid heuristic to determine light map UVs without reading mtd files or something
                            if (vert.UVs.Count > 2 && flvr.Materials[mesh.MaterialIndex].Textures.Count > 11)
                            {
                                MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[2].X, vert.UVs[2].Y);
                            }
                            else
                            {
                                MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[1].X, vert.UVs[1].Y);
                            }
                        }
                        else
                        {
                            // Better heuristic with MTDs
                            int uvindex  = mtd.Textures.Find(tex => tex.Type.ToUpper() == "G_LIGHTMAP" || tex.Type.ToUpper() == "G_DOLTEXTURE1").UVNumber;
                            int uvoffset = 1;
                            for (int j = 1; j < uvindex; j++)
                            {
                                if (!mtd.Textures.Any(t => (t.UVNumber == j)))
                                {
                                    uvoffset++;
                                }
                            }
                            uvindex -= uvoffset;
                            if (vert.UVs.Count > uvindex)
                            {
                                MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[uvindex].X, vert.UVs[uvindex].Y);
                            }
                            else
                            {
                                MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[1].X, vert.UVs[1].Y);
                            }
                        }
                    }
                    else
                    {
                        MeshVertices[i].TextureCoordinate2 = Vector2.Zero;
                    }
                }
                else
                {
                    MeshVertices[i].TextureCoordinate  = Vector2.Zero;
                    MeshVertices[i].TextureCoordinate2 = Vector2.Zero;
                }
            }

            VertexCount = MeshVertices.Length;

            MeshFacesets = new List <FlverSubmeshRendererFaceSet>();

            foreach (var faceset in mesh.FaceSets)
            {
                bool is32bit = faceset.IndexSize == 0x20;

                var newFaceSet = new FlverSubmeshRendererFaceSet()
                {
                    BackfaceCulling = faceset.CullBackfaces,
                    IsTriangleStrip = faceset.TriangleStrip,
                    IndexBuffer     = new IndexBuffer(
                        GFX.Device,
                        is32bit ? IndexElementSize.ThirtyTwoBits : IndexElementSize.SixteenBits,
                        faceset.Vertices.Length,
                        BufferUsage.WriteOnly),
                    IndexCount = faceset.Vertices.Length,
                };

                if (faceset.Flags == FLVER.FaceSet.FSFlags.LodLevel1)
                {
                    newFaceSet.LOD = 1;
                    HasNoLODs      = false;
                }
                else if (faceset.Flags == FLVER.FaceSet.FSFlags.LodLevel2)
                {
                    newFaceSet.LOD = 2;
                    HasNoLODs      = false;
                }

                if (is32bit)
                {
                    newFaceSet.IndexBuffer.SetData(faceset.Vertices);
                }
                else
                {
                    newFaceSet.IndexBuffer.SetData(faceset.Vertices.Select(x => (ushort)x).ToArray());
                }

                MeshFacesets.Add(newFaceSet);
            }

            Bounds = BoundingBox.CreateFromPoints(MeshVertices.Select(x => x.Position));

            VertBuffer = new VertexBuffer(GFX.Device,
                                          typeof(VertexPositionColorNormalTangentTexture), MeshVertices.Length, BufferUsage.WriteOnly);
            VertBuffer.SetData(MeshVertices);

            VertBufferBinding = new VertexBufferBinding(VertBuffer, 0, 0);

            TryToLoadTextures();
        }
Exemplo n.º 14
0
        public static void ModelSwapModule()
        {
            System.Windows.Forms.OpenFileDialog openFileDialog1;
            openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
            openFileDialog1.InitialDirectory = System.IO.Directory.GetCurrentDirectory();
            openFileDialog1.Title            = "Choose template seikiro model file.";
            //openFileDialog1.ShowDialog();

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                Console.WriteLine(openFileDialog1.FileName);
                //openFileDialog1.
            }
            else
            {
                return;
            }

            FLVER b = FLVER.Read(openFileDialog1.FileName);



            System.Windows.Forms.OpenFileDialog openFileDialog2 = new System.Windows.Forms.OpenFileDialog();
            openFileDialog2.InitialDirectory = System.IO.Directory.GetCurrentDirectory();
            openFileDialog2.Title            = "Choose source DS/BB model file.";
            //openFileDialog1.ShowDialog();

            if (openFileDialog2.ShowDialog() == DialogResult.OK)
            {
                Console.WriteLine(openFileDialog2.FileName);
                //openFileDialog1.
            }
            else
            {
                return;
            }
            FLVER src = FLVER.Read(openFileDialog2.FileName);



            Console.WriteLine(b.Header);

            Console.WriteLine("Seikiro unk is:" + b.SekiroUnk);



            Console.WriteLine("Material:");
            foreach (FLVER.Material m in b.Materials)
            {
                Console.WriteLine(m.Name);
            }

            foreach (FLVER.Mesh m in b.Meshes)
            {
                Console.WriteLine("Mesh#" + m.MaterialIndex);
            }

            //* new
            //b.Header.BigEndian = src.Header.BigEndian;


            //


            //X: is not the sword axis!!!
            //Y: ++ means closer to the hand!
            //Unit: in meter(?)


            //For Moonlight sword -> threaded cane, Y+0.5f

            Form f = new Form();

            Label l = new Label();

            l.Text     = "x,y,z offset? Y= weapon length axis,Y+=Closer to hand";
            l.Size     = new System.Drawing.Size(150, 15);
            l.Location = new System.Drawing.Point(10, 20);
            f.Controls.Add(l);


            TextBox t = new TextBox();

            t.Size     = new System.Drawing.Size(70, 15);
            t.Location = new System.Drawing.Point(10, 60);
            t.Text     = "0";
            f.Controls.Add(t);



            TextBox t2 = new TextBox();

            t2.Size     = new System.Drawing.Size(70, 15);
            t2.Location = new System.Drawing.Point(10, 100);
            t2.Text     = "0";
            f.Controls.Add(t2);

            TextBox t3 = new TextBox();

            t3.Size     = new System.Drawing.Size(70, 15);
            t3.Location = new System.Drawing.Point(10, 140);
            t3.Text     = "0";
            f.Controls.Add(t3);

            CheckBox cb1 = new CheckBox();

            cb1.Size     = new System.Drawing.Size(70, 15);
            cb1.Location = new System.Drawing.Point(10, 160);
            cb1.Text     = "Copy Material";
            f.Controls.Add(cb1);

            CheckBox cb2 = new CheckBox();

            cb2.Size     = new System.Drawing.Size(150, 15);
            cb2.Location = new System.Drawing.Point(10, 180);
            cb2.Text     = "Copy Bones";
            f.Controls.Add(cb2);

            CheckBox cb3 = new CheckBox();

            cb3.Size     = new System.Drawing.Size(150, 15);
            cb3.Location = new System.Drawing.Point(10, 200);
            cb3.Text     = "Copy Dummy";
            f.Controls.Add(cb3);


            CheckBox cb4 = new CheckBox();

            cb4.Size     = new System.Drawing.Size(350, 15);
            cb4.Location = new System.Drawing.Point(10, 220);
            cb4.Text     = "All vertex weight to first bone";
            f.Controls.Add(cb4);

            f.ShowDialog();

            float x = float.Parse(t.Text);
            float y = float.Parse(t2.Text);
            float z = float.Parse(t3.Text);


            b.Meshes = src.Meshes;


            if (cb1.Checked)
            {
                b.Materials = src.Materials;
            }

            if (cb2.Checked)
            {
                b.Bones = src.Bones;
            }

            if (cb3.Checked)
            {
                b.Dummies = src.Dummies;
            }

            if (cb4.Checked)
            {
                for (int i = 0; i < b.Meshes.Count; i++)
                {
                    b.Meshes[i].BoneIndices = new List <int>();
                    b.Meshes[i].BoneIndices.Add(0);
                    b.Meshes[i].BoneIndices.Add(1);
                    b.Meshes[i].DefaultBoneIndex = 1;
                    foreach (FLVER.Vertex v in b.Meshes[i].Vertices)
                    {
                        for (int j = 0; j < v.Positions.Count; j++)
                        {
                            if (v.BoneWeights == null)
                            {
                                continue;
                            }
                            v.Positions[j] = new System.Numerics.Vector3(0, 0, 0);
                            for (int k = 0; k < v.BoneWeights.Length; k++)
                            {
                                v.BoneWeights[k] = 0;
                                v.BoneIndices[k] = 0;
                            }
                            v.BoneIndices[0] = 1;
                            v.BoneWeights[0] = 1;
                        }
                    }
                    //targetFlver.Meshes[i].Vertices = new List<FLVER.Vertex>();
                }
            }

            foreach (FLVER.Mesh m in b.Meshes)
            {
                foreach (FLVER.Vertex v in m.Vertices)
                {
                    for (int i = 0; i < v.Positions.Count; i++)
                    {
                        v.Positions[i] = new System.Numerics.Vector3(v.Positions[i].X + x, v.Positions[i].Y + y, v.Positions[i].Z + z);
                    }
                }
            }



            b.Write(openFileDialog1.FileName + "n");
            MessageBox.Show("Swap completed!", "Info");
            //Console.WriteLine("End reading");
            //Application.Exit();
        }
        /*public FlverSubmeshRenderer(FlverSubmesh f)
         * {
         *  var shortMaterialName = MiscUtil.GetFileNameWithoutDirectoryOrExtension(f.Material.MTDName);
         *  if (shortMaterialName.EndsWith("_Alp") || shortMaterialName.EndsWith("_Edge"))
         *  {
         *      DrawStep = GFXDrawStep.AlphaEdge;
         *  }
         *  else
         *  {
         *      DrawStep = GFXDrawStep.Opaque;
         *  }
         *
         *  foreach (var matParam in f.Material.Parameters)
         *  {
         *      if (matParam.Name.ToUpper() == "G_DIFFUSE")
         *          TexNameDiffuse = matParam.Value;
         *      else if (matParam.Name.ToUpper() == "G_SPECULAR")
         *          TexNameSpecular = matParam.Value;
         *      else if (matParam.Name.ToUpper() == "G_BUMPMAP")
         *          TexNameNormal = matParam.Value;
         *  }
         *
         *  var MeshVertices = new VertexPositionColorNormalTangentTexture[f.Vertices.Count];
         *  for (int i = 0; i < f.Vertices.Count; i++)
         *  {
         *      var vert = f.Vertices[i];
         *      MeshVertices[i] = new VertexPositionColorNormalTangentTexture();
         *
         *      MeshVertices[i].Position = new Vector3(vert.Position.X, vert.Position.Y, vert.Position.Z);
         *
         *      if (vert.Normal != null && vert.BiTangent != null)
         *      {
         *          MeshVertices[i].Normal = Vector3.Normalize(new Vector3(vert.Normal.X, vert.Normal.Y, vert.Normal.Z));
         *          MeshVertices[i].Tangent = Vector3.Normalize(new Vector3(vert.BiTangent.X, vert.BiTangent.Y, vert.BiTangent.Z));
         *          MeshVertices[i].Binormal = Vector3.Cross(Vector3.Normalize(MeshVertices[i].Normal), Vector3.Normalize(MeshVertices[i].Tangent)) * vert.BiTangent.W;
         *      }
         *
         *      if (vert.UVs.Count > 0)
         *      {
         *          MeshVertices[i].TextureCoordinate = vert.UVs[0];
         *      }
         *      else
         *      {
         *          MeshVertices[i].TextureCoordinate = Vector2.Zero;
         *      }
         *
         *      // We set the mesh's vertex color to that of a selected mesh.
         *      // The shader with lighting ignores this so it will only show
         *      // up on the primitive shader, which is what is used to draw
         *      // the currently highlighted map piece
         *      MeshVertices[i].Color = Main.SELECTED_MESH_COLOR.ToVector4();
         *  }
         *
         *  VertexCount = MeshVertices.Length;
         *
         *  MeshFacesets = new List<FlverSubmeshRendererFaceSet>();
         *
         *  foreach (var faceset in f.FaceSets)
         *  {
         *      var newFaceSet = new FlverSubmeshRendererFaceSet()
         *      {
         *          BackfaceCulling = faceset.CullBackfaces,
         *          IsTriangleStrip = faceset.IsTriangleStrip,
         *          IndexBuffer = new IndexBuffer(
         *                      GFX.Device,
         *                      IndexElementSize.SixteenBits,
         *                      sizeof(short) * faceset.VertexIndices.Count,
         *                      BufferUsage.None),
         *          IndexCount = faceset.VertexIndices.Count,
         *      };
         *
         *      if (faceset.FlagsLOD1)
         *      {
         *          newFaceSet.LOD = (byte)1;
         *          HasNoLODs = false;
         *      }
         *      else if (faceset.FlagsLOD2)
         *      {
         *          newFaceSet.LOD = (byte)2;
         *          HasNoLODs = false;
         *      }
         *
         *      newFaceSet.IndexBuffer.SetData(faceset.VertexIndices
         *          .Select(x =>
         *          {
         *              if (x == ushort.MaxValue)
         *                  return (short)(-1);
         *              else
         *                  return (short)x;
         *          })
         *          .ToArray());
         *      MeshFacesets.Add(newFaceSet);
         *  }
         *
         *  Bounds = BoundingBox.CreateFromPoints(MeshVertices.Select(x => x.Position));
         *
         *  VertBuffer = new VertexBuffer(GFX.Device,
         *      typeof(VertexPositionColorNormalTangentTexture), MeshVertices.Length, BufferUsage.WriteOnly);
         *  VertBuffer.SetData(MeshVertices);
         * }*/

        public FlverSubmeshRenderer(FLVER flvr, FLVER.Mesh mesh)
        {
            var shortMaterialName = MiscUtil.GetFileNameWithoutDirectoryOrExtension(flvr.Materials[mesh.MaterialIndex].MTD);

            if (shortMaterialName.EndsWith("_Alp") ||
                shortMaterialName.Contains("_Edge") ||
                shortMaterialName.Contains("_Decal") ||
                shortMaterialName.Contains("_Cloth") ||
                shortMaterialName.Contains("_al") ||
                shortMaterialName.Contains("BlendOpacity"))
            {
                DrawStep = GFXDrawStep.AlphaEdge;
            }
            else
            {
                DrawStep = GFXDrawStep.Opaque;
            }

            foreach (var matParam in flvr.Materials[mesh.MaterialIndex].Params)
            {
                var paramNameCheck = matParam.Param.ToUpper();
                // DS3/BB
                if (paramNameCheck == "G_DIFFUSETEXTURE")
                {
                    TexNameDiffuse = matParam.Value;
                }
                else if (paramNameCheck == "G_SPECULARTEXTURE")
                {
                    TexNameSpecular = matParam.Value;
                }
                else if (paramNameCheck == "G_BUMPMAPTEXTURE")
                {
                    TexNameNormal = matParam.Value;
                }
                else if (paramNameCheck == "G_DOLTEXTURE1")
                {
                    TexNameDOL1 = matParam.Value;
                }
                else if (paramNameCheck == "G_DOLTEXTURE2")
                {
                    TexNameDOL2 = matParam.Value;
                }
                // DS1 params
                else if (paramNameCheck == "G_DIFFUSE")
                {
                    TexNameDiffuse = matParam.Value;
                }
                else if (paramNameCheck == "G_SPECULAR")
                {
                    TexNameSpecular = matParam.Value;
                }
                else if (paramNameCheck == "G_BUMPMAP")
                {
                    TexNameNormal = matParam.Value;
                }
            }

            var MeshVertices = new VertexPositionColorNormalTangentTexture[mesh.VertexGroups[0].Vertices.Count];

            for (int i = 0; i < mesh.VertexGroups[0].Vertices.Count; i++)
            {
                var vert = mesh.VertexGroups[0].Vertices[i];
                MeshVertices[i] = new VertexPositionColorNormalTangentTexture();

                MeshVertices[i].Position = new Vector3(vert.Position.X, vert.Position.Y, vert.Position.Z);

                if (vert.Normal != null && vert.Tangents != null && vert.Tangents.Count > 0)
                {
                    MeshVertices[i].Normal   = Vector3.Normalize(new Vector3(vert.Normal.X, vert.Normal.Y, vert.Normal.Z));
                    MeshVertices[i].Tangent  = Vector3.Normalize(new Vector3(vert.Tangents[0].X, vert.Tangents[0].Y, vert.Tangents[0].Z));
                    MeshVertices[i].Binormal = Vector3.Cross(Vector3.Normalize(MeshVertices[i].Normal), Vector3.Normalize(MeshVertices[i].Tangent)) * vert.Tangents[0].W;
                }

                if (vert.UVs.Count > 0)
                {
                    MeshVertices[i].TextureCoordinate = new Vector2(vert.UVs[0].X, vert.UVs[0].Y);
                    if (vert.UVs.Count > 1)
                    {
                        MeshVertices[i].TextureCoordinate2 = new Vector2(vert.UVs[1].X, vert.UVs[1].Y);
                    }
                    else
                    {
                        MeshVertices[i].TextureCoordinate2 = Vector2.Zero;
                    }
                }
                else
                {
                    MeshVertices[i].TextureCoordinate  = Vector2.Zero;
                    MeshVertices[i].TextureCoordinate2 = Vector2.Zero;
                }
            }

            VertexCount = MeshVertices.Length;

            MeshFacesets = new List <FlverSubmeshRendererFaceSet>();

            foreach (var faceset in mesh.FaceSets)
            {
                bool is32bit = (faceset.IndexSize == 0x20);

                var newFaceSet = new FlverSubmeshRendererFaceSet()
                {
                    BackfaceCulling = faceset.CullBackfaces,
                    IsTriangleStrip = faceset.TriangleStrip,
                    IndexBuffer     = new IndexBuffer(
                        GFX.Device,
                        is32bit ? IndexElementSize.ThirtyTwoBits : IndexElementSize.SixteenBits,
                        faceset.Vertices.Length,
                        BufferUsage.WriteOnly),
                    IndexCount = faceset.Vertices.Length,
                };

                if (faceset.Flags == FLVER.FaceSet.FSFlags.LodLevel1)
                {
                    newFaceSet.LOD = (byte)1;
                    HasNoLODs      = false;
                }
                else if (faceset.Flags == FLVER.FaceSet.FSFlags.LodLevel2)
                {
                    newFaceSet.LOD = (byte)2;
                    HasNoLODs      = false;
                }

                if (is32bit)
                {
                    newFaceSet.IndexBuffer.SetData(faceset.Vertices);
                }
                else
                {
                    newFaceSet.IndexBuffer.SetData(faceset.Vertices.Select(x => (ushort)x).ToArray());
                }

                MeshFacesets.Add(newFaceSet);
            }

            Bounds = BoundingBox.CreateFromPoints(MeshVertices.Select(x => x.Position));

            VertBuffer = new VertexBuffer(GFX.Device,
                                          typeof(VertexPositionColorNormalTangentTexture), MeshVertices.Length, BufferUsage.WriteOnly);
            VertBuffer.SetData(MeshVertices);

            TryToLoadTextures();
        }