Exemplo n.º 1
0
    public void DisplayMeshMain(HalfEdgeData2 meshData, Normalizer2 normalizer)
    {
        //UnNormalize and to 3d
        HalfEdgeData3 meshDataUnNormalized_3d = new HalfEdgeData3();


        //We dont want to modify the original data
        //HalfEdgeData2 meshDataUnNormalized = normalizer.UnNormalize(meshData);

        HashSet <HalfEdgeFace2> faces_2d = meshData.faces;

        foreach (HalfEdgeFace2 f in faces_2d)
        {
            MyVector2 p1 = f.edge.v.position;
            MyVector2 p2 = f.edge.nextEdge.v.position;
            MyVector2 p3 = f.edge.nextEdge.nextEdge.v.position;

            p1 = normalizer.UnNormalize(p1);
            p2 = normalizer.UnNormalize(p2);
            p3 = normalizer.UnNormalize(p3);

            meshDataUnNormalized_3d.AddTriangle(p1.ToMyVector3_Yis3D(), p2.ToMyVector3_Yis3D(), p3.ToMyVector3_Yis3D());
        }

        this.meshData = meshDataUnNormalized_3d.faces;

        DisplayMesh(meshDataUnNormalized_3d.faces, displayMeshHere);

        //Normalize again
        //meshData = normalizer.Normalize(meshDataUnNormalized);
    }
    private IEnumerator GenerateHull(HashSet <MyVector3> points, HalfEdgeData3 convexHull)
    {
        //PAUSE FOR VISUALIZATION
        //Display what we have so far
        controller.DisplayMeshMain(convexHull.faces);
        controller.HideAllVisiblePoints(convexHull.verts);

        yield return(new WaitForSeconds(10f));


        //Add all other points one-by-one
        List <MyVector3> pointsToAdd = new List <MyVector3>(points);

        foreach (MyVector3 p in pointsToAdd)
        {
            //Is this point within the tetrahedron
            bool isWithinHull = _Intersections.PointWithinConvexHull(p, convexHull);

            if (isWithinHull)
            {
                points.Remove(p);

                controller.HideVisiblePoint(p);

                continue;
            }


            //PAUSE FOR VISUALIZATION
            //Display active point
            controller.DisplayActivePoint(p);

            //Rotate camera to this point
            //Important to turn this vector to 2d
            Vector3 unity_pos = controller.normalizer.UnNormalize(p).ToVector3();

            controller.cameraScript.SetWantedHeight(unity_pos.y);

            unity_pos.y = 0f;

            controller.cameraScript.SetWantedDirection((Vector3.zero - unity_pos).normalized);

            yield return(new WaitForSeconds(2f));


            //Find visible triangles and edges on the border between the visible and invisible triangles
            HashSet <HalfEdgeFace3> visibleTriangles = null;
            HashSet <HalfEdge3>     borderEdges      = null;

            IterativeHullAlgorithm3D.FindVisibleTrianglesAndBorderEdgesFromPoint(p, convexHull, out visibleTriangles, out borderEdges);

            //Remove all visible triangles
            foreach (HalfEdgeFace3 triangle in visibleTriangles)
            {
                convexHull.DeleteFace(triangle);
            }


            //PAUSE FOR VISUALIZATION
            //For visualization purposes we now need to create two meshes and then remove the triangles again
            controller.DisplayMeshMain(convexHull.faces);
            controller.DisplayMeshOther(visibleTriangles);
            controller.HideAllVisiblePoints(convexHull.verts);

            yield return(new WaitForSeconds(2f));


            //PAUSE FOR VISUALIZATION
            //Remove all now visible triangles that forms the hole
            List <HalfEdgeFace3> visibleTrianglesList = new List <HalfEdgeFace3>(visibleTriangles);

            for (int i = 0; i < visibleTrianglesList.Count; i++)
            {
                visibleTriangles.Remove(visibleTrianglesList[i]);

                controller.DisplayMeshOther(visibleTriangles);

                yield return(new WaitForSeconds(0.5f));
            }


            //Save all ned edges so we can connect them with an opposite edge
            //To make it faster you can use the ideas in the Valve paper to get a sorted list of newEdges
            HashSet <HalfEdge3> newEdges = new HashSet <HalfEdge3>();

            foreach (HalfEdge3 borderEdge in borderEdges)
            {
                //Each edge is point TO a vertex
                MyVector3 p1 = borderEdge.prevEdge.v.position;
                MyVector3 p2 = borderEdge.v.position;

                //The border edge belongs to a triangle which is invisible
                //Because triangles are oriented clockwise, we have to add the vertices in the other direction
                //to build a new triangle with the point
                HalfEdgeFace3 newTriangle = convexHull.AddTriangle(p2, p1, p);


                //PAUSE FOR VISUALIZATION
                controller.DisplayMeshMain(convexHull.faces);

                yield return(new WaitForSeconds(0.5f));


                //Connect the new triangle with the opposite edge on the border
                //When we create the face we give it a reference edge which goes to p2
                //So the edge we want to connect is the next edge
                HalfEdge3 edgeToConnect = newTriangle.edge.nextEdge;

                edgeToConnect.oppositeEdge = borderEdge;
                borderEdge.oppositeEdge    = edgeToConnect;

                //Two edges are still not connected, so save those
                HalfEdge3 e1 = newTriangle.edge;
                //HalfEdge3 e2 = newTriangle.edge.nextEdge;
                HalfEdge3 e3 = newTriangle.edge.nextEdge.nextEdge;

                newEdges.Add(e1);
                //newEdges.Add(e2);
                newEdges.Add(e3);
            }


            //Two edges in each triangle are still not connected with an opposite edge
            foreach (HalfEdge3 e in newEdges)
            {
                if (e.oppositeEdge != null)
                {
                    continue;
                }

                convexHull.TryFindOppositeEdge(e, newEdges);
            }


            //PAUSE FOR VISUALIZATION
            //controller.DisplayMeshMain(convexHull.faces);

            //yield return new WaitForSeconds(2f);
            controller.HideVisiblePoint(p);
        }


        controller.HideActivePoint();

        controller.cameraScript.SetWantedDirection(Vector3.zero);
        controller.cameraScript.SetWantedHeight(0f);

        //controller.DisplayMeshMain(convexHull.faces);

        //yield return new WaitForSeconds(5f);


        yield return(null);
    }
