public static bool SplitPolygonsByPlane(List <Polygon> polygons,        // Source polygons that will be split
                                                Plane splitPlane,
                                                bool excludeNewPolygons,        // Whether new polygons should be marked as excludeFromBuild
                                                out List <Polygon> polygonsFront,
                                                out List <Polygon> polygonsBack)
        {
            polygonsFront = new List <Polygon>();
            polygonsBack  = new List <Polygon>();

            // First of all make sure splitting actually needs to occur (we'll get bad issues if
            // we try splitting geometry when we don't need to)
            if (!PolygonsIntersectPlane(polygons, splitPlane))
            {
                return(false);
            }

            Material newMaterial = polygons[0].Material;

            // These are the vertices that will be used in the new caps
            List <Vertex> newVertices = new List <Vertex>();

            for (int polygonIndex = 0; polygonIndex < polygons.Count; polygonIndex++)
            {
                Polygon.PolygonPlaneRelation planeRelation = Polygon.TestPolygonAgainstPlane(polygons[polygonIndex], splitPlane);

                // Polygon has been found to span both sides of the plane, attempt to split into two pieces
                if (planeRelation == Polygon.PolygonPlaneRelation.Spanning)
                {
                    Polygon frontPolygon;
                    Polygon backPolygon;
                    Vertex  newVertex1;
                    Vertex  newVertex2;

                    // Attempt to split the polygon
                    if (Polygon.SplitPolygon(polygons[polygonIndex], out frontPolygon, out backPolygon, out newVertex1, out newVertex2, splitPlane))
                    {
                        // If the split algorithm was successful (produced two valid polygons) then add each polygon to
                        // their respective points and track the intersection points
                        polygonsFront.Add(frontPolygon);
                        polygonsBack.Add(backPolygon);

                        newVertices.Add(newVertex1);
                        newVertices.Add(newVertex2);

                        newMaterial = polygons[polygonIndex].Material;
                    }
                    else
                    {
                        // Two valid polygons weren't generated, so use the valid one
                        if (frontPolygon != null)
                        {
                            planeRelation = Polygon.PolygonPlaneRelation.InFront;
                        }
                        else if (backPolygon != null)
                        {
                            planeRelation = Polygon.PolygonPlaneRelation.Behind;
                        }
                        else
                        {
                            Debug.LogError("Polygon splitting has resulted in two zero area polygons. This is unhandled.");
                            //							Polygon.PolygonPlaneRelation secondplaneRelation = Polygon.TestPolygonAgainstPlane(polygons[polygonIndex], splitPlane);
                        }
                    }
                }

                // If the polygon is on one side of the plane or the other
                if (planeRelation != Polygon.PolygonPlaneRelation.Spanning)
                {
                    // Make sure any points that are coplanar on non-straddling polygons are still used in polygon
                    // construction
                    for (int vertexIndex = 0; vertexIndex < polygons[polygonIndex].Vertices.Length; vertexIndex++)
                    {
                        if (Polygon.ComparePointToPlane(polygons[polygonIndex].Vertices[vertexIndex].Position, splitPlane) == Polygon.PointPlaneRelation.On)
                        {
                            newVertices.Add(polygons[polygonIndex].Vertices[vertexIndex]);
                        }
                    }

                    if (planeRelation == Polygon.PolygonPlaneRelation.Behind)
                    {
                        polygonsBack.Add(polygons[polygonIndex]);
                    }
                    else
                    {
                        polygonsFront.Add(polygons[polygonIndex]);
                    }
                }
            }

            // If any splits occured or coplanar vertices are found. (For example if you're splitting a sphere at the
            // equator then no polygons will be split but there will be a bunch of coplanar vertices!)
            if (newVertices.Count > 0)
            {
                // HACK: This code is awful, because we end up with lots of duplicate vertices
                List <Vector3> positions = newVertices.Select(item => item.Position).ToList();

                Polygon newPolygon = PolygonFactory.ConstructPolygon(positions, true);

                // Assuming it was possible to create a polygon
                if (newPolygon != null)
                {
                    if (!MathHelper.PlaneEqualsLooser(newPolygon.Plane, splitPlane))
                    {
                        // Polygons are sometimes constructed facing the wrong way, possibly due to a winding order
                        // mismatch. If the two normals are opposite, flip the new polygon
                        if (Vector3.Dot(newPolygon.Plane.normal, splitPlane.normal) < -0.9f)
                        {
                            newPolygon.Flip();
                        }
                    }

                    newPolygon.ExcludeFromFinal = excludeNewPolygons;
                    newPolygon.Material         = newMaterial;

                    polygonsFront.Add(newPolygon);

                    newPolygon = newPolygon.DeepCopy();
                    newPolygon.Flip();

                    newPolygon.ExcludeFromFinal = excludeNewPolygons;
                    newPolygon.Material         = newMaterial;


                    if (newPolygon.Plane.normal == Vector3.zero)
                    {
                        Debug.LogError("Invalid Normal! Shouldn't be zero. This is unexpected since extraneous positions should have been removed!");
                        //						Polygon fooNewPolygon = PolygonFactory.ConstructPolygon(positions, true);
                    }

                    polygonsBack.Add(newPolygon);
                }
                return(true);
            }
            else
            {
                // It wasn't possible to create the polygon, for example the constructed polygon was too small
                // This could happen if you attempt to clip the tip off a long but thin brush, the plane-polyhedron test
                // would say they intersect but in reality the resulting polygon would be near zero area
                return(false);
            }
        }
        public static Polygon[] ConnectVertices(Polygon[] polygons, List <Vertex> sourceVertices, out List <Edge> newEdges)
        {
            List <Polygon> newPolygons = new List <Polygon>(polygons);

            newEdges = new List <Edge>();

            for (int i = 0; i < newPolygons.Count; i++)
            {
                // Source vertices on the polygon
                int matchedIndex1 = -1;
                int matchedIndex2 = -1;

                for (int j = 0; j < sourceVertices.Count; j++)
                {
                    int index = System.Array.IndexOf(newPolygons[i].Vertices, sourceVertices[j]);

                    if (index != -1)
                    {
                        if (matchedIndex1 == -1)
                        {
                            matchedIndex1 = index;
                        }
                        else if (matchedIndex2 == -1)
                        {
                            matchedIndex2 = index;
                        }
                    }
                }

                // Check that found two valid points and that they're not neighbours
                // (neighbouring vertices can't be connected as they already are by an edge)
                if (matchedIndex1 != -1 && matchedIndex2 != -1 &&
                    !AreNeighbours(matchedIndex1, matchedIndex2, newPolygons[i].Vertices.Length))
                {
//					Vertex neighbourVertex = newPolygons[i].Vertices[(matchedIndex1 + 1) % newPolygons[i].Vertices.Length];
//
//					Vector3 vector1 = newPolygons[i].Vertices[matchedIndex1].Position - neighbourVertex.Position;
//					Vector3 vector2 = newPolygons[i].Vertices[matchedIndex2].Position - newPolygons[i].Vertices[matchedIndex1].Position;
//					Vector3 normal = Vector3.Cross(vector1, vector2).normalized;
//
//					Vector3 thirdPoint = newPolygons[i].Vertices[matchedIndex1].Position + normal;
                    Vector3 thirdPoint = newPolygons[i].Vertices[matchedIndex1].Position + newPolygons[i].Plane.normal;

                    // First split the shared polygon
                    Plane splitPlane = new Plane(newPolygons[i].Vertices[matchedIndex1].Position, newPolygons[i].Vertices[matchedIndex2].Position, thirdPoint);

                    Polygon splitPolygon1;
                    Polygon splitPolygon2;
                    Vertex  newVertex1;
                    Vertex  newVertex2;

                    if (Polygon.SplitPolygon(newPolygons[i], out splitPolygon1, out splitPolygon2, out newVertex1, out newVertex2, splitPlane))
                    {
                        newPolygons[i] = splitPolygon1;
                        newPolygons.Insert(i + 1, splitPolygon2);
                        // Skip over new polygon
                        i++;
                        newEdges.Add(new Edge(newVertex1, newVertex2));
                    }
                    else
                    {
                        Debug.LogWarning("Split polygon failed");
                    }
                }
            }
            return(newPolygons.ToArray());
        }
