private static List <Triangle> CreateCap(Vector3 start, float radius, Vector3 normal, int steps, int precision) { var triangles = new List <Triangle>(); var end = start + normal * radius; for (int i = 0; i < precision; ++i) { float t1 = ((i + 0) / (float)precision); float t2 = ((i + 1) / (float)precision); float radius1 = MathHelper.Lerp(0, radius, (float)Math.Sqrt(1f - (t1 * t1))); float radius2 = MathHelper.Lerp(0, radius, (float)Math.Sqrt(1f - (t2 * t2))); var pos1 = Vector3.Lerp(start, end, t1); var pos2 = Vector3.Lerp(start, end, t2); var startPoints = Disk.CreatePoints(pos1, normal, radius1, steps); var endPoints = Disk.CreatePoints(pos2, normal, radius2, steps); triangles.AddRange(GeometryHelper.ExtrudePoints(startPoints, endPoints)); } return(triangles); }
public static List <Part> Load(string[] lines) { // The global geometry var positions = new List <Vector3>(); var normals = new List <Vector3>(); var texcoords = new List <Vector3>(); var vertices = new List <Vertex>(); var indices = new List <int>(); var mesh = new List <Part>(); var currentGroup = ""; var currentMaterial = "unknown"; // Parse all lines foreach (var rawLine in lines) { // Skip the line if empty or is a comment var line = rawLine.Trim(); if (line == "" || line.StartsWith("#")) { continue; } // Cut the line in different parts var parts = line.Split(Separator, StringSplitOptions.RemoveEmptyEntries); var type = parts[0]; // Vertex declaration if (type.StartsWith("v")) { var vector = ParseVector3(parts); if (type == "v") { positions.Add(vector); } else if (type == "vt") { texcoords.Add(vector); } else if (type == "vn") { normals.Add(vector); } } else if (type == "f") { // Face declaration if (currentGroup != "") { // Add the vertices to the group vertices.Add(GetVertexFromF(parts[1], positions, texcoords, normals)); var index1 = vertices.Count - 1; vertices.Add(GetVertexFromF(parts[2], positions, texcoords, normals)); var index2 = vertices.Count - 1; vertices.Add(GetVertexFromF(parts[3], positions, texcoords, normals)); var index3 = vertices.Count - 1; // Add the indices indices.Add(index1); indices.Add(index2); indices.Add(index3); // Handle quads if (parts.Length > 4) { vertices.Add(GetVertexFromF(parts[4], positions, texcoords, normals)); var index4 = vertices.Count - 1; indices.Add(index1); indices.Add(index3); indices.Add(index4); } } } else if (type == "g" || type == "o") { string name = string.Join("_", parts.Skip(1)); if (name != currentGroup) { if (currentGroup != "") { // Add the group to the mesh var group = new Part() { Name = currentGroup, Material = currentMaterial }; group.Vertices.AddRange(vertices); group.Indices.AddRange(indices); mesh.Add(group); vertices.Clear(); indices.Clear(); } currentGroup = name; } } else if (type.StartsWith("usemtl")) { currentMaterial = (parts.Length > 1) ? parts[1] : ""; } } // Add the last group to the mesh if (vertices.Any() && indices.Any()) { var group = new Part() { Name = currentGroup, Material = currentMaterial }; group.Vertices.AddRange(vertices); group.Indices.AddRange(indices); mesh.Add(group); } // Recalculate the normals if needed if (!normals.Any()) { // Recreate the normals foreach (var part in mesh) { // Default normal for every different vertex var normalsPerVertex = new Dictionary <Vector3, Vector3>(); foreach (var vertex in part.Vertices) { normalsPerVertex[vertex.Position] = new Vector3(); } for (int i = 0; i < (part.Indices.Count - 2); i += 3) { // Compute the normal for each triangle var i1 = part.Indices[i + 0]; var i2 = part.Indices[i + 1]; var i3 = part.Indices[i + 2]; var pos1 = part.Vertices[i1].Position; var pos2 = part.Vertices[i2].Position; var pos3 = part.Vertices[i3].Position; var normal = GeometryHelper.GetFaceNormal(pos1, pos2, pos3); // Add the normals normalsPerVertex[pos1] = Vector3.Normalize(normalsPerVertex[pos1] + normal); normalsPerVertex[pos2] = Vector3.Normalize(normalsPerVertex[pos2] + normal); normalsPerVertex[pos3] = Vector3.Normalize(normalsPerVertex[pos3] + normal); } // Apply the new normals for (int i = 0; i < part.Vertices.Count; ++i) { var vertex = part.Vertices[i]; vertex.Normal = normalsPerVertex[vertex.Position]; part.Vertices[i] = vertex; } } } // Return the mesh return(mesh); }
private static Vector3 GetNewPosition(IReadOnlyList <Triangle> allFaces, Vector3 vertex) { var faces = GetFacesForPoint(allFaces, vertex); var edges = GetEdgesForPoint(allFaces, vertex); if (faces.Count == edges.Count) { return(Barycentre(vertex, faces.Count, GeometryHelper.Average(faces.Select(f => f.Center)), GeometryHelper.Average(edges.Select(p => GeometryHelper.GetEdgeMiddle(vertex, p))))); } else { var avgMidEdges = GeometryHelper.Average(edges.Where(p => GetFacesForEdge(allFaces, vertex, p).Count == 1).Select(p => GeometryHelper.GetEdgeMiddle(vertex, p))); return((vertex + avgMidEdges) / 2f); } }