public OBJGroup Build(List <OBJMaterial> materials) { Mesh mesh = new Mesh(); mesh.name = this.meshName; mesh.vertices = vertices.ToArray(); mesh.uv = uv.ToArray(); if (this.normals.Count > 0) { mesh.normals = normals.ToArray(); } mesh.triangles = triangles.ToArray(); if (this.normals.Count <= 0) { mesh.RecalculateNormals(); } mesh.RecalculateBounds(); var group = new OBJGroup(this.meshName, mesh); if (materials != null) { group.material = materials.Find((mat) => mat.name == this.mtlName); } return(group); }
//------------------------------------------------------------------------------------------------------------ public static OBJData EncodeOBJ(this Mesh lMesh) { OBJData lData = new OBJData { m_Vertices = new List <Vector3>(lMesh.vertices), m_UVs = new List <Vector2>(lMesh.uv), m_Normals = new List <Vector3>(lMesh.normals), m_UV2s = new List <Vector2>(lMesh.uv2), m_Colors = new List <Color>(lMesh.colors) }; int[] lIndices = null; OBJGroup lGroup = null; OBJFace lFace = null; OBJFaceVertex lFaceVertex = null; for (int lMCount = 0; lMCount < lMesh.subMeshCount; ++lMCount) { lIndices = lMesh.GetTriangles(lMCount); lGroup = new OBJGroup(lMesh.name + "_" + lMCount.ToString()); for (int lCount = 0; lCount < lIndices.Length; lCount += 3) { lFace = new OBJFace(); lFaceVertex = new OBJFaceVertex(); lFaceVertex.m_VertexIndex = lData.m_Vertices.Count > 0 ? lIndices[lCount] : -1; lFaceVertex.m_UVIndex = lData.m_UVs.Count > 0 ? lIndices[lCount] : -1; lFaceVertex.m_NormalIndex = lData.m_Normals.Count > 0 ? lIndices[lCount] : -1; lFaceVertex.m_UV2Index = lData.m_UV2s.Count > 0 ? lIndices[lCount] : -1; lFaceVertex.m_ColorIndex = lData.m_Colors.Count > 0 ? lIndices[lCount] : -1; lFace.AddVertex(lFaceVertex); lFaceVertex = new OBJFaceVertex(); lFaceVertex.m_VertexIndex = lData.m_Vertices.Count > 0 ? lIndices[lCount + 1] : -1; lFaceVertex.m_UVIndex = lData.m_UVs.Count > 0 ? lIndices[lCount + 1] : -1; lFaceVertex.m_NormalIndex = lData.m_Normals.Count > 0 ? lIndices[lCount + 1] : -1; lFaceVertex.m_UV2Index = lData.m_UV2s.Count > 0 ? lIndices[lCount + 1] : -1; lFaceVertex.m_ColorIndex = lData.m_Colors.Count > 0 ? lIndices[lCount + 1] : -1; lFace.AddVertex(lFaceVertex); lFaceVertex = new OBJFaceVertex(); lFaceVertex.m_VertexIndex = lData.m_Vertices.Count > 0 ? lIndices[lCount + 2] : -1; lFaceVertex.m_UVIndex = lData.m_UVs.Count > 0 ? lIndices[lCount + 2] : -1; lFaceVertex.m_NormalIndex = lData.m_Normals.Count > 0 ? lIndices[lCount + 2] : -1; lFaceVertex.m_UV2Index = lData.m_UV2s.Count > 0 ? lIndices[lCount + 2] : -1; lFaceVertex.m_ColorIndex = lData.m_Colors.Count > 0 ? lIndices[lCount + 2] : -1; lFace.AddVertex(lFaceVertex); lGroup.AddFace(lFace); } lData.m_Groups.Add(lGroup); } return(lData); }
//------------------------------------------------------------------------------------------------------------ public static OBJData LoadOBJ(Stream lStream) { m_OBJData = new OBJData(); m_CurrentMaterial = null; m_CurrentGroup = null; StreamReader lLineStreamReader = new StreamReader(lStream); Action <string> lAction = null; string lCurrentLine = null; string[] lFields = null; string lKeyword = null; string lData = null; while (!lLineStreamReader.EndOfStream) { lCurrentLine = lLineStreamReader.ReadLine(); if (StringExt.IsNullOrWhiteSpace(lCurrentLine) || lCurrentLine[0] == '#') { continue; } lFields = lCurrentLine.Trim().Split(null, 2); if (lFields.Length < 2) { continue; } lKeyword = lFields[0].Trim(); lData = lFields[1].Trim(); lAction = null; m_ParseOBJActionDictionary.TryGetValue(lKeyword.ToLowerInvariant(), out lAction); if (lAction != null) { lAction(lData); } } Debug.Log("reached"); var lOBJData = m_OBJData; m_OBJData = null; return(lOBJData); }
//------------------------------------------------------------------------------------------------------------ public static void LoadOBJ(this Mesh lMesh, OBJData lData) { List <Vector3> lVertices = new List <Vector3>(); List <Vector3> lNormals = new List <Vector3>(); List <Vector2> lUVs = new List <Vector2>(); List <int>[] lIndices = new List <int> [lData.m_Groups.Count]; OBJGroup lGroup = null; lMesh.subMeshCount = lData.m_Groups.Count; for (int lGCount = 0; lGCount < lData.m_Groups.Count; ++lGCount) { lGroup = lData.m_Groups[lGCount]; lIndices[lGCount] = new List <int>(); for (int lFCount = 0; lFCount < lGroup.Faces.Count; ++lFCount) { for (int lVCount = 0; lVCount < lGroup.Faces[lFCount].Count; ++lVCount) { if (lGroup.Faces[lFCount][lVCount].m_VertexIndex < lData.m_Vertices.Count) { lIndices[lGCount].Add(lVertices.Count); lVertices.Add(lData.m_Vertices[lGroup.Faces[lFCount][lVCount].m_VertexIndex]); if (lGroup.Faces[lFCount][lVCount].m_UVIndex >= 0) { lUVs.Add(lData.m_UVs[lGroup.Faces[lFCount][lVCount].m_UVIndex]); } if (lGroup.Faces[lFCount][lVCount].m_NormalIndex >= 0) { lNormals.Add(lData.m_Normals[lGroup.Faces[lFCount][lVCount].m_NormalIndex]); } } } } } lMesh.vertices = lVertices.ToArray(); lMesh.uv = lUVs.ToArray(); lMesh.normals = lNormals.ToArray(); lMesh.RecalculateTangents(); for (int lGCount = 0; lGCount < lData.m_Groups.Count; ++lGCount) { lMesh.SetTriangles(lIndices[lGCount].ToArray(), lGCount); } }
//------------------------------------------------------------------------------------------------------------ public static OBJData LoadOBJ(Stream lStream) { m_OBJData = new OBJData(); m_CurrentMaterial = null; m_CurrentGroup = null; StreamReader lLineStreamReader = new StreamReader(lStream); Action<string> lAction = null; string lCurrentLine = null; string[] lFields = null; string lKeyword = null; string lData = null; while (!lLineStreamReader.EndOfStream) { lCurrentLine = lLineStreamReader.ReadLine(); if (StringExt.IsNullOrWhiteSpace(lCurrentLine) || lCurrentLine[0] == '#') { continue; } lFields = lCurrentLine.Trim().Split(null, 2); if (lFields.Length < 2) { continue; } lKeyword = lFields[0].Trim(); lData = lFields[1].Trim(); lAction = null; m_ParseOBJActionDictionary.TryGetValue(lKeyword.ToLowerInvariant(), out lAction); if (lAction != null) { lAction(lData); } } var lOBJData = m_OBJData; m_OBJData = null; return lOBJData; }
public void Read(string fname) { string input = File.ReadAllText(fname); RegexOptions options = RegexOptions.None; Regex regex = new Regex("[ ]{2,}", options); input = regex.Replace(input, " "); string[] lines = input.Split('\n'); Vector3 v; OBJObject o = null; OBJGroup g = null; for (int i = 0; i < lines.Length; i++) { string[] args = lines[i].Split(' '); switch (args[0]) { case "v": if (o == null) { o = new OBJObject(); g = new OBJGroup(); o.groups.Add(g); objects.Add(o); } v = new Vector3(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3])); this.v.Add(v); break; case "vn": v = new Vector3(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3])); vn.Add(v); break; case "vt": vt.Add(new Vector2(float.Parse(args[1]), float.Parse(args[2]))); break; case "f": g.v.Add(int.Parse(args[1].Split('/')[0]) - 1); g.v.Add(int.Parse(args[2].Split('/')[0]) - 1); g.v.Add(int.Parse(args[3].Split('/')[0]) - 1); if (args[1].Split('/').Length > 1) { g.vt.Add(int.Parse(args[1].Split('/')[1]) - 1); g.vt.Add(int.Parse(args[2].Split('/')[1]) - 1); g.vt.Add(int.Parse(args[3].Split('/')[1]) - 1); } if (args[1].Split('/').Length > 2) { g.vn.Add(int.Parse(args[1].Split('/')[2]) - 1); g.vn.Add(int.Parse(args[2].Split('/')[2]) - 1); g.vn.Add(int.Parse(args[3].Split('/')[2]) - 1); } break; case "o": o = new OBJObject(); o.name = args[1]; objects.Add(o); g = new OBJGroup(); o.groups.Add(g); break; case "g": g = new OBJGroup(); if (o == null || args.Length > 1) { o = new OBJObject(); if (args.Length > 1) { o.name = args[1]; } objects.Add(o); } o.groups.Add(g); break; } } }
//------------------------------------------------------------------------------------------------------------ private static void PushOBJGroup(string lGroupName) { m_CurrentGroup = new OBJGroup(lGroupName); m_OBJData.m_Groups.Add(m_CurrentGroup); }
//------------------------------------------------------------------------------------------------------------ public static void LoadOBJ(this Mesh lMesh, OBJData lData) { List <Vector3> lVertices = new List <Vector3>(); List <Vector3> lNormals = new List <Vector3>(); List <Vector2> lUVs = new List <Vector2>(); List <int>[] lIndices = new List <int> [lData.m_Groups.Count]; Dictionary <OBJFaceVertex, int> lVertexIndexRemap = new Dictionary <OBJFaceVertex, int>(); bool lHasNormals = lData.m_Normals.Count > 0; bool lHasUVs = lData.m_UVs.Count > 0; lMesh.subMeshCount = lData.m_Groups.Count; for (int lGCount = 0; lGCount < lData.m_Groups.Count; ++lGCount) { OBJGroup lGroup = lData.m_Groups[lGCount]; lIndices[lGCount] = new List <int>(); for (int lFCount = 0; lFCount < lGroup.Faces.Count; ++lFCount) { OBJFace lFace = lGroup.Faces[lFCount]; // Unity3d doesn't support non-triangle faces // so we do simple fan triangulation for (int lVCount = 1; lVCount < lFace.Count - 1; ++lVCount) { foreach (int i in new int[] { 0, lVCount, lVCount + 1 }) { OBJFaceVertex lFaceVertex = lFace[i]; int lVertexIndex = -1; if (!lVertexIndexRemap.TryGetValue(lFaceVertex, out lVertexIndex)) { lVertexIndexRemap[lFaceVertex] = lVertices.Count; lVertexIndex = lVertices.Count; lVertices.Add(lData.m_Vertices[lFaceVertex.m_VertexIndex]); if (lHasUVs) { lUVs.Add(lData.m_UVs[lFaceVertex.m_UVIndex]); } if (lHasNormals) { lNormals.Add(lData.m_Normals[lFaceVertex.m_NormalIndex]); } } lIndices[lGCount].Add(lVertexIndex); } } } } lMesh.triangles = new int[] { }; lMesh.vertices = lVertices.ToArray(); lMesh.uv = lUVs.ToArray(); lMesh.normals = lNormals.ToArray(); if (!lHasNormals) { lMesh.RecalculateNormals(); } lMesh.RecalculateTangents(); for (int lGCount = 0; lGCount < lData.m_Groups.Count; ++lGCount) { lMesh.SetTriangles(lIndices[lGCount].ToArray(), lGCount); } }
//------------------------------------------------------------------------------------------------------------ public static OBJData EncodeOBJ(this Mesh lMesh) { OBJData lData = new OBJData { m_Vertices = new List<Vector3>(lMesh.vertices), m_UVs = new List<Vector2>(lMesh.uv), m_Normals = new List<Vector3>(lMesh.normals), m_UV2s = new List<Vector2>(lMesh.uv1), m_Colors = new List<Color>(lMesh.colors) }; int[] lIndices = null; OBJGroup lGroup = null; OBJFace lFace = null; OBJFaceVertex lFaceVertex = null; for (int lMCount = 0; lMCount < lMesh.subMeshCount; ++lMCount) { lIndices = lMesh.GetTriangles(lMCount); lGroup = new OBJGroup(lMesh.name + "_" + lMCount.ToString()); for (int lCount = 0; lCount < lIndices.Length; lCount += 3) { lFace = new OBJFace(); lFaceVertex = new OBJFaceVertex(); lFaceVertex.m_VertexIndex = lData.m_Vertices.Count > 0 ? lIndices[lCount] : -1; lFaceVertex.m_UVIndex = lData.m_UVs.Count > 0 ? lIndices[lCount] : -1; lFaceVertex.m_NormalIndex = lData.m_Normals.Count > 0 ? lIndices[lCount] : -1; lFaceVertex.m_UV2Index = lData.m_UV2s.Count > 0 ? lIndices[lCount] : -1; lFaceVertex.m_ColorIndex = lData.m_Colors.Count > 0 ? lIndices[lCount] : -1; lFace.AddVertex(lFaceVertex); lFaceVertex = new OBJFaceVertex(); lFaceVertex.m_VertexIndex = lData.m_Vertices.Count > 0 ? lIndices[lCount + 1] : -1; lFaceVertex.m_UVIndex = lData.m_UVs.Count > 0 ? lIndices[lCount + 1] : -1; lFaceVertex.m_NormalIndex = lData.m_Normals.Count > 0 ? lIndices[lCount + 1] : -1; lFaceVertex.m_UV2Index = lData.m_UV2s.Count > 0 ? lIndices[lCount + 1] : -1; lFaceVertex.m_ColorIndex = lData.m_Colors.Count > 0 ? lIndices[lCount + 1] : -1; lFace.AddVertex(lFaceVertex); lFaceVertex = new OBJFaceVertex(); lFaceVertex.m_VertexIndex = lData.m_Vertices.Count > 0 ? lIndices[lCount + 2] : -1; lFaceVertex.m_UVIndex = lData.m_UVs.Count > 0 ? lIndices[lCount + 2] : -1; lFaceVertex.m_NormalIndex = lData.m_Normals.Count > 0 ? lIndices[lCount + 2] : -1; lFaceVertex.m_UV2Index = lData.m_UV2s.Count > 0 ? lIndices[lCount + 2] : -1; lFaceVertex.m_ColorIndex = lData.m_Colors.Count > 0 ? lIndices[lCount + 2] : -1; lFace.AddVertex(lFaceVertex); lGroup.AddFace(lFace); } lData.m_Groups.Add(lGroup); } return lData; }
public void Parse(TextReader reader) { // For each line: string line; var whitespace = new char[] { ' ', '\t' }; var slash = new char[] { '/' }; OBJGroup currentGroup = null; while ((line = reader.ReadLine()) != null) { // Strip comment var commentIdx = line.IndexOf('#'); if (commentIdx >= 0) { line = line.Substring(0, commentIdx); } // Segment var parts = line.Split(whitespace, StringSplitOptions.RemoveEmptyEntries); if (parts.Length == 0) { continue; } // Parse var type = parts[0].ToLowerInvariant(); switch (type) { case "mtllib": { var path = parts[1]; MTLLib = path; break; } case "o": case "g": { var name = parts[1]; currentGroup = new OBJGroup(name); Groups.Add(currentGroup); break; } case "v": { var x = float.Parse(parts[1], CultureInfo.InvariantCulture); var y = float.Parse(parts[2], CultureInfo.InvariantCulture); var z = float.Parse(parts[3], CultureInfo.InvariantCulture); Positions.Add(new Vector3(x, y, z)); if (parts.Length > 4) { var r = float.Parse(parts[4], CultureInfo.InvariantCulture); var g = float.Parse(parts[5], CultureInfo.InvariantCulture); var b = float.Parse(parts[6], CultureInfo.InvariantCulture); var a = (parts.Length > 7) ? float.Parse(parts[7], CultureInfo.InvariantCulture) : 1.0f; Colours.Add(new Vector4(r, g, b, a)); } else { Colours.Add(Vector4.One); } break; } case "vt": { var x = float.Parse(parts[1], CultureInfo.InvariantCulture); var y = float.Parse(parts[2], CultureInfo.InvariantCulture); TexCoords.Add(new Vector2(x, y)); break; } case "vn": { var x = float.Parse(parts[1], CultureInfo.InvariantCulture); var y = float.Parse(parts[2], CultureInfo.InvariantCulture); var z = float.Parse(parts[3], CultureInfo.InvariantCulture); Normals.Add(new Vector3(x, y, z)); break; } case "usemtl": { var name = parts[1]; currentGroup.MaterialName = name; break; } case "f": { var face = new OBJFace(); face.FirstVertex = Verts.Count; for (int i = 1; i < parts.Length; ++i) { var part = parts[i]; var subParts = part.Split(slash, StringSplitOptions.None); var vert = new OBJVert(); if (subParts.Length > 0) { int posIndex; if (int.TryParse(subParts[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out posIndex)) { vert.PositionIndex = posIndex; } } if (subParts.Length > 1) { int texCoordIndex; if (int.TryParse(subParts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out texCoordIndex)) { vert.TexCoordIndex = texCoordIndex; } } if (subParts.Length > 2) { int normalIndex; if (int.TryParse(subParts[2], NumberStyles.Integer, CultureInfo.InvariantCulture, out normalIndex)) { vert.NormalIndex = normalIndex; } } Verts.Add(vert); face.VertexCount++; } currentGroup.Faces.Add(face); break; } } } }