/// <summary> /// The extract meshes to obj. /// </summary> /// <param name="path">The path.</param> /// <remarks></remarks> public virtual void ExtractMeshesToOBJ(string path) { if (path[path.Length - 1] != '\\') { path += "\\"; } string texturepath = path + "Textures\\"; Directory.CreateDirectory(texturepath); List<string> names = new List<string>(); string mtllib = this.name + ".mtl"; FileStream FS = new FileStream(path + mtllib, FileMode.Create); StreamWriter SW = new StreamWriter(FS); if (Shaders == null) { goto hce1; } Panel p = new Panel(); Renderer r = new Renderer(); r.CreateDevice(p); for (int x = 0; x < this.Shaders.Shader.Length; x++) { string[] namesplit = this.Shaders.Shader[x].shaderName.Split('\\'); string temps = namesplit[namesplit.Length - 1]; temps = temps.Replace(' ', '_'); names.Add(temps); this.Shaders.Shader[x].MakeTextures(ref r.device); // if (this.Shaders.Shader[x].MainTexture == null) { continue; } TextureLoader.Save( texturepath + temps + ".dds", ImageFileFormat.Dds, this.Shaders.Shader[x].MainTexture); // this.Shaders.Shader[x].MainBitmap.Save(texturepath + temps + ".gif", System.Drawing.Imaging.ImageFormat.Gif); if (x > 0) { SW.WriteLine(string.Empty); } SW.WriteLine("newmtl " + temps); SW.WriteLine("Ka 1.000000 1.000000 1.000000"); SW.WriteLine("Kd 1.000000 1.000000 1.000000"); SW.WriteLine("Ks 1.000000 1.000000 1.000000"); SW.WriteLine("Ns 0.000000"); SW.WriteLine("map_Kd .\\Textures\\" + temps + ".dds"); } SW.Close(); FS.Close(); hce1: FileStream FS2 = new FileStream(path + this.name + ".obj", FileMode.Create); StreamWriter SW2 = new StreamWriter(FS2); int faces = 0; int pass = 0; SW2.WriteLine("# ------------------------------------"); SW2.WriteLine("# Halo 2 Model - Extracted with Entity"); SW2.WriteLine("# ------------------------------------"); for (int x = 0; x < this.RawDataMetaChunks.Length; x++) { SW2.WriteLine(); SW2.WriteLine("g Section_" + x.ToString().PadLeft(3, '0')); writeOBJ(SW2, mtllib, this.RawDataMetaChunks[x], names, ref pass, ref faces); FS = new FileStream(path + this.name + "[" + x + "].obj", FileMode.Create); SW = new StreamWriter(FS); SW.WriteLine("# ------------------------------------"); SW.WriteLine("# Halo 2 Model - Extracted with Entity"); SW.WriteLine("# ------------------------------------"); int ps = 0; int fc = 0; writeOBJ(SW, mtllib, this.RawDataMetaChunks[x], names, ref ps, ref fc); /* SW.WriteLine("mtllib " + mtllib); for (int y = 0; y < this.RawDataMetaChunks[x].VerticeCount; y++) { string temps = "v " + this.RawDataMetaChunks[x].Vertices[y].X.ToString() + " " + this.RawDataMetaChunks[x].Vertices[y].Y.ToString() + " " + this.RawDataMetaChunks[x].Vertices[y].Z.ToString(); SW.WriteLine(temps); } SW.WriteLine("# " + this.RawDataMetaChunks[x].Vertices.Count.ToString() + " vertices"); for (int y = 0; y < this.RawDataMetaChunks[x].VerticeCount; y++) { string temps = "vt " + this.RawDataMetaChunks[x].UVs[y].X.ToString() + " " + this.RawDataMetaChunks[x].UVs[y].Y.ToString(); SW.WriteLine(temps); } SW.WriteLine("# " + this.RawDataMetaChunks[x].Vertices.Count.ToString() + " texture vertices"); for (int y = 0; y < this.RawDataMetaChunks[x].VerticeCount; y++) { string temps = "vn " + this.RawDataMetaChunks[x].Normals[y].X + " " + this.RawDataMetaChunks[x].Normals[y].Y + " " + this.RawDataMetaChunks[x].Normals[y].Z; SW.WriteLine(temps); } SW.WriteLine("# " + this.RawDataMetaChunks[x].Vertices.Count.ToString() + " normals"); for (int y = 0; y < this.RawDataMetaChunks[x].SubMeshInfo.Length; y++) { SW.WriteLine("g 0." + y.ToString()); // SW.WriteLine("s 0." + y.ToString()); try { SW.WriteLine("usemtl " + names[this.RawDataMetaChunks[x].SubMeshInfo[y].ShaderNumber]); } catch { } short[] s***e = new short[100000]; int s = 0; if (this.RawDataMetaChunks[x].FaceCount * 3 != this.RawDataMetaChunks[x].IndiceCount) { int m = this.RawDataMetaChunks[x].SubMeshInfo[y].IndiceStart; bool dir = false; short tempx; short tempy; short tempz; do { //if (mode.EndOfIndices[x][j]>m+2){break;} tempx = this.RawDataMetaChunks[x].Indices[m]; tempy = this.RawDataMetaChunks[x].Indices[m + 1]; tempz = this.RawDataMetaChunks[x].Indices[m + 2]; if (tempx != tempy && tempx != tempz && tempy != tempz) { if (dir == false) { s***e[s] = tempx; s***e[s + 1] = tempy; s***e[s + 2] = tempz; s += 3; dir = true; } else { s***e[s] = tempx; s***e[s + 1] = tempz; s***e[s + 2] = tempy; s += 3; dir = false; } m += 1; } else { if (dir == true) { dir = false; } else { dir = true; } m += 1; } } while (m < this.RawDataMetaChunks[x].SubMeshInfo[y].IndiceStart + this.RawDataMetaChunks[x].SubMeshInfo[y].IndiceCount - 2); } else { Array.Copy(this.RawDataMetaChunks[x].Indices, this.RawDataMetaChunks[x].SubMeshInfo[y].IndiceStart, s***e, 0, this.RawDataMetaChunks[x].SubMeshInfo[y].IndiceCount); s = this.RawDataMetaChunks[x].SubMeshInfo[y].IndiceCount;//this.RawDataMetaChunks[x].IndiceCount; } for (int xx = 0; xx < s; xx += 3) { string temps = "f " + (s***e[xx] + 1) + "/" + (s***e[xx] + 1) + "/" + (s***e[xx] + 1) + " " + (s***e[xx + 1] + 1) + "/" + (s***e[xx + 1] + 1) + "/" + (s***e[xx + 1] + 1) + " " + (s***e[xx + 2] + 1) + "/" + (s***e[xx + 2] + 1) + "/" + (s***e[xx + 2] + 1); SW.WriteLine(temps); } SW.WriteLine("# " + (s / 3) + " elements"); } */ SW.Close(); FS.Close(); } SW2.Close(); FS2.Close(); }
/// <summary> /// The extract meshes to x. /// </summary> /// <param name="path">The path.</param> /// <remarks></remarks> public void ExtractMeshesToX(string path) { if (path[path.Length - 1] != '\\') { path += "\\"; } string texturepath = path + "Textures\\"; Directory.CreateDirectory(texturepath); List<string> materialnames = new List<string>(); Panel f = new Panel(); Renderer r = new Renderer(); r.CreateDevice(f); for (int x = 0; x < this.Shaders.Shader.Length; x++) { this.Shaders.Shader[x].MakeTextures(ref r.device); string[] namesplit = this.Shaders.Shader[x].shaderName.Split('\\'); string temps = namesplit[namesplit.Length - 1]; temps = temps.Replace(" ", "_"); temps = temps.Replace("1", "One"); temps = temps.Replace("2", "Two"); temps = temps.Replace("3", "Three"); temps = temps.Replace("4", "Four"); temps = temps.Replace("5", "Five"); temps = temps.Replace("6", "Six"); temps = temps.Replace("7", "Seven"); temps = temps.Replace("8", "Eight"); temps = temps.Replace("9", "Nine"); temps = temps.Replace("0", "Zero"); // if (materialnames.IndexOf(temps)==-1) materialnames.Add(temps); TextureLoader.Save( texturepath + temps + ".dds", ImageFileFormat.Dds, this.Shaders.Shader[x].MainTexture); } for (int x = 0; x < this.RawDataMetaChunks.Length; x++) { FileStream FS = new FileStream(path + this.name + "[" + x + "].X", FileMode.Create); StreamWriter SW = new StreamWriter(FS); SW.WriteLine("xof 0303txt 0032"); SW.WriteLine(string.Empty); SW.WriteLine("Header {"); SW.WriteLine("1;"); SW.WriteLine("0;"); SW.WriteLine("1;"); SW.WriteLine("}"); SW.WriteLine(string.Empty); // blankline #region Write_Materials for (int y = 0; y < materialnames.Count; y++) { SW.WriteLine("Material " + materialnames[y] + "{"); SW.WriteLine("1.000000; 1.000000; 1.000000; 1.000000;;"); // R = 1.0, G = 0.0, B = 0.0 SW.WriteLine("0.000000;"); SW.WriteLine("0.000000;0.000000;0.000000;;"); SW.WriteLine("0.000000;0.000000;0.000000;;"); SW.WriteLine("TextureFilename {"); string tempmloc = "\"Textures\\" + materialnames[y] + ".dds\";"; tempmloc = tempmloc.Replace("\\", "\\\\"); SW.WriteLine(tempmloc); SW.WriteLine("}"); SW.WriteLine("}"); } #endregion SW.WriteLine(string.Empty); // blankline #region Write_Frame_Heirarchy // Write_Frame_Header("Scene_Root", Matrix.Identity, ref SW); if (this.Frames != null) { WriteRecursiveFrameHeirarchy(this.Frames.Frame[0], ref SW); } #endregion #region Write_Mesh ////scene root matrix Matrix tempm = Matrix.Identity; Write_Frame_Header("Scene_Root", tempm, ref SW); SW.WriteLine(string.Empty); // blankline Write_Frame_Header("Root", tempm, ref SW); #region Write_Mesh_Header SW.WriteLine("Mesh TestMesh {"); SW.WriteLine(this.RawDataMetaChunks[x].VerticeCount + "; // vertices count"); #endregion #region Write_Vertices for (int y = 0; y < this.RawDataMetaChunks[x].VerticeCount; y++) { string temps = this.RawDataMetaChunks[x].Vertices[y].X + ";" + this.RawDataMetaChunks[x].Vertices[y].Y + ";" + this.RawDataMetaChunks[x].Vertices[y].Z; temps += y != this.RawDataMetaChunks[x].VerticeCount - 1 ? ";," : ";;"; SW.WriteLine(temps); } #endregion SW.WriteLine(string.Empty); // blankline #region Face_Fields int[] faceCounts = new int[this.RawDataMetaChunks[x].SubMeshInfo.Length]; short[] tempIndices = new short[100000]; int totalindicecount = 0; int totalfacecount = 0; #endregion #region Process Faces for (int y = 0; y < this.RawDataMetaChunks[x].SubMeshInfo.Length; y++) { int s = 0; // check if indices are triangle list or strip if (this.RawDataMetaChunks[x].FaceCount * 3 != this.RawDataMetaChunks[x].IndiceCount) { #region Decompress_Triangle_Strips int m = this.RawDataMetaChunks[x].SubMeshInfo[y].IndiceStart; bool dir = false; short tempx; short tempy; short tempz; do { tempx = this.RawDataMetaChunks[x].Indices[m]; tempy = this.RawDataMetaChunks[x].Indices[m + 1]; tempz = this.RawDataMetaChunks[x].Indices[m + 2]; if (tempx != tempy && tempx != tempz && tempy != tempz) { if (dir == false) { tempIndices[totalindicecount + s] = tempx; tempIndices[totalindicecount + s + 1] = tempy; tempIndices[totalindicecount + s + 2] = tempz; s += 3; dir = true; } else { tempIndices[totalindicecount + s] = tempx; tempIndices[totalindicecount + s + 1] = tempz; tempIndices[totalindicecount + s + 2] = tempy; s += 3; dir = false; } m += 1; } else { if (dir) { dir = false; } else { dir = true; } m += 1; } } while (m < this.RawDataMetaChunks[x].SubMeshInfo[y].IndiceStart + this.RawDataMetaChunks[x].SubMeshInfo[y].IndiceCount - 2); #endregion } else { Array.Copy( this.RawDataMetaChunks[x].Indices, this.RawDataMetaChunks[x].SubMeshInfo[y].IndiceStart, tempIndices, totalindicecount, this.RawDataMetaChunks[x].SubMeshInfo[y].IndiceCount); s = this.RawDataMetaChunks[x].SubMeshInfo[y].IndiceCount; } faceCounts[y] = s / 3; totalindicecount += s; } totalfacecount = totalindicecount / 3; #endregion #region WriteFaces SW.WriteLine(totalfacecount + "; // face count"); for (int xx = 0; xx < totalindicecount; xx += 3) { string temps = "3;" + tempIndices[xx] + "," + tempIndices[xx + 1] + "," + tempIndices[xx + 2]; temps += xx != totalindicecount - 3 ? ";," : ";;"; SW.WriteLine(temps); } #endregion SW.WriteLine(string.Empty); // blankline #region MeshMaterialList #region MeshMaterialList_Header SW.WriteLine("MeshMaterialList {"); SW.WriteLine(this.RawDataMetaChunks[x].SubMeshInfo.Length + ";"); // Amount of Textures SW.WriteLine(totalfacecount + ";"); // Total Face Count #endregion #region WriteFaceTextures for (int y = 0; y < this.RawDataMetaChunks[x].SubMeshInfo.Length; y++) { for (int xx = 0; xx < faceCounts[y]; xx ++) { string temps = y + ";"; // temps+=(y==this.RawDataMetaChunks[x].SubMeshInfo.Length-1&&xx==faceCounts[y]-1)?";:":";,"; SW.WriteLine(temps); } } #endregion #region WriteTextureNames for (int y = 0; y < this.RawDataMetaChunks[x].SubMeshInfo.Length; y++) { SW.WriteLine("{" + materialnames[this.RawDataMetaChunks[x].SubMeshInfo[y].ShaderNumber] + "}"); } #endregion SW.WriteLine("}"); #endregion SW.WriteLine(string.Empty); // blankline #region Write_Normals #region Write_Normals_Header SW.WriteLine("MeshNormals {"); SW.WriteLine(this.RawDataMetaChunks[x].VerticeCount + "; // normal count"); #endregion #region OutputNormals for (int y = 0; y < this.RawDataMetaChunks[x].VerticeCount; y++) { NumberFormatInfo ni = new NumberFormatInfo(); ni.NumberDecimalDigits = 7; string xs = this.RawDataMetaChunks[x].Normals[y].X.ToString("f", ni); string ys = this.RawDataMetaChunks[x].Normals[y].Y.ToString("f", ni); string zs = this.RawDataMetaChunks[x].Normals[y].Z.ToString("f", ni); string temps = xs + ";" + ys + ";" + zs; temps += y != this.RawDataMetaChunks[x].VerticeCount - 1 ? ";," : ";;"; SW.WriteLine(temps); } #endregion SW.WriteLine(string.Empty); // blankline #region WriteRedundantNormalFaces SW.WriteLine(totalfacecount + "; // face count"); for (int xx = 0; xx < totalindicecount; xx += 3) { string temps = "3;" + tempIndices[xx] + "," + tempIndices[xx + 1] + "," + tempIndices[xx + 2]; temps += xx != totalindicecount - 3 ? ";," : ";;"; SW.WriteLine(temps); } #endregion SW.WriteLine("}"); #endregion #region Write_UVs SW.WriteLine("MeshTextureCoords {"); SW.WriteLine(this.RawDataMetaChunks[x].VerticeCount + "; // uv count"); for (int y = 0; y < this.RawDataMetaChunks[x].VerticeCount; y++) { string temps = this.RawDataMetaChunks[x].UVs[y].X + ";" + this.RawDataMetaChunks[x].UVs[y].Y; temps += y != this.RawDataMetaChunks[x].VerticeCount - 1 ? ";," : ";;"; SW.WriteLine(temps); } SW.WriteLine("}"); #endregion #region Write_Bones #region Skin_Mesh_Header SW.WriteLine("XSkinMeshHeader {"); SW.WriteLine("2;"); SW.WriteLine("4;"); SW.WriteLine(this.RawDataMetaChunks[x].BoneMap.Count + ";"); SW.WriteLine("}"); #endregion #region Skin_Weights for (int y = 0; y < this.RawDataMetaChunks[x].BoneMap.Count; y++) { SW.WriteLine("SkinWeights {"); SW.WriteLine("\"" + this.Frames.Frame[this.RawDataMetaChunks[x].BoneMap[y]].Name + "\";"); List<int> tempintarray = new List<int>(); for (int z = 0; z < this.RawDataMetaChunks[x].VerticeBones.Count; z++) { if (this.RawDataMetaChunks[x].VerticeBones[z].BoneIndex[0] == y) { tempintarray.Add(z); } } SW.WriteLine(tempintarray.Count + ";"); for (int z = 0; z < tempintarray.Count; z++) { SW.WriteLine(tempintarray[z] + ((z == tempintarray.Count - 1) ? ";" : ",")); } for (int z = 0; z < tempintarray.Count; z++) { SW.WriteLine( this.RawDataMetaChunks[x].VerticeBones[y].Weight[0] + ((z == tempintarray.Count - 1) ? ";" : ",")); } Matrix mm; // if (y == 0) // { // mm = this.Frames.Frame[this.RawDataMetaChunks[x].BoneMap[y]].matrix; // mm.Translate(-0.1f, -0.1f, 0); // mm = mm - this.Frames.Frame[this.RawDataMetaChunks[x].BoneMap[y]].matrix; // } // else // { mm = Matrix.Identity; // } WriteMatrix(mm, ref SW); SW.WriteLine("}"); } #endregion #endregion SW.WriteLine("}"); SW.WriteLine("}"); SW.WriteLine("}"); // SW.WriteLine("}"); #endregion SW.Close(); FS.Close(); } }
/// <summary> /// The load from obj. /// </summary> /// <param name="FilePath">The file path.</param> /// <remarks></remarks> public virtual void LoadFromOBJ(string FilePath) { if (FilePath[FilePath.Length - 1] != '\\') { FilePath += "\\"; } FileStream FS = new FileStream(FilePath + this.name + ".mtl", FileMode.Open); StreamReader SR = new StreamReader(FS); List<string> MaterialNames = new List<string>(); string temps = string.Empty; while (temps != null) { temps = SR.ReadLine(); if (temps == null) { break; } string[] split = temps.Split(' '); if (split[0] == "newmtl") { // if (MaterialNames.IndexOf(split[1]) == -1) // { MaterialNames.Add(split[1]); // } } } if (MaterialNames.Count > this.Shaders.Shader.Length) { List<ShaderInfo> newlist = new List<ShaderInfo>(); for (int x = 0; x < this.Shaders.Shader.Length; x++) { newlist.Add(this.Shaders.Shader[x]); } int diff = MaterialNames.Count - this.Shaders.Shader.Length; for (int x = 0; x < diff; x++) { newlist.Add(this.Shaders.Shader[0]); } this.Shaders.Shader = newlist.ToArray(); } SR.Close(); FS.Close(); #region Bounding Box Fields float minx = 0; float maxx = 0; float miny = 0; float maxy = 0; float minz = 0; float maxz = 0; float minu = 0; float maxu = 0; float minv = 0; float maxv = 0; #endregion #region Read OBJ Files for (int x = 0; x < this.RawDataMetaChunks.Length; x++) { #region Fields int verticecount = 0; int facecount = 0; List<Vector3> vertices = new List<Vector3>(); List<Vector3> normals = new List<Vector3>(); List<Vector2> uvs = new List<Vector2>(); List<List<short>> faces = new List<List<short>>(); List<List<short>> facesuv = new List<List<short>>(); List<List<short>> facesnormal = new List<List<short>>(); Hashtable Materials = new Hashtable(); int groupcount = 0; #endregion FS = new FileStream(FilePath + this.name + "[" + x + "].obj", FileMode.Open); SR = new StreamReader(FS); #region ParseFile do { temps = SR.ReadLine(); if (temps == null) { continue; } temps = temps.Replace(" ", " "); string[] tempstrings = temps.Split(',', ' '); switch (tempstrings[0]) { #region Vertices case "v": Vector3 tempv = new Vector3(); tempv.X = float.Parse(tempstrings[1]); tempv.Y = float.Parse(tempstrings[2]); tempv.Z = float.Parse(tempstrings[3]); if (tempv.X < minx) { minx = tempv.X; } if (tempv.X > maxx) { maxx = tempv.X; } if (tempv.Y < miny) { miny = tempv.Y; } if (tempv.Y > maxy) { maxy = tempv.Y; } if (tempv.Z < minz) { minz = tempv.Z; } if (tempv.Z > maxz) { maxz = tempv.Z; } vertices.Add(tempv); verticecount++; break; #endregion #region Normals case "vn": Vector3 tempvn = new Vector3(); tempvn.X = float.Parse(tempstrings[1]); tempvn.Y = float.Parse(tempstrings[2]); tempvn.Z = float.Parse(tempstrings[3]); normals.Add(tempvn); break; #endregion #region UVs case "vt": Vector2 tempv2 = new Vector2(); tempv2.X = float.Parse(tempstrings[1]); tempv2.Y = float.Parse(tempstrings[2]); if (tempv2.X < minu) { minu = tempv2.X; } if (tempv2.X > maxu) { maxu = tempv2.X; } if (tempv2.Y < minv) { minv = tempv2.Y; } if (tempv2.Y > maxv) { maxv = tempv2.Y; } uvs.Add(tempv2); verticecount++; break; #endregion #region Group case "g": List<short> templist = new List<short>(); List<short> templist2 = new List<short>(); List<short> templist3 = new List<short>(); faces.Add(templist); facesuv.Add(templist2); facesnormal.Add(templist3); groupcount++; break; #endregion #region Faces case "f": string[] split1 = tempstrings[1].Split('/'); string[] split2 = tempstrings[2].Split('/'); string[] split3 = tempstrings[3].Split('/'); short temp1 = short.Parse(split1[0]); short temp2 = short.Parse(split2[0]); short temp3 = short.Parse(split3[0]); temp1--; temp2--; temp3--; faces[groupcount - 1].Add(temp1); faces[groupcount - 1].Add(temp2); faces[groupcount - 1].Add(temp3); temp1 = short.Parse(split1[1]); temp2 = short.Parse(split2[1]); temp3 = short.Parse(split3[1]); temp1--; temp2--; temp3--; facesuv[groupcount - 1].Add(temp1); facesuv[groupcount - 1].Add(temp2); facesuv[groupcount - 1].Add(temp3); temp1 = short.Parse(split1[2]); temp2 = short.Parse(split2[2]); temp3 = short.Parse(split3[2]); temp1--; temp2--; temp3--; facesnormal[groupcount - 1].Add(temp1); facesnormal[groupcount - 1].Add(temp2); facesnormal[groupcount - 1].Add(temp3); facecount += 3; break; #endregion #region Materials case "usemtl": Materials.Add(groupcount - 1, tempstrings[1]); // Materials.Add(Materials.Count, tempstrings[1]); break; #endregion } } while (temps != null); #endregion SR.Close(); FS.Close(); int count = 0; while (count < faces.Count) { start: if (faces[count].Count == 0) { faces.RemoveAt(count); facesuv.RemoveAt(count); facesnormal.RemoveAt(count); count = 0; groupcount--; goto start; } count++; } Renderer temprender = new Renderer(); Panel fakepanel = new Panel(); temprender.CreateDevice(fakepanel); List<List<short>> Faces = new List<List<short>>(); List<List<short>> Facesuv = new List<List<short>>(); List<List<short>> Facesnormal = new List<List<short>>(); List<short> newIndices = new List<short>(); #region Submeshes this.RawDataMetaChunks[x].SubMeshInfo = new RawDataMetaChunk.ModelSubMeshInfo[groupcount]; int totalindicecount = 0; this.RawDataMetaChunks[x].Vertices.Clear(); this.RawDataMetaChunks[x].UVs.Clear(); this.RawDataMetaChunks[x].Normals.Clear(); for (int y = 0; y < groupcount; y++) { Faces.Add(new List<short>()); for (int h = 0; h < faces[y].Count; h++) { int tempvert = faces[y][h]; int tempuv = facesuv[y][h]; int tempnorm = facesnormal[y][h]; for (int i = 0; i < y + 1; i++) { for (int j = 0; j < faces[i].Count; j++) { if (i == y && j == h) { goto gohere1; } int tempvert2 = faces[i][j]; int tempuv2 = facesuv[i][j]; int tempnorm2 = facesnormal[i][j]; if (tempvert == tempvert2 && tempuv == tempuv2 && tempnorm == tempnorm2) { Faces[y].Add(Faces[i][j]); goto gohere; } } } gohere1: this.RawDataMetaChunks[x].UVs.Add(uvs[facesuv[y][h]]); this.RawDataMetaChunks[x].Vertices.Add(vertices[faces[y][h]]); this.RawDataMetaChunks[x].Normals.Add(normals[facesnormal[y][h]]); Faces[y].Add((short)(this.RawDataMetaChunks[x].Vertices.Count - 1)); gohere: ; } #region Make Triangle Strip Mesh m = temprender.MakeMesh( this.RawDataMetaChunks[x].Vertices, Faces[y], this.RawDataMetaChunks[x].UVs); int indicecount = 0; unsafe { int[] adj = new int[m.NumberFaces * 3]; m.GenerateAdjacency(0.0f, adj); int[] test; int[] test2; GraphicsStream oi; Mesh oid = m.Optimize( MeshFlags.OptimizeIgnoreVerts | MeshFlags.OptimizeAttributeSort, adj, out test, out test2, out oi); IndexBuffer ib = oid.IndexBuffer; ib = Mesh.ConvertMeshSubsetToSingleStrip( oid, 0, MeshFlags.OptimizeIgnoreVerts | MeshFlags.OptimizeStripeReorder | MeshFlags.IbManaged, out indicecount); GraphicsStream xxxx = ib.Lock(0, 0, LockFlags.None); short* ind = (short*)xxxx.InternalData.ToPointer(); for (int z = 0; z < indicecount; z++) { newIndices.Add(ind[z]); } } #endregion #region SubmeshInfo RawDataMetaChunk.ModelSubMeshInfo submesh = new RawDataMetaChunk.ModelSubMeshInfo(); submesh.IndiceStart = totalindicecount; totalindicecount += indicecount; submesh.IndiceCount = indicecount; submesh.ShaderNumber = 0; object tempobject = Materials[y]; if (tempobject != null) { int tempint = MaterialNames.IndexOf((string)tempobject); if (tempint != -1) { submesh.ShaderNumber = tempint; } } this.RawDataMetaChunks[x].SubMeshInfo[y] = submesh; #endregion } #endregion this.RawDataMetaChunks[x].Indices = newIndices.ToArray(); this.RawDataMetaChunks[x].IndiceCount = this.RawDataMetaChunks[x].Indices.Length; this.RawDataMetaChunks[x].VerticeCount = this.RawDataMetaChunks[x].Vertices.Count; this.RawDataMetaChunks[x].FaceCount = facecount / 3; } #region Bounding Box this.BoundingBox.MinX = minx; this.BoundingBox.MaxX = maxx; this.BoundingBox.MinY = miny; this.BoundingBox.MaxY = maxy; this.BoundingBox.MinZ = minz; this.BoundingBox.MaxZ = maxz; this.BoundingBox.MinU = minu; this.BoundingBox.MaxU = maxu; this.BoundingBox.MinV = minv; this.BoundingBox.MaxV = maxv; #endregion #endregion }
/// <summary> /// The extract model as single mesh. /// </summary> /// <param name="path">The path.</param> /// <remarks></remarks> public void ExtractModelAsSingleMesh(string path) { int ndex = path.LastIndexOf('\\'); string f**k = path.Remove(ndex + 1); string texturepath = f**k + "Textures\\"; Directory.CreateDirectory(texturepath); List<string> names = new List<string>(); string mtllib = this.Name + ".mtl"; FileStream FS = new FileStream(f**k + mtllib, FileMode.Create); StreamWriter SW = new StreamWriter(FS); Panel p = new Panel(); Renderer r = new Renderer(); r.CreateDevice(p); for (int x = 0; x < this.Shaders.Shader.Length; x++) { string[] namesplit = this.Shaders.Shader[x].shaderName.Split('\\'); string temps = namesplit[namesplit.Length - 1]; names.Add(temps); this.Shaders.Shader[x].MakeTextures(ref r.device); TextureLoader.Save( texturepath + temps + ".dds", ImageFileFormat.Dds, this.Shaders.Shader[x].MainTexture); if (x > 0) { SW.WriteLine(string.Empty); } SW.WriteLine("newmtl " + temps); SW.WriteLine("Ka 1.000000 1.000000 1.000000"); SW.WriteLine("Kd 1.000000 1.000000 1.000000"); SW.WriteLine("Ks 1.000000 1.000000 1.000000"); SW.WriteLine("Ns 0.000000"); SW.WriteLine(@"map_Kd .\\Textures\\" + temps + ".dds"); } SW.Close(); FS.Close(); #region ExportBSPMeshes FS = new FileStream(path, FileMode.Create); SW = new StreamWriter(FS); SW.WriteLine("# ------------------------------------"); SW.WriteLine("# Halo 2 BSP Mesh - Extracted with Entity"); SW.WriteLine("# ------------------------------------"); SW.WriteLine("mtllib " + mtllib); int vertcount = 0; for (int x = 0; x < this.BSPRawDataMetaChunks.Length; x++) { if (this.BSPRawDataMetaChunks[x].VerticeCount == 0) { continue; } for (int y = 0; y < this.BSPRawDataMetaChunks[x].VerticeCount; y++) { string temps = "v " + this.BSPRawDataMetaChunks[x].Vertices[y].X.ToString("R") + " " + this.BSPRawDataMetaChunks[x].Vertices[y].Y.ToString("R") + " " + this.BSPRawDataMetaChunks[x].Vertices[y].Z.ToString("R"); SW.WriteLine(temps); } SW.WriteLine("# " + this.BSPRawDataMetaChunks[x].Vertices.Count + " vertices"); for (int y = 0; y < this.BSPRawDataMetaChunks[x].VerticeCount; y++) { string temps = "vt " + this.BSPRawDataMetaChunks[x].UVs[y].X.ToString("R") + " " + (1 - this.BSPRawDataMetaChunks[x].UVs[y].Y).ToString("R"); SW.WriteLine(temps); } SW.WriteLine("# " + this.BSPRawDataMetaChunks[x].Vertices.Count + " texture vertices"); for (int y = 0; y < this.BSPRawDataMetaChunks[x].VerticeCount; y++) { string temps = "vn " + this.BSPRawDataMetaChunks[x].Normals[y].X.ToString("R") + " " + this.BSPRawDataMetaChunks[x].Normals[y].Y.ToString("R") + " " + this.BSPRawDataMetaChunks[x].Normals[y].Z.ToString("R"); SW.WriteLine(temps); } SW.WriteLine("# " + this.BSPRawDataMetaChunks[x].Vertices.Count + " normals"); for (int y = 0; y < this.BSPRawDataMetaChunks[x].SubMeshInfo.Length; y++) { SW.WriteLine("g " + x + "." + y); // SW.WriteLine("s "+x.ToString()+"." + y.ToString()); SW.WriteLine("usemtl " + names[this.BSPRawDataMetaChunks[x].SubMeshInfo[y].ShaderNumber]); // int[] s***e = new int[100000]; int[] s***e = new int[this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount]; int s = 0; if (this.BSPRawDataMetaChunks[x].FaceCount * 3 != this.BSPRawDataMetaChunks[x].IndiceCount) { int m = this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceStart; bool dir = false; short tempx; short tempy; short tempz; do { // if (mode.EndOfIndices[x][j]>m+2){break;} tempx = this.BSPRawDataMetaChunks[x].Indices[m]; tempy = this.BSPRawDataMetaChunks[x].Indices[m + 1]; tempz = this.BSPRawDataMetaChunks[x].Indices[m + 2]; if (tempx != tempy && tempx != tempz && tempy != tempz) { if (dir == false) { s***e[s] = vertcount + tempx; s***e[s + 1] = vertcount + tempy; s***e[s + 2] = vertcount + tempz; s += 3; dir = true; } else { s***e[s] = vertcount + tempx; s***e[s + 1] = vertcount + tempz; s***e[s + 2] = vertcount + tempy; s += 3; dir = false; } m += 1; } else { if (dir) { dir = false; } else { dir = true; } m += 1; } } while (m < this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceStart + this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount - 2); } else { for (int u = 0; u < this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount; u++) { s***e[u] = vertcount + this.BSPRawDataMetaChunks[x].Indices[ this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceStart + u]; } s = this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount; } for (int xx = 0; xx < s; xx += 3) { string temps = "f " + (s***e[xx] + 1) + "/" + (s***e[xx] + 1) + "/" + (s***e[xx] + 1) + " " + (s***e[xx + 1] + 1) + "/" + (s***e[xx + 1] + 1) + "/" + (s***e[xx + 1] + 1) + " " + (s***e[xx + 2] + 1) + "/" + (s***e[xx + 2] + 1) + "/" + (s***e[xx + 2] + 1); SW.WriteLine(temps); } SW.WriteLine("# " + (s / 3) + " elements"); } vertcount += this.BSPRawDataMetaChunks[x].VerticeCount; } #endregion SW.Close(); FS.Close(); #region ExportBSPPermutationMeshes FS = new FileStream(path.Substring(0, path.LastIndexOf('.')) + "-permutations.obj", FileMode.Create); SW = new StreamWriter(FS); SW.WriteLine("# ------------------------------------"); SW.WriteLine("# Halo 2 BSP Permutation Mesh"); SW.WriteLine("# ------------------------------------"); SW.WriteLine("mtllib " + mtllib); vertcount = 0; for (int tx = 0; tx < this.PermutationInfo.Length; tx++) { int x = this.PermutationInfo[tx].sceneryIndex; if ((this.BSPPermutationRawDataMetaChunks[x].RawDataChunkInfo.Length == 0) || (this.BSPPermutationRawDataMetaChunks[x].VerticeCount == 0)) { continue; } for (int y = 0; y < this.BSPPermutationRawDataMetaChunks[x].VerticeCount; y++) { Vector3 tv3 = new Vector3( this.BSPPermutationRawDataMetaChunks[x].Vertices[y].X, this.BSPPermutationRawDataMetaChunks[x].Vertices[y].Y, this.BSPPermutationRawDataMetaChunks[x].Vertices[y].Z); tv3.TransformCoordinate(this.PermutationInfo[tx].mat); string temps = "v " + tv3.X.ToString("R") + " " + tv3.Y.ToString("R") + " " + tv3.Z.ToString("R"); SW.WriteLine(temps); } SW.WriteLine("# " + this.BSPPermutationRawDataMetaChunks[x].Vertices.Count + " vertices"); for (int y = 0; y < this.BSPPermutationRawDataMetaChunks[x].VerticeCount; y++) { string temps = "vt " + this.BSPPermutationRawDataMetaChunks[x].UVs[y].X.ToString("R") + " " + this.BSPPermutationRawDataMetaChunks[x].UVs[y].Y.ToString("R"); SW.WriteLine(temps); } SW.WriteLine("# " + this.BSPPermutationRawDataMetaChunks[x].Vertices.Count + " texture vertices"); for (int y = 0; y < this.BSPPermutationRawDataMetaChunks[x].VerticeCount; y++) { Vector3 tv3 = new Vector3( this.BSPPermutationRawDataMetaChunks[x].Normals[y].X, this.BSPPermutationRawDataMetaChunks[x].Normals[y].Y, this.BSPPermutationRawDataMetaChunks[x].Normals[y].Z); tv3.TransformNormal(this.PermutationInfo[tx].mat); string temps = "vn " + tv3.X.ToString("R") + " " + tv3.Y.ToString("R") + " " + tv3.Z.ToString("R"); /* string temps = "vn " + this.BSPPermutationRawDataMetaChunks[x].Normals[y].X.ToString() + " " + this.BSPPermutationRawDataMetaChunks[x].Normals[y].Y.ToString() + " " + this.BSPPermutationRawDataMetaChunks[x].Normals[y].Z.ToString(); */ SW.WriteLine(temps); } SW.WriteLine("# " + this.BSPPermutationRawDataMetaChunks[x].Vertices.Count + " normals"); for (int y = 0; y < this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo.Length; y++) { SW.WriteLine("g " + tx + "." + y); SW.WriteLine( "usemtl " + names[this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].ShaderNumber]); // int[] s***e = new int[100000]; int[] s***e = new int[this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount]; int s = 0; if (this.BSPPermutationRawDataMetaChunks[x].FaceCount * 3 != this.BSPPermutationRawDataMetaChunks[x].IndiceCount) { int m = this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].IndiceStart; bool dir = false; short tempx; short tempy; short tempz; do { // if (mode.EndOfIndices[x][j]>m+2){break;} tempx = this.BSPPermutationRawDataMetaChunks[x].Indices[m]; tempy = this.BSPPermutationRawDataMetaChunks[x].Indices[m + 1]; tempz = this.BSPPermutationRawDataMetaChunks[x].Indices[m + 2]; if (tempx != tempy && tempx != tempz && tempy != tempz) { if (dir == false) { s***e[s] = vertcount + tempx; s***e[s + 1] = vertcount + tempy; s***e[s + 2] = vertcount + tempz; s += 3; dir = true; } else { s***e[s] = vertcount + tempx; s***e[s + 1] = vertcount + tempz; s***e[s + 2] = vertcount + tempy; s += 3; dir = false; } m += 1; } else { if (dir) { dir = false; } else { dir = true; } m += 1; } } while (m < this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].IndiceStart + this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount - 2); } else { for (int u = 0; u < this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount; u++) { s***e[u] = vertcount + this.BSPPermutationRawDataMetaChunks[x].Indices[ this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].IndiceStart + u]; } s = this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount; } for (int xx = 0; xx < s; xx += 3) { string temps = "f " + (s***e[xx] + 1) + "/" + (s***e[xx] + 1) + "/" + (s***e[xx] + 1) + " " + (s***e[xx + 1] + 1) + "/" + (s***e[xx + 1] + 1) + "/" + (s***e[xx + 1] + 1) + " " + (s***e[xx + 2] + 1) + "/" + (s***e[xx + 2] + 1) + "/" + (s***e[xx + 2] + 1); SW.WriteLine(temps); } SW.WriteLine("# " + (s / 3) + " elements"); } vertcount += this.BSPPermutationRawDataMetaChunks[x].VerticeCount; } SW.Close(); FS.Close(); #endregion }
/// <summary> /// The extract model. /// </summary> /// <param name="path">The path.</param> /// <remarks></remarks> public void ExtractModel(string path) { if (path[path.Length - 1] != '\\') { path += "\\"; } string texturepath = path + "Textures\\"; Directory.CreateDirectory(texturepath); List<string> names = new List<string>(); string mtllib = this.Name + ".mtl"; FileStream FS = new FileStream(path + mtllib, FileMode.Create); StreamWriter SW = new StreamWriter(FS); Panel p = new Panel(); Renderer r = new Renderer(); r.CreateDevice(p); for (int x = 0; x < this.Shaders.Shader.Length; x++) { string[] namesplit = this.Shaders.Shader[x].shaderName.Split('\\'); string temps = namesplit[namesplit.Length - 1]; temps = temps.Replace(' ', '_'); names.Add(temps); this.Shaders.Shader[x].MakeTextures(ref r.device); try { TextureLoader.Save( texturepath + temps + ".dds", ImageFileFormat.Dds, this.Shaders.Shader[x].MainTexture); } catch { } if (x > 0) { // space SW.WriteLine(string.Empty); } SW.WriteLine("newmtl " + temps); SW.WriteLine("Ka 1.000000 1.000000 1.000000"); SW.WriteLine("Kd 1.000000 1.000000 1.000000"); SW.WriteLine("Ks 1.000000 1.000000 1.000000"); SW.WriteLine("Ns 0.000000"); SW.WriteLine(@"map_Kd .\\Textures\\" + temps + ".dds"); } SW.Close(); FS.Close(); #region ExportBSPMeshes for (int x = 0; x < this.BSPRawDataMetaChunks.Length; x++) { if (this.BSPRawDataMetaChunks[x].VerticeCount == 0) { continue; } FS = new FileStream(path + this.Name + "[" + x + "].obj", FileMode.Create); SW = new StreamWriter(FS); SW.WriteLine("# ------------------------------------"); SW.WriteLine("# Halo 2 BSP Mesh - Extracted with Entity"); SW.WriteLine("# ------------------------------------"); SW.WriteLine("mtllib " + mtllib); for (int y = 0; y < this.BSPRawDataMetaChunks[x].VerticeCount; y++) { string temps = "v " + this.BSPRawDataMetaChunks[x].Vertices[y].X.ToString("R") + " " + this.BSPRawDataMetaChunks[x].Vertices[y].Y.ToString("R") + " " + this.BSPRawDataMetaChunks[x].Vertices[y].Z.ToString("R"); SW.WriteLine(temps); } SW.WriteLine("# " + this.BSPRawDataMetaChunks[x].Vertices.Count + " vertices"); for (int y = 0; y < this.BSPRawDataMetaChunks[x].VerticeCount; y++) { string temps = "vt " + this.BSPRawDataMetaChunks[x].UVs[y].X.ToString("R") + " " + this.BSPRawDataMetaChunks[x].UVs[y].Y.ToString("R"); SW.WriteLine(temps); } SW.WriteLine("# " + this.BSPRawDataMetaChunks[x].Vertices.Count + " texture vertices"); for (int y = 0; y < this.BSPRawDataMetaChunks[x].VerticeCount; y++) { string temps = "vn " + this.BSPRawDataMetaChunks[x].Normals[y].X.ToString("R") + " " + this.BSPRawDataMetaChunks[x].Normals[y].Y.ToString("R") + " " + this.BSPRawDataMetaChunks[x].Normals[y].Z.ToString("R"); SW.WriteLine(temps); } SW.WriteLine("# " + this.BSPRawDataMetaChunks[x].Vertices.Count + " normals"); for (int y = 0; y < this.BSPRawDataMetaChunks[x].SubMeshInfo.Length; y++) { SW.WriteLine("g 0." + y); // SW.WriteLine("s 0." + y.ToString()); SW.WriteLine("usemtl " + names[this.BSPRawDataMetaChunks[x].SubMeshInfo[y].ShaderNumber]); int[] s***e = new int[100000]; int s = 0; // if (this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount == (this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount/3)*3) if (this.BSPRawDataMetaChunks[x].FaceCount * 3 != this.BSPRawDataMetaChunks[x].IndiceCount) { int m = this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceStart; bool dir = false; short tempx; short tempy; short tempz; do { // if (mode.EndOfIndices[x][j]>m+2){break;} tempx = this.BSPRawDataMetaChunks[x].Indices[m]; tempy = this.BSPRawDataMetaChunks[x].Indices[m + 1]; tempz = this.BSPRawDataMetaChunks[x].Indices[m + 2]; if (tempx != tempy && tempx != tempz && tempy != tempz) { if (dir == false) { s***e[s] = tempx; s***e[s + 1] = tempy; s***e[s + 2] = tempz; s += 3; dir = true; } else { s***e[s] = tempx; s***e[s + 1] = tempz; s***e[s + 2] = tempy; s += 3; dir = false; } m += 1; } else { if (dir) { dir = false; } else { dir = true; } m += 1; } } while (m < this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceStart + this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount - 2); } else { Array.Copy( this.BSPRawDataMetaChunks[x].Indices, this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceStart, s***e, 0, this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount); s = this.BSPRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount; } for (int xx = 0; xx < s; xx += 3) { string temps = "f " + (s***e[xx] + 1) + "/" + (s***e[xx] + 1) + "/" + (s***e[xx] + 1) + " " + (s***e[xx + 1] + 1) + "/" + (s***e[xx + 1] + 1) + "/" + (s***e[xx + 1] + 1) + " " + (s***e[xx + 2] + 1) + "/" + (s***e[xx + 2] + 1) + "/" + (s***e[xx + 2] + 1); SW.WriteLine(temps); } SW.WriteLine("# " + (s / 3) + " elements"); } SW.Close(); FS.Close(); } #endregion #region ExportBSPPermutationMeshes for (int x = 0; x < this.BSPPermutationRawDataMetaChunks.Length; x++) { if (this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo == null) { continue; } FS = new FileStream(path + this.Name + "-Permutation[" + x + "].obj", FileMode.Create); SW = new StreamWriter(FS); SW.WriteLine("# ------------------------------------"); SW.WriteLine("# Halo 2 BSP Permutation Mesh - Extracted with Entity"); SW.WriteLine("# ------------------------------------"); SW.WriteLine("mtllib " + mtllib); for (int y = 0; y < this.BSPPermutationRawDataMetaChunks[x].VerticeCount; y++) { string temps = "v " + this.BSPPermutationRawDataMetaChunks[x].Vertices[y].X.ToString("R") + " " + this.BSPPermutationRawDataMetaChunks[x].Vertices[y].Y.ToString("R") + " " + this.BSPPermutationRawDataMetaChunks[x].Vertices[y].Z.ToString("R"); SW.WriteLine(temps); } SW.WriteLine("# " + this.BSPPermutationRawDataMetaChunks[x].Vertices.Count + " vertices"); for (int y = 0; y < this.BSPPermutationRawDataMetaChunks[x].VerticeCount; y++) { string temps = "vt " + this.BSPPermutationRawDataMetaChunks[x].UVs[y].X.ToString("R") + " " + this.BSPPermutationRawDataMetaChunks[x].UVs[y].Y.ToString("R"); SW.WriteLine(temps); } SW.WriteLine("# " + this.BSPPermutationRawDataMetaChunks[x].Vertices.Count + " texture vertices"); for (int y = 0; y < this.BSPPermutationRawDataMetaChunks[x].VerticeCount; y++) { string temps = "vn " + this.BSPPermutationRawDataMetaChunks[x].Normals[y].X.ToString("R") + " " + this.BSPPermutationRawDataMetaChunks[x].Normals[y].Y.ToString("R") + " " + this.BSPPermutationRawDataMetaChunks[x].Normals[y].Z.ToString("R"); SW.WriteLine(temps); } SW.WriteLine("# " + this.BSPPermutationRawDataMetaChunks[x].Vertices.Count + " normals"); for (int y = 0; y < this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo.Length; y++) { SW.WriteLine("g 0." + y); // SW.WriteLine("s 0." + y.ToString()); SW.WriteLine( "usemtl " + names[this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].ShaderNumber]); short[] s***e = new short[100000]; int s = 0; if (this.BSPPermutationRawDataMetaChunks[x].FaceCount * 3 != this.BSPPermutationRawDataMetaChunks[x].IndiceCount) { int m = this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].IndiceStart; bool dir = false; short tempx; short tempy; short tempz; do { // if (mode.EndOfIndices[x][j]>m+2){break;} tempx = this.BSPPermutationRawDataMetaChunks[x].Indices[m]; tempy = this.BSPPermutationRawDataMetaChunks[x].Indices[m + 1]; tempz = this.BSPPermutationRawDataMetaChunks[x].Indices[m + 2]; if (tempx != tempy && tempx != tempz && tempy != tempz) { if (dir == false) { s***e[s] = tempx; s***e[s + 1] = tempy; s***e[s + 2] = tempz; s += 3; dir = true; } else { s***e[s] = tempx; s***e[s + 1] = tempz; s***e[s + 2] = tempy; s += 3; dir = false; } m += 1; } else { if (dir) { dir = false; } else { dir = true; } m += 1; } } while (m < this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].IndiceStart + this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount - 2); } else { Array.Copy( this.BSPPermutationRawDataMetaChunks[x].Indices, this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].IndiceStart, s***e, 0, this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount); s = this.BSPPermutationRawDataMetaChunks[x].SubMeshInfo[y].IndiceCount; } for (int xx = 0; xx < s; xx += 3) { string temps = "f " + (s***e[xx] + 1) + "/" + (s***e[xx] + 1) + "/" + (s***e[xx] + 1) + " " + (s***e[xx + 1] + 1) + "/" + (s***e[xx + 1] + 1) + "/" + (s***e[xx + 1] + 1) + " " + (s***e[xx + 2] + 1) + "/" + (s***e[xx + 2] + 1) + "/" + (s***e[xx + 2] + 1); SW.WriteLine(temps); } SW.WriteLine("# " + (s / 3) + " elements"); } SW.Close(); FS.Close(); } #endregion if (this.UnknownChunks == null) { return; } #region ExportUnknown for (int x = 0; x < this.UnknownChunks.Length; x++) { if (this.UnknownChunks[x].IndiceCount == 0) { continue; } FS = new FileStream(path + this.Name + "-Unknown[" + x + "].obj", FileMode.Create); SW = new StreamWriter(FS); SW.WriteLine("# ------------------------------------"); SW.WriteLine("# Halo 2 BSP Unknown Mesh - Extracted with Entity"); SW.WriteLine("# ------------------------------------"); for (int y = 0; y < this.UnknownChunks[x].VerticeCount; y++) { string temps = "v " + this.UnknownChunks[x].Vertices[y].X + " " + this.UnknownChunks[x].Vertices[y].Y + " " + this.UnknownChunks[x].Vertices[y].Z; SW.WriteLine(temps); } SW.WriteLine("# " + this.UnknownChunks[x].Vertices.Count + " vertices"); SW.WriteLine("g 0.0"); short[] s***e = new short[100000]; int s = 0; Array.Copy(this.UnknownChunks[x].Indices, 0, s***e, 0, UnknownChunks[x].IndiceCount); s = this.UnknownChunks[x].IndiceCount; for (int xx = 0; xx < s; xx += 3) { string temps = "f " + (s***e[xx] + 1) + "/" + (s***e[xx] + 1) + "/" + (s***e[xx] + 1) + " " + (s***e[xx + 1] + 1) + "/" + (s***e[xx + 1] + 1) + "/" + (s***e[xx + 1] + 1) + " " + (s***e[xx + 2] + 1) + "/" + (s***e[xx + 2] + 1) + "/" + (s***e[xx + 2] + 1); SW.WriteLine(temps); } SW.WriteLine("# " + (s / 3) + " elements"); SW.Close(); FS.Close(); } #endregion }
/// <summary> /// The load from obj. /// </summary> /// <param name="FilePath">The file path.</param> /// <remarks></remarks> public void LoadFromOBJ(string FilePath) { if (FilePath[FilePath.Length - 1] != '\\') { FilePath += "\\"; } FileStream FS = new FileStream(FilePath + this.Name + ".mtl", FileMode.Open); StreamReader SR = new StreamReader(FS); List<string> MaterialNames = new List<string>(); string temps = string.Empty; while (temps != null) { temps = SR.ReadLine(); if (temps == null) { break; } string[] split = temps.Split(' '); if (split[0] == "newmtl") { if (MaterialNames.IndexOf(split[1]) == -1) { MaterialNames.Add(split[1]); } } } SR.Close(); FS.Close(); #region Bounding Box Fields float minx = 0; float maxx = 0; float miny = 0; float maxy = 0; float minz = 0; float maxz = 0; float minu = 0; float maxu = 0; float minv = 0; float maxv = 0; #endregion #region Read OBJ Files for (int x = 0; x < this.BSPRawDataMetaChunks.Length; x++) { #region Fields int verticecount = 0; int facecount = 0; List<Vector3> vertices = new List<Vector3>(); List<Vector3> normals = new List<Vector3>(); List<Vector2> uvs = new List<Vector2>(); List<List<int>> faces = new List<List<int>>(); List<List<int>> facesuv = new List<List<int>>(); List<List<int>> facesnormal = new List<List<int>>(); Hashtable Materials = new Hashtable(); int groupcount = 0; #endregion FS = new FileStream(FilePath + this.Name + "[" + x + "].obj", FileMode.Open); SR = new StreamReader(FS); #region ParseFile do { temps = SR.ReadLine(); if (temps == null) { continue; } temps = temps.Replace(" ", " "); string[] tempstrings = temps.Split(',', ' '); switch (tempstrings[0]) { #region Vertices case "v": Vector3 tempv = new Vector3(); tempv.X = float.Parse(tempstrings[1]); tempv.Y = float.Parse(tempstrings[2]); tempv.Z = float.Parse(tempstrings[3]); if (tempv.X < minx) { minx = tempv.X; } if (tempv.X > maxx) { maxx = tempv.X; } if (tempv.Y < miny) { miny = tempv.Y; } if (tempv.Y > maxy) { maxy = tempv.Y; } if (tempv.Z < minz) { minz = tempv.Z; } if (tempv.Z > maxz) { maxz = tempv.Z; } vertices.Add(tempv); verticecount++; break; #endregion #region Normals case "vn": Vector3 tempvn = new Vector3(); tempvn.X = float.Parse(tempstrings[1]); tempvn.Y = float.Parse(tempstrings[2]); tempvn.Z = float.Parse(tempstrings[3]); normals.Add(tempvn); break; #endregion #region UVs case "vt": Vector2 tempv2 = new Vector2(); tempv2.X = float.Parse(tempstrings[1]); tempv2.Y = float.Parse(tempstrings[2]); if (tempv2.X < minu) { minu = tempv2.X; } if (tempv2.X > maxu) { maxu = tempv2.X; } if (tempv2.Y < minv) { minv = tempv2.Y; } if (tempv2.Y > maxv) { maxv = tempv2.Y; } uvs.Add(tempv2); verticecount++; break; #endregion #region Group case "g": if ((faces.Count == 0) || (faces[faces.Count - 1].Count > 0) || (facesuv[facesuv.Count - 1].Count > 0) || (facesnormal[facesnormal.Count - 1].Count > 0)) { List<int> templist = new List<int>(); List<int> templist2 = new List<int>(); List<int> templist3 = new List<int>(); faces.Add(templist); facesuv.Add(templist2); facesnormal.Add(templist3); groupcount++; } break; #endregion #region Faces case "f": string[] split1 = tempstrings[1].Split('/'); string[] split2 = tempstrings[2].Split('/'); string[] split3 = tempstrings[3].Split('/'); int temp1 = int.Parse(split1[0]); int temp2 = int.Parse(split2[0]); int temp3 = int.Parse(split3[0]); temp1--; temp2--; temp3--; faces[groupcount - 1].Add(temp1); faces[groupcount - 1].Add(temp2); faces[groupcount - 1].Add(temp3); temp1 = int.Parse(split1[1]); temp2 = int.Parse(split2[1]); temp3 = int.Parse(split3[1]); temp1--; temp2--; temp3--; facesuv[groupcount - 1].Add(temp1); facesuv[groupcount - 1].Add(temp2); facesuv[groupcount - 1].Add(temp3); temp1 = int.Parse(split1[2]); temp2 = int.Parse(split2[2]); temp3 = int.Parse(split3[2]); temp1--; temp2--; temp3--; facesnormal[groupcount - 1].Add(temp1); facesnormal[groupcount - 1].Add(temp2); facesnormal[groupcount - 1].Add(temp3); facecount += 3; break; #endregion #region Materials case "usemtl": Materials.Add(groupcount - 1, tempstrings[1]); break; #endregion } } while (temps != null); #endregion SR.Close(); FS.Close(); int count = 0; while (count < faces.Count) { start: if (faces[count].Count == 0) { faces.RemoveAt(count); facesuv.RemoveAt(count); facesnormal.RemoveAt(count); count = 0; groupcount--; goto start; } count++; } // Here we have all the vertices/textures/normals loaded into groups /// vertices / uvs / normals as Vector3 /// faces / facesuv / facesnormal as pointers to the above /// /// /// we need to output to (Vetcor3): /// this.BSPRawDataMetaChunks[x].Vertices /// this.BSPRawDataMetaChunks[x].UVs /// this.BSPRawDataMetaChunks[x].Normals /// Renderer temprender = new Renderer(); Panel fakepanel = new Panel(); temprender.CreateDevice(fakepanel); List<List<short>> Faces = new List<List<short>>(); List<List<short>> Facesuv = new List<List<short>>(); List<List<short>> Facesnormal = new List<List<short>>(); List<short> newIndices = new List<short>(); #region Submeshes this.BSPRawDataMetaChunks[x].SubMeshInfo = new ParsedModel.RawDataMetaChunk.ModelSubMeshInfo[groupcount]; int totalindicecount = 0; this.BSPRawDataMetaChunks[x].Vertices.Clear(); this.BSPRawDataMetaChunks[x].UVs.Clear(); this.BSPRawDataMetaChunks[x].Normals.Clear(); for (int y = 0; y < groupcount; y++) { Application.DoEvents(); Faces.Add(new List<short>()); for (int h = 0; h < faces[y].Count; h++) { int tempvert = faces[y][h]; int tempuv = facesuv[y][h]; int tempnorm = facesnormal[y][h]; for (int i = 0; i < y + 1; i++) { for (int j = 0; j < faces[i].Count; j++) { if (i == y && j == h) { goto gohere1; } int tempvert2 = faces[i][j]; int tempuv2 = facesuv[i][j]; int tempnorm2 = facesnormal[i][j]; if (tempvert == tempvert2 && tempuv == tempuv2 && tempnorm == tempnorm2) { Faces[y].Add(Faces[i][j]); newIndices.Add(Faces[i][j]); goto gohere; } } } gohere1: this.BSPRawDataMetaChunks[x].Vertices.Add(vertices[faces[y][h]]); this.BSPRawDataMetaChunks[x].UVs.Add(uvs[facesuv[y][h]]); this.BSPRawDataMetaChunks[x].Normals.Add(normals[facesnormal[y][h]]); newIndices.Add((short)(this.BSPRawDataMetaChunks[x].Vertices.Count - 1)); Faces[y].Add((short)(this.BSPRawDataMetaChunks[x].Vertices.Count - 1)); gohere: ; } #region SubmeshInfo ParsedModel.RawDataMetaChunk.ModelSubMeshInfo submesh = new ParsedModel.RawDataMetaChunk.ModelSubMeshInfo(); submesh.IndiceStart = totalindicecount; totalindicecount += faces[y].Count; submesh.IndiceCount = faces[y].Count; submesh.ShaderNumber = 0; object tempobject = Materials[y]; if (tempobject != null) { int tempint = MaterialNames.IndexOf((string)tempobject); if (tempint != -1) { submesh.ShaderNumber = tempint; } } this.BSPRawDataMetaChunks[x].SubMeshInfo[y] = submesh; #endregion } #endregion this.BSPRawDataMetaChunks[x].FaceCount = facecount / 3; int temp = 0; for (int i = 0; i < faces.Count; i++) { this.BSPRawDataMetaChunks[x].SubMeshInfo[i].IndiceCount = faces[i].Count; this.BSPRawDataMetaChunks[x].SubMeshInfo[i].IndiceStart = temp; temp += faces[i].Count; } this.BSPRawDataMetaChunks[x].Indices = newIndices.ToArray(); this.BSPRawDataMetaChunks[x].IndiceCount = this.BSPRawDataMetaChunks[x].Indices.Length; this.BSPRawDataMetaChunks[x].VerticeCount = this.BSPRawDataMetaChunks[x].Vertices.Count; #region Displays each mesh in a window. Debugging ONLY! /***************************************** Form tForm = new Form(); temprender = new entity.Renderer.Renderer(); fakepanel = new Panel(); temprender.CreateDevice(fakepanel); fakepanel.Size = tForm.Size; tForm.Controls.Add(fakepanel); tForm.Show(); temprender.device.VertexFormat = HaloBSPVertex.FVF; temprender.device.RenderState.CullMode = Cull.None; temprender.device.Transform.World = Matrix.Identity; temprender.device.SamplerState[0].AddressU = TextureAddress.Wrap; temprender.device.SamplerState[0].AddressV = TextureAddress.Wrap; temprender.device.RenderState.Lighting = true; temprender.device.RenderState.ZBufferEnable = true; temprender.device.RenderState.ZBufferWriteEnable = true; temprender.device.SetTexture(0, null); temprender.device.SetTexture(1, null); temprender.device.RenderState.AlphaBlendEnable = false; temprender.device.RenderState.AlphaTestEnable = false; // cam.Position = new Vector3(this.BSPRawDataMetaChunks[x].Vertices[0].X - 10, this.BSPRawDataMetaChunks[x].Vertices[0].Y - 10, this.BSPRawDataMetaChunks[x].Vertices[0].Z); // cam.LookAt = this.BSPRawDataMetaChunks[x].Vertices[0]; Material WhiteMaterial = new Material(); WhiteMaterial.Diffuse = System.Drawing.Color.White; WhiteMaterial.Ambient = System.Drawing.Color.White; Material BlackMaterial = new Material(); BlackMaterial.Diffuse = System.Drawing.Color.Black; BlackMaterial.Ambient = System.Drawing.Color.Black; //Mesh m2 = Mesh.Box(temprender.device, 5, 5, 5); temprender.device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, tForm.Width / tForm.Height, 1f, 250f); //temprender.device.Transform.View = Matrix.LookAtLH(new Vector3(20, 20, 20), new Vector3(0, 0, 0), new Vector3(0, 0, 1)); temprender.device.Transform.View = Matrix.LookAtLH( new Vector3(this.BSPRawDataMetaChunks[x].Vertices[0].X - 5, this.BSPRawDataMetaChunks[x].Vertices[0].Y + 20, this.BSPRawDataMetaChunks[x].Vertices[0].Z - 5), this.BSPRawDataMetaChunks[x].Vertices[0], new Vector3(0, 0, 1)); List<short> tInd = new List<short>(this.BSPPermutationRawDataMetaChunks[x].Indices); Mesh mesh = temprender.MakeMesh(this.BSPPermutationRawDataMetaChunks[x].Vertices, tInd, this.BSPPermutationRawDataMetaChunks[x].UVs); // While the form is still valid, render and process messages while (tForm.Created) { temprender.device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, System.Drawing.Color.Black, 1.0f, 0); temprender.BeginScene(System.Drawing.Color.Blue); temprender.device.Transform.World = Matrix.Translation(0, 0, 0); for (int ll = 0; ll < 1; ll++) { temprender.device.Material = WhiteMaterial; temprender.device.RenderState.FillMode = FillMode.Solid; mesh.DrawSubset(ll); temprender.device.Material = BlackMaterial; temprender.device.RenderState.FillMode = FillMode.WireFrame; mesh.DrawSubset(ll); } //m2.DrawSubset(0); temprender.EndScene(); Application.DoEvents(); GC.Collect(0); GC.WaitForPendingFinalizers(); GC.Collect(0); } /********************************************/ #endregion } #endregion }
// Used for Injection Selection box /// <summary> /// The convert to bump map tool strip menu item_ click. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The e.</param> /// <remarks></remarks> private void convertToBumpMapToolStripMenuItem_Click(object sender, EventArgs e) { if (saveBitmapDialog1.ShowDialog() == DialogResult.Cancel) { return; } Panel p = new Panel(); Renderer r = new Renderer(); r.CreateDevice(p); map.OpenMap(MapTypes.Internal); ParsedBitmap pm = new ParsedBitmap(ref map.SelectedMeta, map); Bitmap b = pm.FindChunkAndDecode(0, 0, 0, ref map.SelectedMeta, map, 0, 0); ShaderInfo s = new ShaderInfo(); s.BumpMapBitmap = b; map.CloseMap(); s.MakeTextures(ref r.device); TextureLoader.Save(saveBitmapDialog1.FileName, ImageFileFormat.Dds, s.NormalMap); }