public static ObjFile FromFile(string fileName) { ObjFile obj = new ObjFile(); obj.FileName = fileName; using (StreamReader file = new StreamReader(fileName)) { string line; string materialName = null; ObjMesh mesh = new ObjMesh("unnamed"); obj.Meshes.Add(mesh); ObjFaceGroup faceGroup = new ObjFaceGroup(); mesh.FaceGroups.Add(faceGroup); while ((line = file.ReadLine()) != null) { if (string.IsNullOrWhiteSpace(line)) { continue; } line = line.Trim(); if (line.StartsWith("#", StringComparison.OrdinalIgnoreCase)) { continue; } string[] values = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); switch (values[0].ToUpperInvariant()) { case "MTLLIB": if (values.Length != 2) { throw new InvalidDataException("missing mtllib name"); } if (obj.Materials.Count > 0) { throw new InvalidDataException("multiple mtllib"); } obj.Materials = ObjMaterialDictionary.FromFile(Path.Combine(Path.GetDirectoryName(fileName), values[1])); break; case "V": if (values.Length < 4) { throw new InvalidDataException("v must be x y z"); } obj.Vertices.Add(new ObjVector3( float.Parse(values[1], CultureInfo.InvariantCulture), float.Parse(values[2], CultureInfo.InvariantCulture), float.Parse(values[3], CultureInfo.InvariantCulture))); break; case "VT": if (values.Length < 3) { throw new InvalidDataException("vt must be u v"); } obj.VertexTexCoords.Add(new ObjVector2( float.Parse(values[1], CultureInfo.InvariantCulture), float.Parse(values[2], CultureInfo.InvariantCulture))); break; case "VN": if (values.Length < 4) { throw new InvalidDataException("vn must be x y z"); } obj.VertexNormals.Add(new ObjVector3( float.Parse(values[1], CultureInfo.InvariantCulture), float.Parse(values[2], CultureInfo.InvariantCulture), float.Parse(values[3], CultureInfo.InvariantCulture))); break; case "O": case "G": if (values.Length < 2) { throw new InvalidDataException("missing object name"); } if (faceGroup.Faces.Count == 0) { mesh.Name = values[1]; } else { mesh = new ObjMesh(values[1]); obj.Meshes.Add(mesh); faceGroup = new ObjFaceGroup(); faceGroup.MaterialName = materialName; mesh.FaceGroups.Add(faceGroup); } break; case "USEMTL": if (values.Length != 2) { throw new InvalidDataException("missing material name"); } materialName = values[1]; if (faceGroup.Faces.Count == 0) { faceGroup.MaterialName = materialName; } else { faceGroup = new ObjFaceGroup(); faceGroup.MaterialName = materialName; mesh.FaceGroups.Add(faceGroup); } break; case "F": if (values.Length == 4) { var v1 = ParseFaceVertex(values[1]); var v2 = ParseFaceVertex(values[2]); var v3 = ParseFaceVertex(values[3]); var face = new ObjFace(); face.VerticesIndex = new ObjIndex(v1.Item1, v2.Item1, v3.Item1); face.VertexTexCoordsIndex = new ObjIndex(v1.Item2, v2.Item2, v3.Item2); face.VertexNormalsIndex = new ObjIndex(v1.Item3, v2.Item3, v3.Item3); faceGroup.Faces.Add(face); } else if (values.Length == 5) { var v1 = ParseFaceVertex(values[1]); var v2 = ParseFaceVertex(values[2]); var v3 = ParseFaceVertex(values[3]); var v4 = ParseFaceVertex(values[4]); var face = new ObjFace(); face.VerticesIndex = new ObjIndex(v1.Item1, v2.Item1, v3.Item1, v4.Item1); face.VertexTexCoordsIndex = new ObjIndex(v1.Item2, v2.Item2, v3.Item2, v4.Item2); face.VertexNormalsIndex = new ObjIndex(v1.Item3, v2.Item3, v3.Item3, v4.Item3); faceGroup.Faces.Add(face); } else { throw new InvalidDataException("invalid face"); } break; } } } return(obj); }
public static ObjFile FromFile(string fileName) { ObjFile obj = new ObjFile(); obj.FileName = fileName; using (StreamReader file = new StreamReader(fileName)) { string line; string materialName = null; ObjMesh mesh = new ObjMesh("unnamed"); obj.Meshes.Add(mesh); ObjFaceGroup faceGroup = new ObjFaceGroup(); mesh.FaceGroups.Add(faceGroup); while ((line = file.ReadLine()) != null) { if (string.IsNullOrWhiteSpace(line)) { continue; } line = line.Trim(); if (line.StartsWith("#", StringComparison.OrdinalIgnoreCase)) { continue; } string[] values = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); switch (values[0].ToUpperInvariant()) { case "MTLLIB": if (values.Length != 2) { throw new InvalidDataException("missing mtllib name"); } if (obj.Materials.Count > 0) { throw new InvalidDataException("multiple mtllib"); } obj.Materials = ObjMaterialDictionary.FromFile(Path.Combine(Path.GetDirectoryName(fileName), values[1])); break; case "V": if (values.Length < 4) { throw new InvalidDataException("v must be x y z"); } obj.Vertices.Add(new ObjVector3( float.Parse(values[1], CultureInfo.InvariantCulture), float.Parse(values[2], CultureInfo.InvariantCulture), float.Parse(values[3], CultureInfo.InvariantCulture))); break; case "VT": if (values.Length < 3) { throw new InvalidDataException("vt must be u v"); } obj.VertexTexCoords.Add(new ObjVector2( float.Parse(values[1], CultureInfo.InvariantCulture), float.Parse(values[2], CultureInfo.InvariantCulture))); break; case "VN": if (values.Length < 4) { throw new InvalidDataException("vn must be x y z"); } obj.VertexNormals.Add(new ObjVector3( float.Parse(values[1], CultureInfo.InvariantCulture), float.Parse(values[2], CultureInfo.InvariantCulture), float.Parse(values[3], CultureInfo.InvariantCulture))); break; case "O": case "G": if (values.Length < 2) { throw new InvalidDataException("missing object name"); } if (faceGroup.Faces.Count == 0) { mesh.Name = values[1]; } else { mesh = new ObjMesh(values[1]); obj.Meshes.Add(mesh); faceGroup = new ObjFaceGroup(); faceGroup.MaterialName = materialName; mesh.FaceGroups.Add(faceGroup); } break; case "USEMTL": if (values.Length != 2) { throw new InvalidDataException("missing material name"); } materialName = values[1]; if (faceGroup.Faces.Count == 0) { faceGroup.MaterialName = materialName; } else { faceGroup = new ObjFaceGroup(); faceGroup.MaterialName = materialName; mesh.FaceGroups.Add(faceGroup); } break; case "F": if (values.Length == 4) { var v1 = ParseFaceVertex(values[1]); var v2 = ParseFaceVertex(values[2]); var v3 = ParseFaceVertex(values[3]); var face = new ObjFace(); face.VerticesIndex = new ObjIndex(v1.Item1, v2.Item1, v3.Item1); face.VertexTexCoordsIndex = new ObjIndex(v1.Item2, v2.Item2, v3.Item2); face.VertexNormalsIndex = new ObjIndex(v1.Item3, v2.Item3, v3.Item3); faceGroup.Faces.Add(face); } else if (values.Length == 5) { var v1 = ParseFaceVertex(values[1]); var v2 = ParseFaceVertex(values[2]); var v3 = ParseFaceVertex(values[3]); var v4 = ParseFaceVertex(values[4]); var face = new ObjFace(); face.VerticesIndex = new ObjIndex(v1.Item1, v2.Item1, v3.Item1, v4.Item1); face.VertexTexCoordsIndex = new ObjIndex(v1.Item2, v2.Item2, v3.Item2, v4.Item2); face.VertexNormalsIndex = new ObjIndex(v1.Item3, v2.Item3, v3.Item3, v4.Item3); faceGroup.Faces.Add(face); } else { throw new InvalidDataException("invalid face"); } break; } } } return obj; }