private vec3[] ArrangeNormals(ObjVNFContext context) { var normals = new vec3[context.vertexCount]; ObjVNFMesh mesh = context.Mesh; for (int i = 0; i < context.faceCount; i++) { ObjVNFFace face = mesh.faces[i]; uint[] normalIndexes = (from item in face.NormalIndexes() select item).ToArray(); uint[] vertexIndexes = (from item in face.VertexIndexes() select item).ToArray(); if (normalIndexes.Length != vertexIndexes.Length) { throw new Exception(string.Format( "normalIndexes.Length [{0}] != vertexIndexes.Length [{1}]!", normalIndexes.Length, vertexIndexes.Length)); } for (int t = 0; t < vertexIndexes.Length; t++) { normals[vertexIndexes[t]] = mesh.normals[normalIndexes[t]]; } } return(normals); }
private ObjVNFFace ParseFace(string[] parts) { ObjVNFFace result = null; if (parts.Length == 4)// f 1 2 3 { uint v0, v1, v2, n0, n1, n2, t0, t1, t2; ParseFaceUnit(parts[1], out v0, out n0, out t0); ParseFaceUnit(parts[2], out v1, out n1, out t1); ParseFaceUnit(parts[3], out v2, out n2, out t2); // index in obj files starts with 1. result = new ObjVNFTriangle(v0 - 1, v1 - 1, v2 - 1, n0 - 1, n1 - 1, n2 - 1, t0 - 1, t1 - 1, t2 - 1); } else if (parts.Length == 5)// f 1 2 3 4 { uint v0, v1, v2, v3, n0, n1, n2, n3, t0, t1, t2, t3; ParseFaceUnit(parts[1], out v0, out n0, out t0); ParseFaceUnit(parts[2], out v1, out n1, out t1); ParseFaceUnit(parts[3], out v2, out n2, out t2); ParseFaceUnit(parts[4], out v3, out n3, out t3); // index in obj files starts with 1. result = new ObjVNFQuad(v0 - 1, v1 - 1, v2 - 1, v3 - 1, n0 - 1, n1 - 1, n2 - 1, n3 - 1, t0 - 1, t1 - 1, t2 - 1, t3 - 1); } else { throw new Exception(string.Format("unexpected line parts[{0}]", parts.Length)); } return(result); }
private vec2[] ArrangeTexCoords(ObjVNFContext context) { var texCoords = new vec2[context.vertexCount]; ObjVNFMesh mesh = context.Mesh; for (int i = 0; i < context.faceCount; i++) { ObjVNFFace face = mesh.faces[i]; uint[] texCoordIndexes = face.TexCoordIndexes(); uint[] vertexIndexes = face.VertexIndexes(); if (texCoordIndexes.Length != vertexIndexes.Length) { throw new Exception(string.Format( "texCoordIndexes.Length [{0}] != vertexIndexes.Length [{1}]!", texCoordIndexes.Length, vertexIndexes.Length)); } for (int t = 0; t < vertexIndexes.Length; t++) { texCoords[vertexIndexes[t]] = mesh.texCoords[texCoordIndexes[t]]; } } return(texCoords); }
/// <summary> /// Reads mesh's vertex count, normal count and face count. /// </summary> /// <param name="context"></param> public override void Parse(ObjVNFContext context) { int triangleFaceCount = 0; ObjVNFMesh mesh = context.Mesh; for (int i = 0; i < context.faceCount; i++) { ObjVNFFace face = mesh.faces[i]; uint[] normalIndexes = (from item in face.NormalIndexes() select item).ToArray(); uint[] vertexIndexes = (from item in face.VertexIndexes() select item).ToArray(); if (normalIndexes.Length != vertexIndexes.Length) { throw new Exception(string.Format( "normalIndexes.Length [{0}] != vertexIndexes.Length [{0}]!", normalIndexes.Length, vertexIndexes.Length)); } if (face is ObjVNFTriangle) { triangleFaceCount++; } else if (face is ObjVNFQuad) { triangleFaceCount += 2; } } if (triangleFaceCount != context.faceCount) { var faces = new ObjVNFTriangle[triangleFaceCount]; for (int i = 0, j = 0; i < context.faceCount; i++) { ObjVNFFace face = mesh.faces[i]; if (face is ObjVNFTriangle) { faces[j++] = face as ObjVNFTriangle; } else if (face is ObjVNFQuad) { var quad = face as ObjVNFQuad; faces[j++] = new ObjVNFTriangle( quad.vertexIndexes[0], quad.vertexIndexes[1], quad.vertexIndexes[2], quad.normalIndexes[0], quad.normalIndexes[1], quad.normalIndexes[2], quad.texCoordIndexes[0], quad.texCoordIndexes[1], quad.texCoordIndexes[2]); faces[j++] = new ObjVNFTriangle( quad.vertexIndexes[0], quad.vertexIndexes[2], quad.vertexIndexes[3], quad.normalIndexes[0], quad.normalIndexes[2], quad.normalIndexes[3], quad.texCoordIndexes[0], quad.texCoordIndexes[2], quad.texCoordIndexes[3]); } } mesh.faces = faces; context.faceCount = triangleFaceCount; } }
private vec3[] CalculateNormals(ObjVNFContext context) { ObjVNFMesh mesh = context.Mesh; var faceNormals = new vec3[context.faceCount]; for (int i = 0; i < context.faceCount; i++) { ObjVNFFace face = mesh.faces[i]; uint[] vertexIndexes = (from item in face.VertexIndexes() select item).ToArray(); vec3 v0 = mesh.vertexes[vertexIndexes[0]]; vec3 v1 = mesh.vertexes[vertexIndexes[1]]; vec3 v2 = mesh.vertexes[vertexIndexes[2]]; vec3 normal = (v0 - v1).cross(v0 - v2).normalize(); faceNormals[i] = normal; } var normals = new vec3[context.vertexCount]; var counters = new int[context.vertexCount]; for (int i = 0; i < context.faceCount; i++) { ObjVNFFace face = mesh.faces[i]; uint[] vertexIndexes = (from item in face.VertexIndexes() select item).ToArray(); vec3 v0 = mesh.vertexes[vertexIndexes[0]]; vec3 v1 = mesh.vertexes[vertexIndexes[1]]; vec3 v2 = mesh.vertexes[vertexIndexes[2]]; normals[vertexIndexes[0]] += faceNormals[i]; counters[vertexIndexes[0]]++; normals[vertexIndexes[1]] += faceNormals[i]; counters[vertexIndexes[1]]++; normals[vertexIndexes[2]] += faceNormals[i]; counters[vertexIndexes[2]]++; } for (int i = 0; i < normals.Length; i++) { if (counters[i] > 0) { normals[i] = normals[i].normalize(); } } return(normals); }
/// <summary> /// Reads mesh's vertex count, normal count and face count. /// </summary> /// <param name="context"></param> public override void Parse(ObjVNFContext context) { int triangleFaceCount = 0; ObjVNFMesh mesh = context.Mesh; for (int i = 0; i < context.faceCount; i++) { ObjVNFFace face = mesh.faces[i]; uint[] vertexIndexes = face.VertexIndexes(); if (face is ObjVNFTriangle) { triangleFaceCount++; } else if (face is ObjVNFQuad) { triangleFaceCount += 2; } } if (triangleFaceCount != context.faceCount) { var faces = new ObjVNFTriangle[triangleFaceCount]; for (int i = 0, j = 0; i < context.faceCount; i++) { ObjVNFFace face = mesh.faces[i]; if (face is ObjVNFTriangle) { faces[j++] = face as ObjVNFTriangle; } else if (face is ObjVNFQuad) { var quad = face as ObjVNFQuad; faces[j++] = new ObjVNFTriangle( quad.vertexIndexes[0], quad.vertexIndexes[1], quad.vertexIndexes[2], quad.normalIndexes[0], quad.normalIndexes[1], quad.normalIndexes[2], quad.texCoordIndexes[0], quad.texCoordIndexes[1], quad.texCoordIndexes[2]); faces[j++] = new ObjVNFTriangle( quad.vertexIndexes[0], quad.vertexIndexes[2], quad.vertexIndexes[3], quad.normalIndexes[0], quad.normalIndexes[2], quad.normalIndexes[3], quad.texCoordIndexes[0], quad.texCoordIndexes[2], quad.texCoordIndexes[3]); } } mesh.faces = faces; context.faceCount = triangleFaceCount; } }
/// <summary> /// Reads mesh's vertexes, normals and faces. /// </summary> /// <param name="context"></param> public override void Parse(ObjVNFContext context) { var objVNF = new ObjVNFMesh(); var vertexes = new vec3[context.vertexCount]; var normals = new vec3[context.normalCount]; var texCoords = new vec2[context.texCoordCount]; var faces = new ObjVNFFace[context.faceCount]; string filename = context.ObjFilename; int vertexIndex = 0, normalIndex = 0, texCoordIndex = 0, faceIndex = 0; using (var reader = new System.IO.StreamReader(filename)) { while (!reader.EndOfStream) { string line = reader.ReadLine(); string[] parts = line.Split(separator, StringSplitOptions.RemoveEmptyEntries); if (parts.Length <= 0) { continue; } if (parts[0] == "v") { vertexes[vertexIndex++] = ParseVec3(parts); } else if (parts[0] == "vn") { normals[normalIndex++] = ParseVec3(parts); } else if (parts[0] == "vt") { texCoords[texCoordIndex++] = ParseVec2(parts); } else if (parts[0] == "f") { faces[faceIndex++] = ParseFace(parts); } } } objVNF.vertexes = vertexes; objVNF.normals = normals; objVNF.texCoords = texCoords; objVNF.faces = faces; context.Mesh = objVNF; if (vertexIndex != context.vertexCount) { throw new Exception(string.Format("v: [{0}] not equals to [{1}] in MeshParser!", vertexIndex, context.vertexCount)); } if (normalIndex != context.normalCount) { throw new Exception(string.Format("vn: [{0}] not equals to [{1}] in MeshParser!", normalIndex, context.normalCount)); } if (texCoordIndex != context.texCoordCount) { throw new Exception(string.Format("vt: [{0}] not equals to [{1}] in MeshParser!", texCoordIndex, context.texCoordCount)); } if (faceIndex != context.faceCount) { throw new Exception(string.Format("f: [{0}] not equals to [{1}] in MeshParser!", vertexIndex, context.vertexCount)); } if (faceIndex > 0) { Type type = faces[0].GetType(); for (int i = 1; i < faceIndex; i++) { if (faces[i].GetType() != type) { throw new Exception(string.Format("Different face types [{0}] vs [{1}]!", type, faces[i].GetType())); } } } }