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 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); }
public IEnumerable <IDrawCommand> GetDrawCommand() { if (this.drawCmd == null) { ObjVNFMesh mesh = this.mesh; ushort[] values = new ushort[3]; var index = 0; var array = new Face[mesh.faces.Length]; foreach (var face in mesh.faces) { int i = 0; foreach (var vertexIndex in face.VertexIndexes()) { if (vertexIndex > ushort.MaxValue) { throw new Exception(string.Format("Not support model size greater than {0} vertexes!", ushort.MaxValue)); } values[i++] = (ushort)vertexIndex; } array[index++] = new Face(values[0], values[1], values[2]); i = 0; } AdjacentFace[] adjacentFaces = array.CalculateAdjacentFaces(); IndexBuffer buffer = adjacentFaces.GenIndexBuffer(IndexBufferElementType.UShort, BufferUsage.StaticDraw); this.drawCmd = new DrawElementsCmd(buffer, DrawMode.TrianglesAdjacency); } yield return(this.drawCmd); }
public override void Parse(ObjVNFContext context) { ObjVNFMesh mesh = context.Mesh; if (mesh.texCoords.Length > 0) { vec2[] texCoords = ArrangeTexCoords(context); mesh.texCoords = 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; } }
public override void Parse(ObjVNFContext context) { vec3[] normals = null; ObjVNFMesh mesh = context.Mesh; if (mesh.normals.Length == 0) { normals = CalculateNormals(context); } else { normals = ArrangeNormals(context); } mesh.normals = normals; }
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> /// /// </summary> /// <param name="model"></param> /// <returns></returns> public static ObjVNFNode Create(ObjVNFMesh mesh) { var model = new ObjVNF(mesh); RenderMethodBuilder builder; { var vs = new VertexShader(vertexCode); var fs = new FragmentShader(fragmentCode); var provider = new ShaderArray(vs, fs); var map = new AttributeMap(); map.Add(inPosition, Teapot.strPosition); map.Add(inNormal, Teapot.strNormal); builder = new RenderMethodBuilder(provider, map); } var node = new ObjVNFNode(model, ObjVNF.strPosition, builder); node.ModelSize = model.GetSize(); node.WorldPosition = model.GetPosition(); node.Initialize(); return node; }
/// <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> /// /// </summary> /// <param name="mesh"></param> public ObjVNF(ObjVNFMesh mesh) { this.mesh = mesh; }
/// <summary> /// /// </summary> /// <param name="mesh"></param> public AdjacentTriangleModel(ObjVNFMesh mesh) { this.mesh = mesh; }
/// <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())); } } } }
public override void Parse(ObjVNFContext context) { ObjVNFMesh mesh = context.Mesh; vec3[] vertexes = mesh.vertexes;// positions vec2[] texCoords = mesh.texCoords; vec3[] normals = mesh.normals; if (vertexes == null || texCoords == null || normals == null) { return; } if (vertexes.Length != texCoords.Length || vertexes.Length != normals.Length) { return; } ObjVNFFace[] faces = mesh.faces; if (faces == null || faces.Length == 0) { return; } // if (not triangles) { return; } if (faces[0].VertexIndexes().Count() != 3) { return; } var tangents = new vec3[normals.Length]; for (int i = 0; i < faces.Length; i++) { var face = faces[i] as ObjVNFTriangle; if (face == null) { return; } // no dealing with quad. uint[] vertexIndexes = face.VertexIndexes(); vec3 p0 = vertexes[vertexIndexes[0]]; vec3 p1 = vertexes[vertexIndexes[1]]; vec3 p2 = vertexes[vertexIndexes[2]]; vec2 uv0 = texCoords[vertexIndexes[0]]; vec2 uv1 = texCoords[vertexIndexes[1]]; vec2 uv2 = texCoords[vertexIndexes[2]]; vec3 q0 = p1 - p0, q1 = p2 - p0; float u0 = uv0.x, v0 = uv0.y, u1 = uv1.x, v1 = uv1.y, u2 = uv2.x, v2 = uv2.y; float coefficient = 1.0f / ((u1 - u0) * (v2 - v0) - (v1 - v0) * (u2 - u0)); vec3 tangentFace; tangentFace.x = (v2 - v0) * q0.x + (v0 - v1) * q1.x; tangentFace.y = (v2 - v0) * q0.y + (v0 - v1) * q1.y; tangentFace.z = (v2 - v0) * q0.z + (v0 - v1) * q1.z; //vec3 binormalFace; //binormalFace.x = (u0 - u2) * q0.x + (u1 - u0) * q1.x; //binormalFace.y = (u0 - u2) * q0.y + (u1 - u0) * q1.y; //binormalFace.z = (u0 - u2) * q0.z + (u1 - u0) * q1.z; for (int t = 0; t < vertexIndexes.Length; t++) { vec3 n = normals[vertexIndexes[t]].normalize(); tangents[vertexIndexes[t]] = tangentFace - tangentFace.dot(n) * n; } } mesh.tangents = tangents; }
// https://www.cnblogs.com/bitzhuwei/p/opengl-Computing-Tangent-Space-Basis-Vectors.html public override void Parse(ObjVNFContext context) { ObjVNFMesh mesh = context.Mesh; vec3[] vertexes = mesh.vertexes;// positions vec2[] texCoords = mesh.texCoords; vec3[] normals = mesh.normals; if (vertexes == null || texCoords == null || normals == null) { return; } if (vertexes.Length != texCoords.Length || vertexes.Length != normals.Length) { return; } ObjVNFFace[] faces = mesh.faces; if (faces == null || faces.Length == 0) { return; } // if (not triangles) { return; } if (faces[0].VertexIndexes().Count() != 3) { return; } var tangents = new vec3[normals.Length]; var biTangents = new vec3[normals.Length]; for (int i = 0; i < faces.Length; i++) { var face = faces[i] as ObjVNFTriangle; if (face == null) { return; } // no dealing with quad. uint[] vertexIndexes = face.VertexIndexes(); uint i0 = vertexIndexes[0]; uint i1 = vertexIndexes[1]; uint i2 = vertexIndexes[2]; vec3 p0 = vertexes[i0]; vec3 p1 = vertexes[i1]; vec3 p2 = vertexes[i2]; vec2 uv0 = texCoords[i0]; vec2 uv1 = texCoords[i1]; vec2 uv2 = texCoords[i2]; float x1 = p1.x - p0.x; float y1 = p1.y - p0.y; float z1 = p1.z - p0.z; float x2 = p2.x - p0.x; float y2 = p2.y - p0.y; float z2 = p2.z - p0.z; float s1 = uv1.x - uv0.x; float t1 = uv1.y - uv0.y; float s2 = uv2.x - uv0.x; float t2 = uv2.y - uv0.y; float r = 1.0F / (s1 * t2 - s2 * t1); var sdir = new vec3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); var tdir = new vec3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); //tangents[i0] += sdir; tangents[i0] = (float)i / (float)(i + 1) * tangents[i0] + sdir / (float)(i + 1); //tangents[i1] += sdir; tangents[i1] = (float)i / (float)(i + 1) * tangents[i1] + sdir / (float)(i + 1); //tangents[i2] += sdir; tangents[i2] = (float)i / (float)(i + 1) * tangents[i2] + sdir / (float)(i + 1); //biTangents[i0] += tdir; biTangents[i0] = (float)i / (float)(i + 1) * biTangents[i0] + sdir / (float)(i + 1); //biTangents[i1] += tdir; biTangents[i1] = (float)i / (float)(i + 1) * biTangents[i1] + sdir / (float)(i + 1); //biTangents[i2] += tdir; biTangents[i2] = (float)i / (float)(i + 1) * biTangents[i2] + sdir / (float)(i + 1); } var finalTangents = new vec4[normals.Length]; for (long a = 0; a < normals.Length; a++) { vec3 n = normals[a]; vec3 t = tangents[a]; // Calculate handedness float w = (n.cross(t).dot(biTangents[a]) < 0.0F) ? -1.0F : 1.0F; // Gram-Schmidt orthogonalize finalTangents[a] = new vec4((t - n * n.dot(t)).normalize(), w); } mesh.tangents = finalTangents; }