public static bool PlanePolygonIntersection(Polygon polygon, out Vector3 position1, out Vector3 position2, UnityEngine.Plane testPlane) { position1 = Vector3.zero; position2 = Vector3.zero; bool position1Set = false; bool position2Set = false; for (int i = 0; i < polygon.vertices.Length; i++) { int previousIndex = i - 1; if (previousIndex < 0) { previousIndex = polygon.vertices.Length - 1; } Vertex currentVertex = polygon.vertices[i]; Vertex previousVertex = polygon.vertices[previousIndex]; PointPlaneRelation currentRelation = ComparePointToPlane(currentVertex.Position, testPlane); PointPlaneRelation previousRelation = ComparePointToPlane(previousVertex.Position, testPlane); if (previousRelation == PointPlaneRelation.InFront && currentRelation == PointPlaneRelation.InFront) { } else if (previousRelation == PointPlaneRelation.Behind && currentRelation == PointPlaneRelation.InFront) { float interpolant = Edge.IntersectsPlane(testPlane, previousVertex.Position, currentVertex.Position); position2 = Vector3.Lerp(previousVertex.Position, currentVertex.Position, interpolant); position2Set = true; } else if (previousRelation == PointPlaneRelation.InFront && currentRelation == PointPlaneRelation.Behind) { // Reverse order here so that clipping remains consistent for either CW or CCW testing float interpolant = Edge.IntersectsPlane(testPlane, currentVertex.Position, previousVertex.Position); position1 = Vector3.Lerp(currentVertex.Position, previousVertex.Position, interpolant); position1Set = true; } else if (previousRelation == PointPlaneRelation.Behind && currentRelation == PointPlaneRelation.Behind) { } else if (currentRelation == PointPlaneRelation.On) { if (previousRelation == PointPlaneRelation.InFront) { position1 = currentVertex.Position; position1Set = true; } else if (previousRelation == PointPlaneRelation.Behind) { position2 = currentVertex.Position; position2Set = true; } else { // throw new System.Exception("Unhandled polygon configuration"); } } else if (currentRelation == PointPlaneRelation.Behind) { } else if (currentRelation == PointPlaneRelation.InFront) { } else { } } return(position1Set && position2Set); }
public static bool SplitPolygon(Polygon polygon, out Polygon frontPolygon, out Polygon backPolygon, out Vertex newVertex1, out Vertex newVertex2, UnityEngine.Plane clipPlane) { newVertex1 = null; newVertex2 = null; List <Vertex> frontVertices = new List <Vertex>(); List <Vertex> backVertices = new List <Vertex>(); for (int i = 0; i < polygon.vertices.Length; i++) { int previousIndex = i - 1; if (previousIndex < 0) { previousIndex = polygon.vertices.Length - 1; } Vertex currentVertex = polygon.vertices[i]; Vertex previousVertex = polygon.vertices[previousIndex]; PointPlaneRelation currentRelation = ComparePointToPlane(currentVertex.Position, clipPlane); PointPlaneRelation previousRelation = ComparePointToPlane(previousVertex.Position, clipPlane); if (previousRelation == PointPlaneRelation.InFront && currentRelation == PointPlaneRelation.InFront) { // Front add current frontVertices.Add(currentVertex); } else if (previousRelation == PointPlaneRelation.Behind && currentRelation == PointPlaneRelation.InFront) { float interpolant = Edge.IntersectsPlane(clipPlane, previousVertex.Position, currentVertex.Position); Vertex intersection = Vertex.Lerp(previousVertex, currentVertex, interpolant); // Front add intersection, add current frontVertices.Add(intersection); frontVertices.Add(currentVertex); // Back add intersection backVertices.Add(intersection.DeepCopy()); newVertex2 = intersection; } else if (previousRelation == PointPlaneRelation.InFront && currentRelation == PointPlaneRelation.Behind) { // Reverse order here so that clipping remains consistent for either CW or CCW testing float interpolant = Edge.IntersectsPlane(clipPlane, currentVertex.Position, previousVertex.Position); Vertex intersection = Vertex.Lerp(currentVertex, previousVertex, interpolant); // Front add intersection frontVertices.Add(intersection); // Back add intersection, current backVertices.Add(intersection.DeepCopy()); backVertices.Add(currentVertex); newVertex1 = intersection; } else if (previousRelation == PointPlaneRelation.Behind && currentRelation == PointPlaneRelation.Behind) { // Back add current backVertices.Add(currentVertex); } else if (currentRelation == PointPlaneRelation.On) { // Front add current frontVertices.Add(currentVertex); // Back add current backVertices.Add(currentVertex.DeepCopy()); if (previousRelation == PointPlaneRelation.InFront) { newVertex1 = currentVertex; } else if (previousRelation == PointPlaneRelation.Behind) { newVertex2 = currentVertex; } else { // throw new System.Exception("Unhandled polygon configuration"); } } else if (currentRelation == PointPlaneRelation.Behind) { backVertices.Add(currentVertex); } else if (currentRelation == PointPlaneRelation.InFront) { frontVertices.Add(currentVertex); } else { throw new System.Exception("Unhandled polygon configuration"); } } // Debug.Log("done"); frontPolygon = new Polygon(frontVertices.ToArray(), polygon.Material, polygon.ExcludeFromFinal, polygon.UserExcludeFromFinal, polygon.uniqueIndex); backPolygon = new Polygon(backVertices.ToArray(), polygon.Material, polygon.ExcludeFromFinal, polygon.UserExcludeFromFinal, polygon.uniqueIndex); // Because of some floating point issues and some edge cases relating to splitting the tip of a very thin // polygon we can't reliable test that the polygon intersects a plane and will produce two valid pieces // so after splitting we need to do an additional test to check that each polygon is valid. If it isn't // then we mark that polygon as null and return false to indicate the split wasn't entirely successful bool splitNecessary = true; if (frontPolygon.vertices.Length < 3 || frontPolygon.Plane.normal == Vector3.zero) { frontPolygon = null; splitNecessary = false; } if (backPolygon.vertices.Length < 3 || backPolygon.Plane.normal == Vector3.zero) { backPolygon = null; splitNecessary = false; } return(splitNecessary); }