public void Intersect(AABB cuttingNodeBounds, Plane[] cuttingNodePlanes, Vector3 cuttingNodeTranslation, Vector3 inputPolygonTranslation, List<Polygon> inputPolygons, List<Polygon> inside, List<Polygon> aligned, List<Polygon> revAligned, List<Polygon> outside) { var categories = new PolygonSplitResult[cuttingNodePlanes.Length]; var translatedPlanes = new Plane[cuttingNodePlanes.Length]; var translation = Vector3.Subtract(cuttingNodeTranslation, inputPolygonTranslation); // translate the planes we cut our polygons with so that they're located at the same // relative distance from the polygons as the brushes are from each other. for (int i = 0; i < cuttingNodePlanes.Length; i++) translatedPlanes[i] = Plane.Translated(cuttingNodePlanes[i], translation); var vertices = this.Vertices; var edges = this.Edges; var planes = this.Planes; for (int i = inputPolygons.Count - 1; i >= 0; i--) { var inputPolygon = inputPolygons[i]; if (inputPolygon.FirstIndex == -1) continue; var bounds = inputPolygon.Bounds; var finalResult = PolygonSplitResult.CompletelyInside; // A quick check if the polygon lies outside the planes we're cutting our polygons with. if (!AABB.IsOutside(cuttingNodeBounds, translation, bounds)) { PolygonSplitResult intermediateResult; Polygon outsidePolygon = null; for (int otherIndex = 0; otherIndex < translatedPlanes.Length; otherIndex++) { var translatedCuttingPlane = translatedPlanes[otherIndex]; var side = cuttingNodePlanes[otherIndex].OnSide(bounds, translation.Negated()); if (side == PlaneSideResult.Outside) { finalResult = PolygonSplitResult.CompletelyOutside; break; // nothing left to process, so we exit } else if (side == PlaneSideResult.Inside) continue; var polygon = inputPolygon; intermediateResult = PolygonSplit(translatedCuttingPlane, inputPolygonTranslation, ref polygon, out outsidePolygon); inputPolygon = polygon; if (intermediateResult == PolygonSplitResult.CompletelyOutside) { finalResult = PolygonSplitResult.CompletelyOutside; break; // nothing left to process, so we exit } else if (intermediateResult == PolygonSplitResult.Split) { if (outside != null) outside.Add(outsidePolygon); // Note: left over is still completely inside, // or plane (opposite) aligned } else if (intermediateResult != PolygonSplitResult.CompletelyInside) finalResult = intermediateResult; } } else finalResult = PolygonSplitResult.CompletelyOutside; switch (finalResult) { case PolygonSplitResult.CompletelyInside: inside .Add(inputPolygon); break; case PolygonSplitResult.CompletelyOutside: outside.Add(inputPolygon); break; // The polygon can only be visible if it's part of the last brush that shares it's surface area, // otherwise we'd get overlapping polygons if two brushes overlap. // When the (final) polygon is aligned with one of the cutting planes, we know it lies on the surface of // the CSG node we're cutting the polygons with. We also know that this node is not the node this polygon belongs to // because we've done that check earlier on. So we flag this polygon as being invisible. case PolygonSplitResult.PlaneAligned: inputPolygon.Visible = false; aligned .Add(inputPolygon); break; case PolygonSplitResult.PlaneOppositeAligned: inputPolygon.Visible = false; revAligned.Add(inputPolygon); break; } } }
// Intersects a mesh with a brush (set of planes) #region Intersect public void Intersect(AABB cuttingNodeBounds, Plane[] cuttingNodePlanes, Vector3 cuttingNodeTranslation, Vector3 inputPolygonTranslation, List <Polygon> inputPolygons, List <Polygon> inside, List <Polygon> aligned, List <Polygon> revAligned, List <Polygon> outside) { var categories = new PolygonSplitResult[cuttingNodePlanes.Length]; var translatedPlanes = new Plane[cuttingNodePlanes.Length]; var translation = Vector3.Subtract(cuttingNodeTranslation, inputPolygonTranslation); // translate the planes we cut our polygons with so that they're located at the same // relative distance from the polygons as the brushes are from each other. for (int i = 0; i < cuttingNodePlanes.Length; i++) { translatedPlanes[i] = Plane.Translated(cuttingNodePlanes[i], translation); } var vertices = this.Vertices; var edges = this.Edges; var planes = this.Planes; for (int i = inputPolygons.Count - 1; i >= 0; i--) { var inputPolygon = inputPolygons[i]; if (inputPolygon.FirstIndex == -1) { continue; } var bounds = inputPolygon.Bounds; var finalResult = PolygonSplitResult.CompletelyInside; // A quick check if the polygon lies outside the planes we're cutting our polygons with. if (!AABB.IsOutside(cuttingNodeBounds, translation, bounds)) { PolygonSplitResult intermediateResult; Polygon outsidePolygon = null; for (int otherIndex = 0; otherIndex < translatedPlanes.Length; otherIndex++) { var translatedCuttingPlane = translatedPlanes[otherIndex]; var side = cuttingNodePlanes[otherIndex].OnSide(bounds, -translation); if (side == PlaneSideResult.Outside) { finalResult = PolygonSplitResult.CompletelyOutside; break; // nothing left to process, so we exit } else if (side == PlaneSideResult.Inside) { continue; } var polygon = inputPolygon; intermediateResult = PolygonSplit(translatedCuttingPlane, inputPolygonTranslation, ref polygon, out outsidePolygon); inputPolygon = polygon; if (intermediateResult == PolygonSplitResult.CompletelyOutside) { finalResult = PolygonSplitResult.CompletelyOutside; break; // nothing left to process, so we exit } else if (intermediateResult == PolygonSplitResult.Split) { if (outside != null) { outside.Add(outsidePolygon); } // Note: left over is still completely inside, // or plane (opposite) aligned } else if (intermediateResult != PolygonSplitResult.CompletelyInside) { finalResult = intermediateResult; } } } else { finalResult = PolygonSplitResult.CompletelyOutside; } switch (finalResult) { case PolygonSplitResult.CompletelyInside: inside.Add(inputPolygon); break; case PolygonSplitResult.CompletelyOutside: outside.Add(inputPolygon); break; // The polygon can only be visible if it's part of the last brush that shares it's surface area, // otherwise we'd get overlapping polygons if two brushes overlap. // When the (final) polygon is aligned with one of the cutting planes, we know it lies on the surface of // the CSG node we're cutting the polygons with. We also know that this node is not the node this polygon belongs to // because we've done that check earlier on. So we flag this polygon as being invisible. case PolygonSplitResult.PlaneAligned: inputPolygon.Visible = false; aligned.Add(inputPolygon); break; case PolygonSplitResult.PlaneOppositeAligned: inputPolygon.Visible = false; revAligned.Add(inputPolygon); break; } } }