/// <summary> /// /// </summary> /// <param name="inputFile"></param> /// <param name="encoding">default utf-8</param> /// <returns></returns> public static ObjModel Parse(string inputFile, Encoding encoding = null) { encoding = encoding ?? TextParser.DefaultEncoding; // https://stackoverflow.com/questions/2161895/reading-large-text-files-with-streams-in-c-sharp using (var fs = new FileStream(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var bs = new BufferedStream(fs)) using (var sr = new StreamReader(bs, encoding)) { var nameBuilder = new StringBuilder(); var model = new ObjModel(); var groupBuilder = model.GetMapBuilder("default"); var objectBuilder = model.GetMapBuilder("default"); var meshBuilder = model.GetMapBuilder(""); TextParser.Lex(sr, (key, args) => { switch (key) { case "mtllib": model.MaterialLibaries.AddRange(args); break; case "v": args = TextParser.ParseArgs(args); model.Positions.Add(ParsePoint(args)); break; case "vt": args = TextParser.ParseArgs(args); model.TextureCoords.Add(ParseUv(args)); break; case "vn": args = TextParser.ParseArgs(args); model.Normals.Add(ParseNormal(args)); break; case "vp": break; case "p": args = TextParser.ParseArgs(args); foreach (var a in args) { var index = FindIndex(model.Positions, a); model.Points.Add(index); } break; case "l": args = TextParser.ParseArgs(args); FillLineSegments(model, args); break; case "fo": case "f": args = TextParser.ParseArgs(args); FillPolygon(model, args); break; case "g": args = TextParser.ParseArgs(args); groupBuilder.Start(args[0]); break; case "o": args = TextParser.ParseArgs(args); objectBuilder.Start(args[0]); if (String.IsNullOrEmpty(model.Name)) { model.Name = args[0]; } break; case "usemtl": meshBuilder.Start(args[0]); break; } }); objectBuilder.End(); groupBuilder.End(); meshBuilder.End(); model.Objects = objectBuilder.Result; model.Groups = groupBuilder.Result; model.Meshes = meshBuilder.Result; return(model); } }
/// <summary> /// /// </summary> /// <param name="inputFile"></param> /// <param name="encoding">default utf-8</param> /// <returns></returns> public static MtlModel Parse(string inputFile, Encoding encoding = null) { encoding = encoding ?? TextParser.DefaultEncoding; using (var fs = new FileStream(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var bs = new BufferedStream(fs)) using (var sr = new StreamReader(bs, encoding)) { var model = new MtlModel(); string name = null; var mat = new Material(); TextParser.Lex(sr, (key, args) => { switch (key) { case "newmtl": if (!String.IsNullOrEmpty(name)) { model.Materials.Add(name, mat); mat = new Material(); } name = args[0]; break; case "Ka": mat.Ambient = ParseColor(args); break; case "Kd": mat.Diffuse = ParseColor(args); break; case "Ks": mat.Specular = ParseColor(args); break; case "Ke": mat.Emissive = ParseColor(args); break; case "Tf": mat.TransmissionFilter = ParseColor(args); break; case "Ns": if (float.TryParse(args[0], out var ns)) { mat.SpecularExponent = ns; } break; case "Ni": if (float.TryParse(args[0], out var ni)) { mat.OpticalDensity = ni; } break; case "illum": if (uint.TryParse(args[0], out var illum)) { mat.Illumination = illum; } break; case "d": if (float.TryParse(args[0], out var d)) { mat.Dissolve = d; } break; case "map_Ka": mat.AmbientMap = ParseMap(args); break; case "map_Kd": mat.DiffuseMap = ParseMap(args); break; case "map_Ks": mat.SpecularMap = ParseMap(args); break; case "map_Ke": mat.EmissiveMap = ParseMap(args); break; case "bump": case "map_bump": case "map_Bump": mat.BumpMap = ParseMap(args); break; } }); if (!String.IsNullOrEmpty(name)) { model.Materials.Add(name, mat); } return(model); } }