public ObjLoader(string filename, ShaderProgram program) { Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; this.defaultProgram = program; System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew(); ObjMaterial defaultMaterial = new ObjMaterial(program); using (StreamReader stream = new StreamReader(filename)) { List<string> lines = new List<string>(); int vertexOffset = 1, vertexCount = 0; int uvOffset = 1, uvCount = 0; // read the entire file while (!stream.EndOfStream) { string line = stream.ReadLine(); if (line.Trim().Length == 0) continue; if ((line[0] == 'o' || line[0] == 'g') && lines.Count != 0) { ObjObject newObject = new ObjObject(lines, materials, vertexOffset, uvOffset); if (vertexCount != 0) objects.Add(newObject); if (newObject.Material == null) newObject.Material = defaultMaterial; lines.Clear(); vertexOffset += vertexCount; uvOffset += uvCount; vertexCount = 0; uvCount = 0; } if (line[0] != '#') lines.Add(line); if (line[0] == 'v') { if (line[1] == ' ') vertexCount++; else uvCount++; } // check if a material file is being used if (line[0] == 'm' && line[1] == 't') LoadMaterials(CreateFixedPath(filename, line.Split(' ')[1])); } // make sure we grab any remaining objects that occured before the EOF if (lines != null) objects.Add(new ObjObject(lines, materials, vertexOffset, uvOffset)); } watch.Stop(); Console.WriteLine("Took {0}ms", watch.ElapsedMilliseconds); }
private void LoadMaterials(string filename) { using (StreamReader stream = new StreamReader(filename)) { List<string> lines = new List<string>(); while (!stream.EndOfStream) { string line = stream.ReadLine(); if (line.Trim().Length == 0) continue; if (line[0] == 'n' && lines.Count != 0) { // if this is a new material ('newmtl name') then load it ObjMaterial material = new ObjMaterial(lines, defaultProgram); if (!materials.ContainsKey(material.Name)) materials.Add(material.Name, material); lines.Clear(); } if (line[0] == 'm') { // try to fix up filenames of texture maps string[] split = line.Split(' '); lines.Add(string.Format("{0} {1}", split[0], CreateFixedPath(filename, split[1]))); } else if (line[0] != '#') lines.Add(line); // ignore comments } // If the obj has just one material would not execute the ObjMaterial function up, so I added (if the there are lines still not processed, process them) if (lines.Count != 0) { ObjMaterial materialEnd = new ObjMaterial(lines, defaultProgram); if (!materials.ContainsKey(materialEnd.Name)) materials.Add(materialEnd.Name, materialEnd); lines.Clear(); } } }
public ObjObject(List <string> lines, Dictionary <string, ObjMaterial> materials, int vertexOffset, int uvOffset) { // we need at least 1 line to be a valid file if (lines.Count == 0) { return; } // the first line should contain 'o' if (lines[0][0] != 'o' && lines[0][0] != 'g') { return; } this.Name = lines[0].Substring(2); List <Vector3> vertexList = new List <Vector3>(); List <Vector2> uvList = new List <Vector2>(); List <int> triangleList = new List <int>(); List <Vector2> unpackedUvs = new List <Vector2>(); List <int> normalsList = new List <int>(); // now we read the lines for (int i = 1; i < lines.Count; i++) { string[] split = lines[i].Split(' '); switch (split[0]) { case "v": vertexList.Add(new Vector3(double.Parse(split[1]), double.Parse(split[2]), double.Parse(split[3])) * 0.025f); break; case "vt": uvList.Add(new Vector2(double.Parse(split[1]), double.Parse(split[2]))); break; case "f": string[] indices = new string[] { split[1], split[2], split[3] }; if (split[1].Contains("/")) { indices[0] = split[1].Substring(0, split[1].IndexOf("/")); indices[1] = split[2].Substring(0, split[2].IndexOf("/")); indices[2] = split[3].Substring(0, split[3].IndexOf("/")); string[] uvs = new string[3]; uvs[0] = split[1].Substring(split[1].IndexOf("/") + 1); uvs[1] = split[2].Substring(split[2].IndexOf("/") + 1); uvs[2] = split[3].Substring(split[3].IndexOf("/") + 1); int[] triangle = new int[] { int.Parse(indices[0]) - vertexOffset, int.Parse(indices[1]) - vertexOffset, int.Parse(indices[2]) - vertexOffset }; if (unpackedUvs.Count == 0) { for (int j = 0; j < vertexList.Count; j++) { unpackedUvs.Add(Vector2.Zero); } } normalsList.Add(triangle[0]); normalsList.Add(triangle[1]); normalsList.Add(triangle[2]); if (unpackedUvs[triangle[0]] == Vector2.Zero) { unpackedUvs[triangle[0]] = uvList[int.Parse(uvs[0]) - uvOffset]; } else { unpackedUvs.Add(uvList[int.Parse(uvs[0]) - uvOffset]); vertexList.Add(vertexList[triangle[0]]); triangle[0] = unpackedUvs.Count - 1; } if (unpackedUvs[triangle[1]] == Vector2.Zero) { unpackedUvs[triangle[1]] = uvList[int.Parse(uvs[1]) - uvOffset]; } else { unpackedUvs.Add(uvList[int.Parse(uvs[1]) - uvOffset]); vertexList.Add(vertexList[triangle[1]]); triangle[1] = unpackedUvs.Count - 1; } if (unpackedUvs[triangle[2]] == Vector2.Zero) { unpackedUvs[triangle[2]] = uvList[int.Parse(uvs[2]) - uvOffset]; } else { unpackedUvs.Add(uvList[int.Parse(uvs[2]) - uvOffset]); vertexList.Add(vertexList[triangle[2]]); triangle[2] = unpackedUvs.Count - 1; } triangleList.Add(triangle[0]); triangleList.Add(triangle[1]); triangleList.Add(triangle[2]); } else { triangleList.Add(int.Parse(indices[0]) - vertexOffset); triangleList.Add(int.Parse(indices[1]) - vertexOffset); triangleList.Add(int.Parse(indices[2]) - vertexOffset); } break; case "usemtl": if (materials.ContainsKey(split[1])) { Material = materials[split[1]]; } break; } } // calculate the normals (if they didn't exist) Vector3[] vertexData = vertexList.ToArray(); int[] elementData = triangleList.ToArray(); Vector3[] normalData = CalculateNormals(vertexData, elementData); // now convert the lists over to vertex buffer objects to be rendered by OpenGL this.vertices = new VBO <Vector3>(vertexData); this.normals = new VBO <Vector3>(normalData); if (unpackedUvs.Count != 0) { this.uvs = new VBO <Vector2>(unpackedUvs.ToArray()); } this.triangles = new VBO <int>(elementData, BufferTarget.ElementArrayBuffer); }
public ObjLoader(string filename, ShaderProgram program) { this.defaultProgram = program; System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew(); ObjMaterial defaultMaterial = new ObjMaterial(program); using (StreamReader stream = new StreamReader(filename)) { List <string> lines = new List <string>(); int vertexOffset = 1, vertexCount = 0; int uvOffset = 1, uvCount = 0; // read the entire file while (!stream.EndOfStream) { string line = stream.ReadLine(); if (line.Trim().Length == 0) { continue; } if ((line[0] == 'o' || line[0] == 'g') && lines.Count != 0) { ObjObject newObject = new ObjObject(lines, materials, vertexOffset, uvOffset); objects.Add(newObject); if (newObject.Material == null) { newObject.Material = defaultMaterial; } lines.Clear(); vertexOffset += vertexCount; uvOffset += uvCount; vertexCount = 0; uvCount = 0; } if (line[0] != '#') { lines.Add(line); } if (line[0] == 'v') { if (line[1] == ' ') { vertexCount++; } else { uvCount++; } } // check if a material file is being used if (line[0] == 'm' && line[1] == 't') { LoadMaterials(CreateFixedPath(filename, line.Split(' ')[1])); } } } watch.Stop(); Console.WriteLine("Took {0}ms", watch.ElapsedMilliseconds); }
public ObjLoader(string filename, ShaderProgram program) { Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; this.defaultProgram = program; System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew(); ObjMaterial defaultMaterial = new ObjMaterial(program); using (StreamReader stream = new StreamReader(filename)) { List <string> lines = new List <string>(); List <string> objLines = new List <string>(); int vertexOffset = 1, vertexCount = 0; int uvOffset = 1, uvCount = 0; // read the entire file while (!stream.EndOfStream) { string line = stream.ReadLine(); if (line.Trim().Length == 0) { continue; } if ((line[0] == 'o' && lines.Count != 0) || (line[0] == 'g' && objLines.Count != 0)) { List <string> combinedLines = new List <string>(objLines); combinedLines.AddRange(lines); ObjObject newObject = new ObjObject(combinedLines, materials, vertexOffset, uvOffset); if (newObject.VertexCount != 0) { objects.Add(newObject); } if (newObject.Material == null) { newObject.Material = defaultMaterial; } lines.Clear(); if (line[0] == 'o') { objLines.Clear(); vertexOffset += vertexCount; uvOffset += uvCount; vertexCount = 0; uvCount = 0; } } if (line[0] == 'v') { if (line[1] == ' ') { vertexCount++; } else { uvCount++; } objLines.Add(line); } else if (line[0] != '#') { lines.Add(line); } // check if a material file is being used if (line[0] == 'm' && line[1] == 't') { LoadMaterials(CreateFixedPath(filename, line.Split(' ')[1])); } } // make sure we grab any remaining objects that occured before the EOF if (lines != null) { List <string> combinedLines = new List <string>(objLines); combinedLines.AddRange(lines); ObjObject newObject = new ObjObject(combinedLines, materials, vertexOffset, uvOffset); objects.Add(newObject); } } watch.Stop(); Console.WriteLine("Took {0}ms", watch.ElapsedMilliseconds); }