Ejemplo n.º 1
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);
    }
Ejemplo n.º 2
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();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Deprecated, cannot solve tangent properly.
        /// </summary>
        static void importObj()
        {
            var    openFileDialog2 = new OpenFileDialog();
            string res             = "";

            if (openFileDialog2.ShowDialog() == DialogResult.No)
            {
                return;
            }
            res = openFileDialog2.FileName;
            var objLoaderFactory       = new ObjLoaderFactory();
            MaterialStreamProvider msp = new MaterialStreamProvider();
            var openFileDialog3        = new OpenFileDialog();

            openFileDialog3.Title = "Choose MTL file:";
            if (openFileDialog3.ShowDialog() == DialogResult.No)
            {
                return;
            }

            msp.Open(openFileDialog3.FileName);
            var        objLoader  = objLoaderFactory.Create(msp);
            FileStream fileStream = new FileStream(res, FileMode.Open);
            LoadResult result     = objLoader.Load(fileStream);



            // ObjLoader.Loader.Data.Elements.Face f = result.Groups[0].Faces[0];
            // ObjLoader.Loader.Data.Elements.FaceVertex[] fv =getVertices(f);

            // string groups = new JavaScriptSerializer().Serialize(fv);
            //string vertices = new JavaScriptSerializer().Serialize(result.Vertices);

            //MessageBox.Show(groups,"Group info");
            // MessageBox.Show(vertices, "V info");
            fileStream.Close();

            //Step 1 add a new buffer layout for my program:
            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;



            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          = false;
            mn.VertexBuffers    = new List <FLVER.VertexBuffer>();
            mn.VertexBuffers.Add(new FLVER.VertexBuffer(0, layoutCount, -1));
            mn.Vertices = new List <FLVER.Vertex>();
            // mn.Vertices.Add(generateVertex(new Vector3(1,0,0),new Vector3(0,0,0),new Vector3(0,0,0),new Vector3(0,1,0),new Vector3(1,0,0)));
            //mn.Vertices.Add(generateVertex(new Vector3(0, 1, 0), new Vector3(0, 0, 0), new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 0, 0)));
            //mn.Vertices.Add(generateVertex(new Vector3(0, 0, 1), new Vector3(0, 0, 0), new Vector3(0, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 0, 0)));
            if (result.Groups.Count == 0)
            {
                MessageBox.Show("You imported nothing!");
                return;
            }
            MessageBox.Show("Vertice number:" + result.Vertices.Count + "Texture V number:" + result.Textures.Count + "Normal number:" + result.Normals.Count + "Face groups:" + result.Groups[0].Faces.Count);

            VertexNormalList[] vnlist = new VertexNormalList[result.Vertices.Count + 1];
            for (int i = 0; i < vnlist.Length; i++)
            {
                vnlist[i] = new VertexNormalList();
            }

            List <uint> faceIndexs = new List <uint>();

            uint[] textureIndexs = new uint[result.Vertices.Count + 1];
            foreach (var gr in result.Groups)
            {
                foreach (var faces in gr.Faces)
                {
                    var vList = getVertices(faces);

                    /*for (int i3 = 0; i3 < vList.Length - 2; i3++)
                     * {
                     *  faceIndexs.Add((uint)(vList[i3].VertexIndex)-1);
                     *  faceIndexs.Add((uint)(vList[i3+1].VertexIndex)-1);
                     *  faceIndexs.Add((uint)(vList[i3+2].VertexIndex)-1);
                     * }*/
                    if (vList.Length == 4)
                    {
                        faceIndexs.Add((uint)(vList[0].VertexIndex) - 1);
                        faceIndexs.Add((uint)(vList[2].VertexIndex) - 1);
                        faceIndexs.Add((uint)(vList[1].VertexIndex) - 1);

                        //record normal to help calculate vertex normals
                        int helperI = 0;
                        vnlist[(uint)(vList[helperI].VertexIndex) - 1].add(new Vector3D(result.Normals[vList[helperI].NormalIndex - 1].X, result.Normals[vList[helperI].NormalIndex - 1].Y, result.Normals[vList[helperI].NormalIndex - 1].Z));
                        textureIndexs[(vList[helperI].VertexIndex) - 1] = ((uint)vList[helperI].TextureIndex - 1);

                        helperI = 2;
                        vnlist[(uint)(vList[helperI].VertexIndex) - 1].add(new Vector3D(result.Normals[vList[helperI].NormalIndex - 1].X, result.Normals[vList[helperI].NormalIndex - 1].Y, result.Normals[vList[helperI].NormalIndex - 1].Z));
                        textureIndexs[(vList[helperI].VertexIndex) - 1] = ((uint)vList[helperI].TextureIndex - 1);

                        helperI = 1;
                        vnlist[(uint)(vList[helperI].VertexIndex) - 1].add(new Vector3D(result.Normals[vList[helperI].NormalIndex - 1].X, result.Normals[vList[helperI].NormalIndex - 1].Y, result.Normals[vList[helperI].NormalIndex - 1].Z));
                        textureIndexs[(vList[helperI].VertexIndex) - 1] = ((uint)vList[helperI].TextureIndex - 1);


                        faceIndexs.Add((uint)(vList[2].VertexIndex) - 1);
                        faceIndexs.Add((uint)(vList[0].VertexIndex) - 1);
                        faceIndexs.Add((uint)(vList[3].VertexIndex) - 1);

                        helperI = 2;
                        vnlist[(uint)(vList[helperI].VertexIndex) - 1].add(new Vector3D(result.Normals[vList[helperI].NormalIndex - 1].X, result.Normals[vList[helperI].NormalIndex - 1].Y, result.Normals[vList[helperI].NormalIndex - 1].Z));
                        textureIndexs[(vList[helperI].VertexIndex) - 1] = ((uint)vList[helperI].TextureIndex - 1);

                        helperI = 0;
                        vnlist[(uint)(vList[helperI].VertexIndex) - 1].add(new Vector3D(result.Normals[vList[helperI].NormalIndex - 1].X, result.Normals[vList[helperI].NormalIndex].Y, result.Normals[vList[helperI].NormalIndex].Z));
                        textureIndexs[(vList[helperI].VertexIndex) - 1] = ((uint)vList[helperI].TextureIndex - 1);

                        helperI = 3;
                        vnlist[(uint)(vList[helperI].VertexIndex) - 1].add(new Vector3D(result.Normals[vList[helperI].NormalIndex].X, result.Normals[vList[helperI].NormalIndex].Y, result.Normals[vList[helperI].NormalIndex].Z));
                        textureIndexs[(vList[helperI].VertexIndex) - 1] = ((uint)vList[helperI].TextureIndex - 1);
                    }
                    else if (vList.Length == 3)
                    {
                        faceIndexs.Add((uint)(vList[0].VertexIndex) - 1);
                        faceIndexs.Add((uint)(vList[2].VertexIndex) - 1);
                        faceIndexs.Add((uint)(vList[1].VertexIndex) - 1);


                        int helperI = 2;
                        vnlist[(uint)(vList[helperI].VertexIndex) - 1].add(new Vector3D(result.Normals[vList[helperI].NormalIndex - 1].X, result.Normals[vList[helperI].NormalIndex - 1].Y, result.Normals[vList[helperI].NormalIndex - 1].Z));
                        textureIndexs[(vList[helperI].VertexIndex) - 1] = ((uint)vList[helperI].TextureIndex - 1);

                        helperI = 0;
                        vnlist[(uint)(vList[helperI].VertexIndex) - 1].add(new Vector3D(result.Normals[vList[helperI].NormalIndex - 1].X, result.Normals[vList[helperI].NormalIndex - 1].Y, result.Normals[vList[helperI].NormalIndex - 1].Z));
                        textureIndexs[(vList[helperI].VertexIndex) - 1] = ((uint)vList[helperI].TextureIndex - 1);

                        helperI = 1;
                        vnlist[(uint)(vList[helperI].VertexIndex) - 1].add(new Vector3D(result.Normals[vList[helperI].NormalIndex - 1].X, result.Normals[vList[helperI].NormalIndex - 1].Y, result.Normals[vList[helperI].NormalIndex - 1].Z));
                        textureIndexs[(vList[helperI].VertexIndex) - 1] = ((uint)vList[helperI].TextureIndex - 1);
                    }
                }
            }
            //mn.FaceSets[0].Vertices = new uint [3]{0,1,2 };


            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();



            //Set all the vertices.
            for (int iv = 0; iv < result.Vertices.Count; iv++)
            {
                var v = result.Vertices[iv];

                Vector3 uv1     = new Vector3();
                Vector3 uv2     = new Vector3();
                Vector3 normal  = new Vector3(0, 1, 0);
                Vector3 tangent = new Vector3(1, 0, 0);
                if (result.Textures != null)
                {
                    if (iv < result.Textures.Count)
                    {
                        var vm = result.Textures[(int)textureIndexs[iv]];
                        uv1 = new Vector3(vm.X, vm.Y, 0);
                        uv2 = new Vector3(vm.X, vm.Y, 0);
                    }
                }
                normal  = vnlist[iv].calculateAvgNormal().toNumV3();
                tangent = RotatePoint(normal, 0, (float)Math.PI / 2, 0);
                mn.Vertices.Add(generateVertex(new Vector3(v.X, v.Y, v.Z), uv1, uv2, normal, tangent));
            }
            FLVER.Material matnew = new JavaScriptSerializer().Deserialize <FLVER.Material>(new JavaScriptSerializer().Serialize(targetFlver.Materials[0]));
            matnew.Name = res.Substring(res.LastIndexOf('\\') + 1);
            targetFlver.Materials.Add(matnew);
            mn.MaterialIndex = materialCount;


            targetFlver.Meshes.Add(mn);
            MessageBox.Show("Added a custom mesh! PLease click modify to save it!");
            updateVertices();
            //mn.Vertices.Add();
        }
        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();
        }
        /*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();
        }