Example #1
0
        private List<Face> Tessellate(Face f)
        {
            // Base Case: Face is already a triangle
            if (f.vertices.Count() == 3)
            {
                return new List<Face>(new Face[] { f });
            }
            else
            {
                int verts = f.vertices.Count();
                // Find an ear on the face, remove it
                for (int i = 0; i < verts; i++)
                {
                    Vector3 v1 = f.vertices[i];
                    Vector3 v2 = f.vertices[(i + 1) % verts];
                    Vector3 v3 = f.vertices[(i + 2) % verts];
                    Face tri = new Face();
                    tri.vertices.Add(v1);
                    tri.vertices.Add(v2);
                    tri.vertices.Add(v3);

                    bool anyPointInPolygon = false;
                    foreach (Vector3 p in f.vertices)
                    {
                        if (p != v1 && p != v2 && p != v3 && IsPointInPolygon(tri, p))
                        {
                            anyPointInPolygon = true;
                            break;
                        }
                    }

                    // First check: see if any point in the original polygon is inside the new triangle
                    if (anyPointInPolygon) //AnyPointInPolygon(tri, f.vertices))
                    {
                        // Can't use this triangle, move onto the next one
                    }
                    else
                    {
                        // Second Check: see if the midpoint on the new line is within the original polygon
                        Vector3 midpoint = (v1 + v3) / 2;
                        if (!IsPointInPolygon(f, midpoint))
                        {
                            // Can't use this triangle, move onto the next one
                        }
                        else
                        {
                            // Triangle satisfies criteria for an ear! Add it to the face list.
                            List<Face> faces = new List<Face>();
                            faces.Add(tri);
                            f.vertices.RemoveAt((i + 1) % verts);
                            faces.AddRange(Tessellate(f));
                            return faces;
                        }
                    }
                }
            }

            // If we get here, the face has no ear and more than 3 vertices... Bad situation!
            //throw new Exception("Failed to tessellate face!");
            badfaces.Add(f);
            return new List<Face>();
        }
Example #2
0
File: PolyNet.cs Project: GNZ/CG
        public void addFace(Vertex[] vertices)
        {
            HalfEdge[] currentHalfEdges = new HalfEdge[vertices.Length];

            //add halfedges
            for (int curr = 0; curr < vertices.Length; curr++)
            {
                int next_he = (curr + 1) % vertices.Length;

                // look if half-edge already exists
                HalfEdge exist = existHalfEdge(vertices[curr], vertices[next_he]);

                // if it does, add it to the array, otherwise create it
                if (exist == null)
                {
                    // create half edge from current to next vertex
                    currentHalfEdges[curr] = new HalfEdge(vertices[curr], vertices[next_he]);
                    HalfEdge twin = new HalfEdge(vertices[next_he],vertices[curr]);

                    currentHalfEdges[curr].twin = twin;
                    twin.twin = currentHalfEdges[curr];
                    // add halfedge to polynet halfedges dictionary
                    this.halfEdges.Add(vertices[curr], vertices[next_he], currentHalfEdges[curr]);
                    this.halfEdges.Add(vertices[next_he], vertices[curr], twin);
                }
                else
                {
                    currentHalfEdges[curr] = exist;
                }
            }

            // create face with some halfedge
            Face face = new Face(currentHalfEdges[0]);
            // calculate face's normal
            face.normal = faceNormal(vertices);
            // add face to faces list
            faces.Add(face);

            // link halfedges with next and prev
            for(int i = 0; i < currentHalfEdges.Length; i++){
                int next = (i + 1) % currentHalfEdges.Length;
                int prev = (currentHalfEdges.Length + i - 1) % currentHalfEdges.Length;

                currentHalfEdges[i].next = currentHalfEdges[next];
                currentHalfEdges[i].prev = currentHalfEdges[prev];

                // link face to halfedge
                currentHalfEdges[i].face = face;
            }
        }
