Пример #1
0
        public static List <Vertices> ConvexPartition(Vertices vertices, TriangulationAlgorithm algorithm, bool discardAndFixInvalid = true, float tolerance = 0.001f)
        {
            if (vertices.Count <= 3)
            {
                return new List <Vertices> {
                           vertices
                }
            }
            ;

            List <Vertices> results = null;

            switch (algorithm)
            {
            case TriangulationAlgorithm.Earclip:
#pragma warning disable 162
                // ReSharper disable three ConditionIsAlwaysTrueOrFalse
                if (Settings.SkipSanityChecks)
                {
                    Debug.Assert(!vertices.IsCounterClockWise(), "The Ear-clip algorithm expects the polygon to be clockwise.");
                }
                else
                {
                    if (vertices.IsCounterClockWise())
                    {
                        Vertices temp = new Vertices(vertices);
                        temp.Reverse();
                        results = EarclipDecomposer.ConvexPartition(temp, tolerance);
                    }
                    else
                    {
                        results = EarclipDecomposer.ConvexPartition(vertices, tolerance);
                    }
                }
                break;

            case TriangulationAlgorithm.Bayazit:
                if (Settings.SkipSanityChecks)
                {
                    Debug.Assert(vertices.IsCounterClockWise(), "The polygon is not counter clockwise. This is needed for Bayazit to work correctly.");
                }
                else
                {
                    if (!vertices.IsCounterClockWise())
                    {
                        Vertices temp = new Vertices(vertices);
                        temp.Reverse();
                        results = BayazitDecomposer.ConvexPartition(temp);
                    }
                    else
                    {
                        results = BayazitDecomposer.ConvexPartition(vertices);
                    }
                }
                break;

            case TriangulationAlgorithm.Flipcode:
                if (Settings.SkipSanityChecks)
                {
                    Debug.Assert(vertices.IsCounterClockWise(), "The polygon is not counter clockwise. This is needed for Bayazit to work correctly.");
                }
#pragma warning restore 162
                else
                {
                    if (!vertices.IsCounterClockWise())
                    {
                        Vertices temp = new Vertices(vertices);
                        temp.Reverse();
                        results = FlipcodeDecomposer.ConvexPartition(temp);
                    }
                    else
                    {
                        results = FlipcodeDecomposer.ConvexPartition(vertices);
                    }
                }
                break;

            case TriangulationAlgorithm.Seidel:
                results = SeidelDecomposer.ConvexPartition(vertices, tolerance);
                break;

            case TriangulationAlgorithm.SeidelTrapezoids:
                results = SeidelDecomposer.ConvexPartitionTrapezoid(vertices, tolerance);
                break;

            case TriangulationAlgorithm.Delauny:
                results = CDTDecomposer.ConvexPartition(vertices);
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(algorithm));
            }

            if (discardAndFixInvalid)
            {
                for (int i = results.Count - 1; i >= 0; i--)
                {
                    Vertices polygon = results[i];

                    if (!ValidatePolygon(polygon))
                    {
                        results.RemoveAt(i);
                    }
                }
            }

            return(results);
        }
Пример #2
0
        /// <summary>
        /// Creates a mesh out of a polygon.
        /// </summary>
        /// <param name="vertices">Boundary vertices of the polygon.</param>
        /// <param name="holes">Hole vertices of the polygon if any.</param>
        /// <returns></returns>
        public static Mesh CreatePolygonMesh(List <Vector2> vertices, List <List <Vector2> > holes = null)
        {
            // split the polygon into convex parts so we can use fan triangulation https://en.wikipedia.org/wiki/Fan_triangulation
            List <List <Vector2> > convexPolygons = CDTDecomposer.ConvexPartition(vertices, holes);

            //Debug.Log("Polygon is split into " + convexPolygons.Count + " parts");
            // create mesh arrays
            List <List <Vector3> > meshVerticesList  = new List <List <Vector3> >();
            List <List <Vector3> > meshNormalsList   = new List <List <Vector3> >();
            List <List <int> >     meshTrianglesList = new List <List <int> >();

            for (int i = 0; i < convexPolygons.Count; i++)
            {
                // map 2d vertices of the polygon to 3d on the 0-plane
                List <Vector3> polygon3D = new List <Vector3>();
                foreach (var vertex in convexPolygons[i])
                {
                    polygon3D.Add(new Vector3(vertex.x, 0, vertex.y));
                }
                meshVerticesList.Add(polygon3D);
                // fan triangulation
                List <int> triangles = new List <int>();
                for (int k = 1; k < polygon3D.Count - 1; k++)
                {
                    triangles.Add(0);
                    triangles.Add(k);
                    triangles.Add(k + 1);
                }
                meshTrianglesList.Add(triangles);
            }
            // let all normals point up as this is only in 2D
            foreach (var meshVertices in meshVerticesList)
            {
                meshNormalsList.Add(new List <Vector3>(new Vector3[meshVertices.Count]));
            }
            foreach (var meshNormalList in meshNormalsList)
            {
                for (int i = 0; i < meshNormalList.Count; i++)
                {
                    meshNormalList[i] = Vector3.up;
                }
            }
            CombineInstance[] combinedMeshes = new CombineInstance[convexPolygons.Count];
            for (int i = 0; i < convexPolygons.Count; i++)
            {
                // create a mesh for each convex polygon
                Mesh meshPart = new Mesh();
                meshPart.vertices           = meshVerticesList[i].ToArray();
                meshPart.normals            = meshNormalsList[i].ToArray();
                meshPart.triangles          = meshTrianglesList[i].ToArray();
                combinedMeshes[i].mesh      = meshPart;
                combinedMeshes[i].transform = Matrix4x4.identity;
            }
            // combine the meshes to one mesh
            Mesh mesh = new Mesh();

            mesh.CombineMeshes(combinedMeshes);
            mesh.RecalculateBounds();
            mesh.RecalculateNormals();
            return(mesh);
        }