Exemplo n.º 3
0
    //
    // Add the constraints to the delaunay triangulation
    //

    //timer is for debugging
    private IEnumerator AddConstraints(HalfEdgeData2 triangleData, List <MyVector2> constraints, bool shouldRemoveTriangles, Normalizer2 normalizer, System.Diagnostics.Stopwatch timer = null)
    {
        //Validate the data
        if (constraints == null)
        {
            yield return(null);
        }



        //
        // PAUSE AND VISUALIZE
        //

        //Show the constraint with a line mesh
        HashSet <Triangle2> lineTriangles = _GenerateMesh.ConnectedLineSegments(constraints, width: 0.01f, isConnected: true);

        //UnNormalized and to half-edge 3 (also move each vertex up a little or will intersect with the underlying mesh)
        HalfEdgeData3 lineData = new HalfEdgeData3();

        foreach (Triangle2 t in lineTriangles)
        {
            MyVector2 p1 = t.p1;
            MyVector2 p2 = t.p2;
            MyVector2 p3 = t.p3;

            p1 = normalizer.UnNormalize(p1);
            p2 = normalizer.UnNormalize(p2);
            p3 = normalizer.UnNormalize(p3);

            lineData.AddTriangle(p1.ToMyVector3_Yis3D(0.1f), p2.ToMyVector3_Yis3D(0.1f), p3.ToMyVector3_Yis3D(0.1f));
        }

        visualizeController.DisplayMeshOtherUnNormalized(lineData.faces);

        yield return(new WaitForSeconds(2f));



        //Get a list with all edges
        //This is faster than first searching for unique edges
        //The report suggest we should do a triangle walk, but it will not work if the mesh has holes
        //The mesh has holes because we remove triangles while adding constraints one-by-one
        //so maybe better to remove triangles after we added all constraints...
        HashSet <HalfEdge2> edges = triangleData.edges;


        //The steps numbering is from the report
        //Step 1. Loop over each constrained edge. For each of these edges, do steps 2-4
        for (int i = 0; i < constraints.Count; i++)
        {
            //Let each constrained edge be defined by the vertices:
            MyVector2 c_p1 = constraints[i];
            MyVector2 c_p2 = constraints[MathUtility.ClampListIndex(i + 1, constraints.Count)];

            //Check if this constraint already exists in the triangulation,
            //if so we are happy and dont need to worry about this edge
            //timer.Start();
            if (IsEdgeInListOfEdges(edges, c_p1, c_p2))
            {
                continue;
            }
            //timer.Stop();

            //Step 2. Find all edges in the current triangulation that intersects with this constraint
            //Is returning unique edges only, so not one edge going in the opposite direction
            //timer.Start();
            Queue <HalfEdge2> intersectingEdges = FindIntersectingEdges_BruteForce(edges, c_p1, c_p2);
            //timer.Stop();

            //Debug.Log("Intersecting edges: " + intersectingEdges.Count);

            //Step 3. Remove intersecting edges by flipping triangles
            //This takes 0 seconds so is not bottleneck
            //timer.Start();
            List <HalfEdge2> newEdges = new List <HalfEdge2>();

            yield return(StartCoroutine(RemoveIntersectingEdges(c_p1, c_p2, intersectingEdges, newEdges, triangleData, normalizer)));

            //timer.Stop();

            //Step 4. Try to restore delaunay triangulation
            //Because we have constraints we will never get a delaunay triangulation
            //This takes 0 seconds so is not bottleneck
            //timer.Start();
            yield return(StartCoroutine(RestoreDelaunayTriangulation(c_p1, c_p2, newEdges, triangleData, normalizer)));
            //timer.Stop();
        }

        //Step 5. Remove superfluous triangles, such as the triangles "inside" the constraints
        if (shouldRemoveTriangles)
        {
            //timer.Start();
            yield return(StartCoroutine(RemoveSuperfluousTriangles(triangleData, constraints, normalizer)));
            //timer.Stop();
        }

        //return triangleData;



        //
        // PAUSE AND VISUALIZE
        //

        visualizeController.HideMeshOther();

        yield return(new WaitForSeconds(2f));
    }