public OBJGroup(string name, OBJGroup prev) : this() { Name = name; Prev = prev; PrevObj = prev as OBJObject ?? prev?.PrevObj; if (PrevObj != null && !(this is OBJObject)) { PrevObj.Groups.Add(this); } }
public static void ParseLineStandard(OBJParserStatus s, string line) { OBJObject o; string[] data = line.Split(' '); switch (data[0]) { case "mtllib": // Currently ignore material libraries. return; case "o": o = new OBJObject(line.Substring(2), s.Current); s.Data.Objects.Add(o); s.Current = o.Groups[0]; s.CurrentMaterial = ""; return; case "g": if (s.Data.Objects.Count == 0) { o = new OBJObject("", s.Current); s.Data.Objects.Add(o); s.Current = o.Groups[0]; s.Current.Name = line.Substring(2); } else { s.Current = new OBJGroup(line.Substring(2), s.Current); if (s.Current.PrevObj.Groups.Count == 2 && s.Current.PrevObj.Groups[0].Name == "") { s.Current.PrevObj.Groups.RemoveAt(0); } } s.CurrentMaterial = ""; return; case "v": s.Current.Vertices.Add(_ParseV3(data, 1)); return; case "vt": s.Current.UVs.Add(_ParseV2(data, 1)); return; case "vn": s.Current.Normals.Add(_ParseV3(data, 1)); return; case "usemtl": // Currently ignore material usages. s.Current.Materials.Add(line.Substring(7)); return; case "s": if (data[1] == "off") { // Currently ignore smoothing group disabling. } else { // Currently ignore smoothing group 1 - 32. } return; case "f": OBJGroup current = s.Current; if (4 <= data.Length && data.Length < 6) { int[] indices = new int[data.Length - 1]; for (int i = 0; i < indices.Length; i++) { string elem = data[i + 1]; int iV = 0; int iN = 0; int iUV = 0; if (elem.Contains("//")) { string[] parts = elem.Split('/'); iV = int.Parse(parts[0]); iN = int.Parse(parts[2]); } else if (_Count(elem, '/', 2)) { string[] parts = elem.Split('/'); iV = int.Parse(parts[0]); iUV = int.Parse(parts[1]); iN = int.Parse(parts[2]); } else if (!elem.Contains("/")) { iV = int.Parse(elem); } else { string[] parts = elem.Split('/'); iV = int.Parse(parts[0]); iUV = int.Parse(parts[1]); } string cacheKey = $"{iV}; {iN}; {iUV}"; int cacheValue; if (current.IndexCache.TryGetValue(cacheKey, out cacheValue)) { indices[i] = cacheValue; } else { cacheValue = current.IndexCache.Count; indices[i] = cacheValue; current.IndexCache[cacheKey] = cacheValue; if ((1 <= iV && iV <= current.Vertices.Count) || (iV < 0 && 1 <= (iV = iV + current.Vertices.Count + 1) && iV <= current.Vertices.Count)) { current.UVertices.Add(current.Vertices[iV - 1]); } else { current.UVertices.Add(Vector3.zero); } if ((1 <= iN && iN <= current.Normals.Count) || (iN < 0 && 1 <= (iN = iN + current.Normals.Count + 1) && iN <= current.Normals.Count)) { current.ContainsNormals = true; current.UNormals.Add(current.Normals[iN - 1]); } else { current.UNormals.Add(Vector3.zero); } if ((1 <= iUV && iUV <= current.UVs.Count) || (iUV < 0 && 1 <= (iUV = iUV + current.UVs.Count + 1) && iUV <= current.UVs.Count)) { current.UUVs.Add(current.UVs[iUV - 1]); } else { current.UUVs.Add(Vector2.zero); } } } OBJFace face = new OBJFace(); face.IndexMap = OBJFace.DefaultIndexMap; face.RawIndices = indices; face.Material = s.CurrentMaterial; s.Current.AddFace(face); if (indices.Length > 3) { face = new OBJFace(); face.IndexMap = OBJFace.SecondaryIndexMap; face.RawIndices = indices; face.Material = s.CurrentMaterial; s.Current.AddFace(face); } } return; } }