public void DumpToOBJ(string file_name) { using (FileStream strm = new FileStream(file_name, FileMode.Create)) { EndianBinaryWriter writer = new EndianBinaryWriter(strm, Endian.Big); List <Vector3> master_list = new List <Vector3>(); for (int i = 0; i < m_Meshes.Count; i++) { Mesh cur_mesh = m_Meshes[i]; for (int j = 0; j < cur_mesh.VertexData.Position.Count; j++) { if (!master_list.Contains(cur_mesh.VertexData.Position[j])) { master_list.Add(cur_mesh.VertexData.Position[j]); } } } for (int i = 0; i < master_list.Count; i++) { writer.Write($"v { master_list[i].X } { master_list[i].Y } { master_list[i].Z }\n".ToCharArray()); writer.Flush(); } for (int i = 0; i < m_Meshes.Count; i++) { writer.Write($"o { m_Meshes[i].Name }\n".ToCharArray()); for (int j = 0; j < m_Meshes[i].Vertices.Count; j += 3) { MeshVertexIndex index_1 = m_Meshes[i].Vertices[j]; MeshVertexIndex index_2 = m_Meshes[i].Vertices[j + 1]; MeshVertexIndex index_3 = m_Meshes[i].Vertices[j + 2]; if (index_1.Position >= m_Meshes[i].VertexData.Position.Count) { continue; } if (index_2.Position >= m_Meshes[i].VertexData.Position.Count) { continue; } if (index_3.Position >= m_Meshes[i].VertexData.Position.Count) { continue; } Vector3 vec_1 = m_Meshes[i].VertexData.Position[index_1.Position]; Vector3 vec_2 = m_Meshes[i].VertexData.Position[index_2.Position]; Vector3 vec_3 = m_Meshes[i].VertexData.Position[index_3.Position]; writer.Write($"f { master_list.IndexOf(vec_1) + 1 } { master_list.IndexOf(vec_2) + 1 } { master_list.IndexOf(vec_3) + 1 }\n".ToCharArray()); writer.Flush(); } } } }
private List <MeshVertexIndex> ConvertTopologyToTriangles(int fromType, List <MeshVertexIndex> indexes) { List <MeshVertexIndex> sortedIndexes = new List <MeshVertexIndex>(); if (fromType == 4) { for (int v = 2; v < indexes.Count; v++) { bool isEven = v % 2 != 0; MeshVertexIndex[] newTri = new MeshVertexIndex[3]; newTri[0] = indexes[v - 2]; newTri[1] = isEven ? indexes[v] : indexes[v - 1]; newTri[2] = isEven ? indexes[v - 1] : indexes[v]; // Check against degenerate triangles (a triangle which shares indexes) if (newTri[0] != newTri[1] && newTri[1] != newTri[2] && newTri[2] != newTri[0]) { sortedIndexes.AddRange(newTri); } else { System.Console.WriteLine("Degenerate triangle detected, skipping TriangleStrip conversion to triangle."); } } } else if (fromType == 1) { for (int v = 1; v < indexes.Count - 1; v++) { // Triangle is always, v, v+1, and index[0]? MeshVertexIndex[] newTri = new MeshVertexIndex[3]; newTri[0] = indexes[v]; newTri[1] = indexes[v + 1]; newTri[2] = indexes[0]; // Check against degenerate triangles (a triangle which shares indexes) if (newTri[0] != newTri[1] && newTri[1] != newTri[2] && newTri[2] != newTri[0]) { sortedIndexes.AddRange(newTri); } else { System.Console.WriteLine("Degenerate triangle detected, skipping TriangleFan conversion to triangle."); } } } else if (fromType == 2) { // The good news is, Triangles just go straight though! sortedIndexes.AddRange(indexes); } else if (fromType == 3) { } else { System.Console.WriteLine("Unsupported GXPrimitiveType: {0} in conversion to Triangle List.", fromType); } return(sortedIndexes); }
private void ReadPrimitiveData(EndianBinaryReader reader, EndianBinaryReader string_table) { reader.Skip(0x38); int prim_offset = reader.ReadInt32(); int prim_count = reader.ReadInt32(); int data_base_offset = prim_offset + (prim_count * 12); reader.BaseStream.Seek(prim_offset, SeekOrigin.Begin); for (int i = 0; i < prim_count; i++) { int name_offset = reader.ReadInt32(); int vec_count = reader.ReadInt32(); int data_offset = reader.ReadInt32(); string_table.BaseStream.Seek(name_offset, SeekOrigin.Begin); string mesh_name = string_table.ReadStringUntil('\0'); Mesh mesh = m_Meshes.Find(x => x.Name == mesh_name); long cur_pos = reader.BaseStream.Position; reader.BaseStream.Seek(data_base_offset + data_offset, SeekOrigin.Begin); for (int v = 0; v < vec_count; v++) { ushort unk_1 = reader.ReadUInt16(); byte unk_a = reader.ReadByte(); byte unk_2 = reader.ReadByte(); List <MeshVertexIndex> vert_indices = new List <MeshVertexIndex>(); for (int a = 0; a < 3; a++) { MeshVertexIndex index = new MeshVertexIndex(); index.Position = reader.ReadInt16(); index.Normal = reader.ReadInt16(); index.Color0 = reader.ReadInt16(); index.Tex0 = reader.ReadInt16(); vert_indices.Add(index); } // quad if (unk_1 == 3) { MeshVertexIndex index = new MeshVertexIndex(); index.Position = reader.ReadInt16(); index.Normal = reader.ReadInt16(); index.Color0 = reader.ReadInt16(); index.Tex0 = reader.ReadInt16(); vert_indices.Add(index); mesh.Vertices.AddRange(new MeshVertexIndex[] { vert_indices[0], vert_indices[1], vert_indices[2] }); mesh.Vertices.AddRange(new MeshVertexIndex[] { vert_indices[1], vert_indices[3], vert_indices[2] }); } else if (unk_1 == 2) { mesh.Vertices.AddRange(new MeshVertexIndex[] { vert_indices[0], vert_indices[1], vert_indices[2] }); reader.SkipInt32(); reader.SkipInt32(); } // tristrip else if (unk_1 == 4) { int tri_count = reader.ReadInt32(); int unk_value = reader.ReadInt32(); List <MeshVertexIndex> strip = new List <MeshVertexIndex>(); strip.AddRange(new MeshVertexIndex[] { vert_indices[0], vert_indices[1], vert_indices[2] }); for (int t = 0; t < tri_count - 1; t++) { MeshVertexIndex orig = strip[strip.Count - 2]; MeshVertexIndex new_vert = new MeshVertexIndex(); new_vert.Position = orig.Position + 3; strip.Add(new_vert); } //mesh.Vertices.AddRange(ConvertTopologyToTriangles(4, strip).ToArray()); } Vector3 unk_3 = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } reader.BaseStream.Seek(cur_pos, SeekOrigin.Begin); } reader.BaseStream.Seek(8, SeekOrigin.Begin); }