public class OBJImporter { public class ObjSurface { public List uvcoords; public List indexList; public string name; public ObjSurface() { uvcoords = new List(); indexList = new List(); } } public static ModelObject Load(GraphicsDevice Device) { StreamReader reader = new StreamReader("belltower.obj"); List objSurfaces = new List(); ObjSurface currentSurface = new ObjSurface(); bool hasSurface = false; List verticies = new List(); List uvcoords = new List(); int indCount = 0; // total number of indicies while (!reader.EndOfStream) { string line = reader.ReadLine(); line = line.Trim(); if (line.Length < 1) continue; switch (line[0]) { case 'o': // object name break; case 'v': // vertex if (line[1] == 't') // uv coord { string data = line.Substring(3); string[] values = data.Split(' '); Vector2 coord = new Vector2(float.Parse(values[0]), float.Parse(values[1])); currentSurface.uvcoords.Add(coord); uvcoords.Add(coord); } else { string data = line.Substring(2); string[] values = data.Split(' '); Vector3 vert = new Vector3(float.Parse(values[0]), float.Parse(values[1]), float.Parse(values[2])); verticies.Add(vert); } break; case 'f': // face string fData = line.Substring(2); string[] fValues = fData.Split(' '); for (int i = 0; i < fValues.Length; i++) { string[] index = fValues[i].Split('/'); currentSurface.indexList.Add(int.Parse(index[0])); indCount++; } break; case 'u': // assume usemtl option string surfaceName = line.Substring(7); if (hasSurface) objSurfaces.Add(currentSurface); currentSurface = new ObjSurface(); currentSurface.name = surfaceName; hasSurface = true; //Console.WriteLine(surfaceName); break; } } reader.Close(); foreach (ObjSurface objSurf in objSurfaces) Console.WriteLine("Surface: " + objSurf.name + ", UVs: " + objSurf.uvcoords.Count + ", Indicies: " + objSurf.indexList.Count); VertexPositionTexture[] vpt = new VertexPositionTexture[verticies.Count]; for(int i = 0; i < verticies.Count; i++) { vpt[i] = new VertexPositionTexture(verticies[i], uvcoords[i]); } ModelObject modelObject = new ModelObject(); ModelSurface surface = new ModelSurface(); VertexBuffer vertexBuffer = new VertexBuffer(Device, VertexPositionTexture.SizeInBytes * verticies.Count, ResourceUsage.None, ResourceManagementMode.Automatic); vertexBuffer.SetData(vpt); surface.VertexBuffer = vertexBuffer; short[] indicies = new short[indCount]; int currentInd = 0; for (int s = 0; s < objSurfaces.Count; s++) { for (int i = 0; i < objSurfaces[s].indexList.Count; i++) { indicies[currentInd] = (short)(objSurfaces[s].indexList[i] - 1); currentInd++; } } surface.IndexBuffer = new IndexBuffer(Device, typeof(short), indCount, ResourceUsage.None, ResourceManagementMode.Automatic); surface.IndexBuffer.SetData(indicies); int baseVert = 0; foreach (ObjSurface objSurf in objSurfaces) { ModelSurfacePart part = new ModelSurfacePart(); part.BaseVertex = 0; part.NumVertices = objSurf.indexList.Count; part.PrimitiveCount = objSurf.indexList.Count / 3; part.StartIndex = baseVert; part.StreamOffset = 0; part.VertexDeclaration = new VertexDeclaration(Device, VertexPositionTexture.VertexElements); part.VertexStride = VertexPositionTexture.SizeInBytes; baseVert += objSurf.indexList.Count; if (File.Exists(objSurf.name + ".tga")) { part.texture = Texture2D.FromFile(Device, objSurf.name + ".tga"); part.hasTexture = true; } else part.hasTexture = false; surface.SurfaceParts.Add(part); } modelObject.Surfaces.Add(surface); return modelObject; } }