Ejemplo n.º 1
0
        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;
                }
            }
        }
Ejemplo n.º 2
0
        // 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;
                }
            }
        }