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