public static async Task <ObjMesh> Load(string definition) { var that = new ObjMesh(); var lines = definition .Split('\n') .Where(l => l.Length > 0 && l[0] != '#') .Select(l => l.Split(' ')); foreach (var line in lines) { await AsyncExtensions.WaitMoment(); var lineType = line[0]; switch (lineType) { case "mtllib": // material library: mtllib joint.mtl // ignore break; case "o": // object: o Cylinder006 // ignore break; case "v": // geometric vertex: v 3.2e-3 -1.4e-10 -5.8e-2 that.GeometryVertices.Add(Parse3DCoords(line)); break; case "vt": // texture vertex: vt 0.2 0.7 that.TextureVertices.Add(ParseUvCoords(line)); break; case "vn": // vertex normal: vn 0.9 -5.3e-9 -6.3e-2 that.VertexNormals.Add(Parse3DCoords(line)); break; case "g": // group name: g Cylinder006_CA_MISC // ignore break; case "usemtl": // material name: usemtl CA_MISC // ignore for now break; case "s": // smoothing group: s 1 // ignore for now break; case "f": // face: f 18/9/26 25/7/61 17/5/19 // entry: geometric vertex id / texture vertex id / vertex normal id var indices = line .Skip(1) .SelectMany(entry => entry.Split('/')) .Select(s => s.Length > 0 ? (int.Parse(s) - 1) : (int?)null) .ToArray(); Debug.Assert(indices.Length == 9); that.VertexComponentIds.AddRange(indices); break; default: throw new ArgumentException($"unsupported obj format entry: {line}", nameof(definition)); } } Debug.Assert(that.VertexComponentIds.Count % 9 == 0); // three vertices for geometry, tex and normals return(that); }