Code:
class BMSConverter { int charCount; int vertCount; int boneCount; int faceCount; string mtlLib; string meshGroup; float[,] vertices; float[,] normals; float[,] textures; //char[,] bones; short[,] faces; #region Calculate public void Calculate(string file) { BinaryReader br = new BinaryReader(File.Open(file, FileMode.Open)); string filetype = new string(br.ReadChars(8)); // Filetype ( first 9 Bytes) string version = new string(br.ReadChars(4)); // 110 if (version.Contains("110")) { // Springe zur position 72 ( Nicht benötigte Header Informationen ) br.BaseStream.Position += 60; // Länge des MeshGroup Namens charCount = br.ReadInt32(); // Lese Namen meshGroup = new string(br.ReadChars(charCount)); // Länge des Materiels Namen charCount = br.ReadInt32(); // Lese Material Namen mtlLib = new string(br.ReadChars(charCount)); // Ignoierere Unbekannten Wert ( Int32 = 4bytes ) ? br.BaseStream.Position += 4; // Lese anzahl der Verticen vertCount = br.ReadInt32(); // Erstelle Arrays vertices = new float[vertCount, 3]; normals = new float[vertCount, 3]; textures = new float[vertCount, 2]; // Lese Werte for (int i = 0; i < vertCount; i++) { // Vertices for (int j = 0; j < 3; j++) { vertices[i,j] = br.ReadSingle(); } // Normal for (int j = 0; j < 3; j++) { normals[i, j] = br.ReadSingle(); } // Textures for (int j = 0; j < 2; j++) { textures[i, j] = br.ReadSingle(); } // Ignoiere 12 Bytes pro Vertices ?? br.BaseStream.Position += 12; } // Lese Bones/.. (Ignoiere Bones) boneCount = br.ReadInt32(); if (boneCount > 0) { for (int i = 0; i < boneCount; i++) { // b charCount = br.ReadInt32(); // Überspringe br.BaseStream.Position += charCount; } br.BaseStream.Position += vertCount * 6; // Unnötiger Gaymax schrott } // Lese Faces faceCount = br.ReadInt32(); faces = new short[faceCount, 3]; for (int i = 0; i < faceCount; i++) { for (int j = 0; j < 3; j++) { faces[i, j] = br.ReadInt16(); } } // Schließe Reader br.Close(); } else { Console.WriteLine("Invaild Version: {0}", version); } } #endregion #region WriteOBJ public void WriteOBJ(string output) { List<string> l_List = new List<string>(); string line; // # = Kommentar line = "# ~ Converted by BMSConverter.NET ~"; l_List.Add(line); line = "# ~ Joymax Engine BMS Version: 110 ~"; l_List.Add(line); // Schreibe Vertices for (int i = 0; i < vertCount; i++) { line = "v " + vertices[i, 0] + " " + vertices[i, 1] + " " + vertices[i, 2]; l_List.Add(line); } // ... normals for (int i = 0; i < vertCount; i++) { line = "vn " + normals[i, 0] + " " + normals[i, 1] + " " + normals[i, 2]; l_List.Add(line); } // Schreibe Texture Vertice for (int i = 0; i < vertCount; i++) { line = "vt " + textures[i, 0] + " " + textures[i, 1]; l_List.Add(line); } line = "# " + vertCount + " vertices\n"; l_List.Add(line); line = "g " + meshGroup; l_List.Add(line); // Faces for (int i = 0; i < faceCount; i++) { line = "f " + (faces[i, 0] + 1) + "/" + (faces[i, 0] + 1) + "/" + (faces[i, 0] + 1) + " " + (faces[i, 1] + 1) + "/" + (faces[i, 1] + 1) + "/" + (faces[i, 1] + 1) + " " + (faces[i, 2] + 1) + "/" + (faces[i, 2] + 1) + "/" + (faces[i, 2] + 1); l_List.Add(line); } for (int i = 0; i < l_List.Count; i++) { // Convert all , to . l_List[i] = l_List[i].Replace(',', '.'); } File.WriteAllLines(output, l_List.ToArray()); } #endregion }
You can view OBJ file with Blender, or with this XNA Sample
XNA Sample:
You can find Models and Textures here:
Data.pk2/prim/mesh/ = MOdels
Data.pk2/prim/mtrl/ = Textures
To Convert a ddj file you need a HexEditor like XVI32
Then delete the first 20bytes and then save as *.dds
DDS can converted by "DDS Converter 2"
Many Models are saved in more then 1 *.bms file