Ejemplo n.º 1
0
    //Display a face which we know is a triangle with its normal at the center
    public static void DebugDrawTriangle(HalfEdgeFace3 f, Color lineColor, Color normalColor, Normalizer3 normalizer = null)
    {
        MyVector3 p1 = f.edge.v.position;
        MyVector3 p2 = f.edge.nextEdge.v.position;
        MyVector3 p3 = f.edge.nextEdge.nextEdge.v.position;

        if (normalizer != null)
        {
            p1 = normalizer.UnNormalize(p1);
            p2 = normalizer.UnNormalize(p2);
            p3 = normalizer.UnNormalize(p3);
        }

        Vector3 normal = f.edge.v.normal.ToVector3();

        TestAlgorithmsHelpMethods.DebugDrawTriangle(p1.ToVector3(), p2.ToVector3(), p3.ToVector3(), normal * 0.5f, Color.white, Color.red);

        //Debug.Log("Displayed Triangle");

        //To test the the triangle is clock-wise
        //TestAlgorithmsHelpMethods.DebugDrawCircle(p1_test, 0.1f, Color.red);
        //TestAlgorithmsHelpMethods.DebugDrawCircle(p2_test, 0.2f, Color.blue);
    }
        //Needles. Triangle where the longest edge is much longer than the shortest one.
        private static bool RemoveNeedle(HalfEdgeData3 meshData, Normalizer3 normalizer = null)
        {
            HashSet <HalfEdgeFace3> triangles = meshData.faces;

            bool foundNeedle = false;

            foreach (HalfEdgeFace3 triangle in triangles)
            {
                /*
                 * List<HalfEdge3> edges = triangle.GetEdges();
                 *
                 * //Sort the edges from shortest to longest
                 * List<HalfEdge3> edgesSorted = edges.OrderBy(e => e.Length()).ToList();
                 *
                 * //The ratio between the shortest and longest side
                 * float edgeLengthRatio = edgesSorted[0].Length() / edgesSorted[2].Length();
                 */

                //Instead of using a million lists, we know we have just three edges we have to sort, so we can do better
                HalfEdge3 e1 = triangle.edge;
                HalfEdge3 e2 = triangle.edge.nextEdge;
                HalfEdge3 e3 = triangle.edge.nextEdge.nextEdge;

                //We want e1 to be the shortest and e3 to be the longest
                if (e1.SqrLength() > e3.SqrLength())
                {
                    (e1, e3) = (e3, e1);
                }

                if (e1.SqrLength() > e2.SqrLength())
                {
                    (e1, e2) = (e2, e1);
                }

                //e1 is now the shortest edge, so we just need to check the second and third

                if (e2.SqrLength() > e3.SqrLength())
                {
                    (e2, e3) = (e3, e2);
                }


                //The ratio between the shortest and longest edge
                float edgeLengthRatio = e1.Length() / e3.Length();

                //This is a needle
                if (edgeLengthRatio < NEEDLE_RATIO)
                {
                    //Debug.Log("We found a needle triangle");

                    TestAlgorithmsHelpMethods.DebugDrawTriangle(triangle, Color.blue, Color.red, normalizer);

                    //Remove the needle by merging the shortest edge
                    MyVector3 mergePosition = (e1.v.position + e1.prevEdge.v.position) * 0.5f;

                    meshData.ContractTriangleHalfEdge(e1, mergePosition);

                    foundNeedle = true;

                    //Now we have to restart because the triangulation has changed
                    break;
                }
            }

            return(foundNeedle);
        }
        //Remove flat tetrahedrons (a vertex in a triangle)
        private static bool RemoveFlatTetrahedrons(HalfEdgeData3 meshData, Normalizer3 normalizer = null)
        {
            HashSet <HalfEdgeVertex3> vertices = meshData.verts;

            bool foundFlatTetrahedron = false;

            foreach (HalfEdgeVertex3 vertex in vertices)
            {
                HashSet <HalfEdge3> edgesGoingToVertex = vertex.GetEdgesPointingToVertex(meshData);

                if (edgesGoingToVertex.Count == 3)
                {
                    //Find the vertices of the triangle covering this vertex clock-wise
                    HalfEdgeVertex3 v1 = vertex.edge.v;
                    HalfEdgeVertex3 v2 = vertex.edge.prevEdge.oppositeEdge.v;
                    HalfEdgeVertex3 v3 = vertex.edge.oppositeEdge.nextEdge.v;

                    //Build a plane
                    MyVector3 normal = MyVector3.Normalize(MyVector3.Cross(v3.position - v2.position, v1.position - v2.position));

                    Plane3 plane = new Plane3(v1.position, normal);

                    //Find the distance from the vertex to the plane
                    float distance = _Geometry.GetSignedDistanceFromPointToPlane(vertex.position, plane);

                    distance = Mathf.Abs(distance);

                    if (distance < FLAT_TETRAHEDRON_DISTANCE)
                    {
                        //Debug.Log("Found flat tetrahedron");

                        Vector3 p1 = normalizer.UnNormalize(v1.position).ToVector3();
                        Vector3 p2 = normalizer.UnNormalize(v2.position).ToVector3();
                        Vector3 p3 = normalizer.UnNormalize(v3.position).ToVector3();

                        TestAlgorithmsHelpMethods.DebugDrawTriangle(p1, p2, p3, normal.ToVector3(), Color.blue, Color.red);

                        foundFlatTetrahedron = true;

                        //Save the opposite edges
                        HashSet <HalfEdge3> oppositeEdges = new HashSet <HalfEdge3>();

                        oppositeEdges.Add(v1.edge.oppositeEdge);
                        oppositeEdges.Add(v2.edge.oppositeEdge);
                        oppositeEdges.Add(v3.edge.oppositeEdge);

                        //Remove the three triangles
                        foreach (HalfEdge3 e in edgesGoingToVertex)
                        {
                            meshData.DeleteFace(e.face);
                        }

                        //Add the new triangle (could maybe connect it ourselves)
                        HalfEdgeFace3 newTriangle = meshData.AddTriangle(v1.position, v2.position, v3.position, findOppositeEdge: false);

                        meshData.TryFindOppositeEdge(newTriangle.edge, oppositeEdges);
                        meshData.TryFindOppositeEdge(newTriangle.edge.nextEdge, oppositeEdges);
                        meshData.TryFindOppositeEdge(newTriangle.edge.nextEdge.nextEdge, oppositeEdges);

                        break;
                    }
                }
            }

            return(foundFlatTetrahedron);
        }