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