示例#3
0
        internal static bool SplitCoplanarPolygonsByPlane(List <Polygon> polygons, // Source polygons that will be split
                                                          Plane splitPlane,
                                                          out List <Polygon> polygonsFront,
                                                          out List <Polygon> polygonsBack)
        {
            polygonsFront = new List <Polygon>();
            polygonsBack  = new List <Polygon>();

            for (int polygonIndex = 0; polygonIndex < polygons.Count; polygonIndex++)
            {
                Polygon.PolygonPlaneRelation planeRelation = Polygon.TestPolygonAgainstPlane(polygons[polygonIndex], splitPlane);

                // Polygon has been found to span both sides of the plane, attempt to split into two pieces
                if (planeRelation == Polygon.PolygonPlaneRelation.Spanning)
                {
                    Polygon frontPolygon;
                    Polygon backPolygon;
                    Vertex  newVertex1;
                    Vertex  newVertex2;

                    // Attempt to split the polygon
                    if (Polygon.SplitPolygon(polygons[polygonIndex], out frontPolygon, out backPolygon, out newVertex1, out newVertex2, splitPlane))
                    {
                        // If the split algorithm was successful (produced two valid polygons) then add each polygon to
                        // their respective points and track the intersection points
                        polygonsFront.Add(frontPolygon);
                        polygonsBack.Add(backPolygon);
                    }
                    else
                    {
                        // Two valid polygons weren't generated, so use the valid one
                        if (frontPolygon != null)
                        {
                            planeRelation = Polygon.PolygonPlaneRelation.InFront;
                        }
                        else if (backPolygon != null)
                        {
                            planeRelation = Polygon.PolygonPlaneRelation.Behind;
                        }
                        else
                        {
                            planeRelation = Polygon.PolygonPlaneRelation.InFront;

                            Debug.LogError("Polygon splitting has resulted in two zero area polygons. This is unhandled.");
                            //							Polygon.PolygonPlaneRelation secondplaneRelation = Polygon.TestPolygonAgainstPlane(polygons[polygonIndex], splitPlane);
                        }
                    }
                }

                // If the polygon is on one side of the plane or the other
                if (planeRelation != Polygon.PolygonPlaneRelation.Spanning)
                {
                    if (planeRelation == Polygon.PolygonPlaneRelation.Behind)
                    {
                        polygonsBack.Add(polygons[polygonIndex]);
                    }
                    else
                    {
                        polygonsFront.Add(polygons[polygonIndex]);
                    }
                }
            }

            if (polygonsBack.Count >= 1 &&
                polygonsFront.Count >= 1)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
示例#4
0
        public static bool SplitPolygonsByEdges(Polygon[] polygons, List <Edge> sourceEdges, out Polygon[] finalPolygons, out List <Edge> newEdges)
        {
            // First of all refine the list of edges to those that are on the polygons and share a polygon with another specified edge
            // Verification step, no more than two edges should be selected per face

            // Once the list of edges is refined, walk through each set of polygons
            // Where a polygon has two specified edges, it needs to be split in two
            // Where a polygon has one specified edge, it needs a vertex to be added
            List <Polygon> newPolygons = new List <Polygon>(polygons); // Complete set of new polygons

            newEdges = new List <Edge>();                              // These are the new edges we create

            List <Edge> edges = new List <Edge>();

            // Pull out a list of edges that occur on any of the polygons at least twice.
            // This way we ignore edges on other brushes or edges which aren't possible to connect via a polygon
            for (int edge1Index = 0; edge1Index < sourceEdges.Count; edge1Index++)
            {
                bool found = false;

                for (int i = 0; i < polygons.Length && !found; i++)
                {
                    Edge edge1 = sourceEdges[edge1Index];

                    for (int edge2Index = 0; edge2Index < sourceEdges.Count && !found; edge2Index++)
                    {
                        if (edge2Index != edge1Index)                        // Skip the same edge
                        {
                            Edge edge2 = sourceEdges[edge2Index];

                            bool edge1Contained = Polygon.ContainsEdge(polygons[i], edge1);
                            bool edge2Contained = Polygon.ContainsEdge(polygons[i], edge2);

                            if (edge1Contained && edge2Contained)
                            {
                                if (!edges.Contains(edge1))
                                {
                                    edges.Add(edge1);
                                }

                                if (!edges.Contains(edge2))
                                {
                                    edges.Add(edge2);
                                }
                                found = true;
                            }
                        }
                    }
                }
            }

            // Now process each polygon
            for (int i = 0; i < polygons.Length; i++)
            {
                Polygon polygon = polygons[i];

                List <Edge> edgesOnPolygon = new List <Edge>();
                for (int edgeIndex = 0; edgeIndex < edges.Count; edgeIndex++)
                {
                    Edge edge = edges[edgeIndex];
                    if (Polygon.ContainsEdge(polygon, edge))
                    {
                        edgesOnPolygon.Add(edge);
                    }
                }

                if (edgesOnPolygon.Count == 1)
                {
                    Vertex newVertex;
                    // Add vertex
                    if (!SplitPolygonAtEdge(polygon, edgesOnPolygon[0], out newVertex))
                    {
                        Debug.LogError("Could not add vertex to adjacent polygon");
                    }
                }
                else if (edgesOnPolygon.Count == 2)
                {
                    // Split into two
                    Edge edge1 = edgesOnPolygon[0];
                    Edge edge2 = edgesOnPolygon[1];

                    // First split the shared polygon
                    Vector3 edge1Center = edge1.GetCenterPoint();
                    Vector3 edge2Center = edge2.GetCenterPoint();

                    Vector3 thirdPoint = edge1Center + polygon.Plane.normal;

                    Plane splitPlane = new Plane(edge1Center, edge2Center, thirdPoint);

                    Polygon splitPolygon1;
                    Polygon splitPolygon2;
                    Vertex  edge1Vertex;
                    Vertex  edge2Vertex;

                    Polygon.SplitPolygon(polygon, out splitPolygon1, out splitPolygon2, out edge1Vertex, out edge2Vertex, splitPlane);

                    newEdges.Add(new Edge(edge1Vertex, edge2Vertex));
                    newPolygons.Remove(polygon);
                    newPolygons.Add(splitPolygon1);
                    newPolygons.Add(splitPolygon2);
                }
            }

            finalPolygons = newPolygons.ToArray();

            return(true);
        }