Example #3
0
 static bool IsPointInPolygon(Face f, Vector3 point)
 {
     // TODO: Implement a ray tracing approach instead - angle summation can be unreliable and slow.
     float angle = 0;
     for (int i = 0; i < f.vertices.Count(); i++)
     {
         Vector3 v1 = f.vertices[i] - point;
         Vector3 v2 = f.vertices[(i + 1) % f.vertices.Count()] - point;
         float direction = Vector3.Dot (Vector3.Cross(v1, v2), f.Normal) / (v1.Length * v2.Length);
         if (direction > -.0001) // Biased towards within polygon
         {
             angle += (float)Math.Acos(Vector3.Dot(v1, v2) / (v1.Length * v2.Length));
         }
         else
         {
             angle -= (float)Math.Acos(Vector3.Dot(v1, v2) / (v1.Length * v2.Length));
         }
     }
     angle = (float)Math.Abs(angle);
     //Console.WriteLine("In Face = {0}, Angle = {1} | {2}", Utilities.MathHelper.NearlyEqual (angle, OpenTK.MathHelper.TwoPi), angle, OpenTK.MathHelper.TwoPi);
     return Utilities.MathHelper.NearlyEqual(angle, OpenTK.MathHelper.TwoPi) || angle > OpenTK.MathHelper.TwoPi;
 }
Example #4
0
        public void LoadObj(string filepath)
        {
            string[] strings = System.IO.File.ReadAllLines(filepath);
            Regex vertexRegex = new Regex (@"^v\s+(?<x>\S+)\s+(?<y>\S+)\s+(?<z>\S+)", RegexOptions.IgnoreCase);
            //Regex faceRegex = new Regex (@"^f(?<face_data>\s+\w+)+", RegexOptions.IgnoreCase);
            //Regex f = new Regex(@"^f(?<face_data>[^/]*/(?<itemNumber>\w+))+", RegexOptions.IgnoreCase);
            Regex faceRegex = new Regex(@"^f(?<face_data>\s+(?<vertex>\d+)/?(?<texture_coordinate>\d+)?/?(?<vertex_normal>\d+)?)+", RegexOptions.IgnoreCase);
            //Regex f = new Regex(@"(?<container>\d{5})(?<serial>[^/]*/(?<itemNumber>\w{5})(?<quantity>\d{3}))+", RegexOptions.IgnoreCase);

            // "f 1/1/1 2/2/1 3/3/1 4/4/1 5/5/1"
            foreach (string s in strings)
            {
                // Lines starting with v are a vertex:
                // "v 10.2426 4.5e-013 -31.7638"
                if (vertexRegex.IsMatch(s))
                {
                    Match m = vertexRegex.Match(s);
                    float x = float.Parse(m.Groups["x"].Value);
                    float y = float.Parse(m.Groups["y"].Value);
                    float z = float.Parse(m.Groups["z"].Value);
                    vertices.Add(new Vector3 (x, z, y) * 1000);
                    //Console.WriteLine("Vertex Found: {0}", v);
                }
                else if (faceRegex.IsMatch(s))
                {
                    Match m = faceRegex.Match(s);

                    //Console.WriteLine(m.Groups["face_data"].Captures.Count);
                    //Console.WriteLine(m.Groups["vertex"].Captures.Count);
                    //Console.WriteLine(m.Groups["texture_coordinate"].Captures.Count);
                    //Console.WriteLine(m.Groups["vertex_normal"].Captures.Count);

                    Face face = new Face();

                    CaptureCollection vert_captures = m.Groups["vertex"].Captures;
                    CaptureCollection texcoord_captures = m.Groups["texture_coordinate"].Captures;
                    CaptureCollection norm_captures = m.Groups["vertex_normal"].Captures;
                    for (int i = 0; i < vert_captures.Count; i++)
                    {
                        int vert_index = int.Parse(vert_captures[i].Value) - 1;
                        if (vert_index < 0 || vert_index > vertices.Count)
                        {
                            Console.WriteLine("Bad vertex index {0}, only {1} vertices loaded", vert_index, vertices.Count);
                        }
                        else
                        {
                            face.vertices.Add(this.vertices[vert_index]);
                        }
                    }
                    if (texcoord_captures.Count == vert_captures.Count)
                    {
                        // TODO: Add texture coordinates to the face
                    }
                    if (norm_captures.Count == vert_captures.Count)
                    {
                        // TODO: Add vertex normals to the face
                    }

                    if (face.vertices.Count < 3)
                    {
                        Console.WriteLine("Bad face defined, less than 3 vertices");
                    }
                    else
                    {
                        AddFace(face);
                    }
                }
            }
        }
Example #5
0
 public Plane(Face f)
 {
     point = f.vertices[0];
     normal = f.Normal;
 }
