Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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);
            }
        }