Example #6
0
 public void AddFace(Face f)
 {
     //this.faces.Add(f);
     this.faces.AddRange(Tessellate(f));
 }
Example #7
0
        private PolyLine TrianglePlaneIntersect(Face f, Plane p)
        {
            PolyLine polyLine = new PolyLine();

            float epsilon = 0.01f; // TODO: Auto compute based on scale
            float epsilon_unit = 0.00001f; // Unit size epsilon value
            Vector3 f_normal = f.Normal;
            f_normal.Normalize();
            p.normal.Normalize();

            if ((f_normal - p.normal).Length < epsilon_unit || (f_normal + p.normal).Length < epsilon_unit)
            {
                // No intersection
            }
            else
            {
                Vector3 expected_direction = Vector3.Cross(f.Normal, p.normal);

                // Assume we're dealing with triangles only
                int verts = f.vertices.Count();
                if (verts != 3)
                {
                    throw new Exception("The number of vertices is not 3!");
                }

                float[] d = new float[3];
                for (int i = 0; i < 3; i++)
                {
                    d[i] = p.Distance(f.vertices[i]);
                }

                for (int i = 0; i < 3; i++)
                {
                    // Is the line on the plane?
                    if (Math.Abs(d[i]) < epsilon && Math.Abs(d[(i + 1) % 3]) < epsilon)
                    {
                        polyLine.points.Add(f.vertices[i]);
                        polyLine.points.Add(f.vertices[(i + 1) % 3]);
                        break;
                    }
                }

                if (polyLine.points.Count() == 0)
                {
                    // Line not on a plain: might have an intersection with a point and the opposite line
                    for (int i = 0; i < 3; i++)
                    {
                        float d1 = d[i];
                        float d2 = d[(i + 1) % 3];
                        float d3 = d[(i + 2) % 3];
                        if (Math.Abs(d[i]) < epsilon && Math.Sign(d2) != Math.Sign(d3))
                        {
                            d2 = Math.Abs(d2);
                            d3 = Math.Abs(d3);

                            // One negative, one positive
                            float total = d2 + d3;
                            Vector3 result = (f.vertices[(i + 1) % 3] * d3 + f.vertices[(i + 2) % 3] * d2) / total;
                            polyLine.points.Add(f.vertices[i]);
                            polyLine.points.Add(result);
                            break;
                        }
                    }
                    if (polyLine.points.Count() == 0)
                    {
                        // No edge in plane and no point + line intersect: maybe two lines intersect?
                        for (int i = 0; i < 3; i++)
                        {
                            // Intersection with an edge
                            if (Math.Sign(d[i]) != Math.Sign(d[(i + 1) % 3]))
                            {
                                float d1 = Math.Abs(d[i]);
                                float d2 = Math.Abs(d[(i + 1) % 3]);
                                float total = d1 + d2;
                                Vector3  result = (f.vertices[i] * d2 + f.vertices[(i + 1) % 3] * d1) / total;
                                polyLine.points.Add(result);
                                if (polyLine.points.Count() == 2)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }

                if (polyLine.points.Count() >= 2)
                {
                    //DrawCone1(polyLine.points[0], polyLine.points[1]);
                    Vector3 direction = polyLine.points[1] - polyLine.points[0];
                    if (Vector3.Dot(direction, expected_direction) < 0)
                    {
                        PolyLine reversed = new PolyLine();
                        reversed.points.Add(polyLine.points[1]);
                        reversed.points.Add(polyLine.points[0]);
                        polyLine = reversed;
                    }
                //
                //
                //    Color[] colors = new Color[] { Color.DarkRed, Color.LightGreen, Color.DarkBlue };
                //    int i = 0;
                //    GL.Begin(BeginMode.LineLoop);
                //    foreach (Vector3 v in polyLine.points)
                //    {
                //        GL.Color3(colors[i++]);
                //        GL.Vertex3(v);
                //
                //    }
                //    GL.End();
                //
                //    GL.PointSize(10);
                //    GL.Color3(Color.Orange);
                //    GL.Begin(BeginMode.Points);
                //    foreach (Vector3 v in polyLine.points)
                //    {
                //        GL.Vertex3(v);
                //    }
                //    GL.End();
                //    GL.PointSize(1);
                }
            }
            return polyLine;
        }