private void ComputeAllSegments() { allSegments.Clear(); for (int i = 0; i < 4; ++i) { circleInter[i] = GetInterWithNextCircle(i); } if (seedInter.type == RaySphereIntersection.eType.None) { return; } int firstIndex = GetFirstIntersectingPlane(-1); if (firstIndex == -1) { // sphere is fully visible, the backCircle is the only circle segment // just take the point closest to any side plane as start Vector3 start = backPlaneInter.ProjectOnCircle(plane[0].ProjectedPoint(center)); allSegments.Add(new CircleSegment(backPlaneInter.onPlane, backPlane.normal, start, 360)); return; } var lsb = new List <SegmentBuilder>(); for (int i = 0; i < 4; ++i) { if (planeInter[i].type != PlaneSphereIntersection.eType.Circle) { continue; } Vector3 s, e; GetPointsForCircleIntersection(i, out s, out e); if (IsVisible(e) || IsVisible(s)) { lsb.Add(new SegmentBuilder(i, s, e)); } } for (var index = 0; index < lsb.Count; index++) { SegmentBuilder builder = lsb[index]; builder.BuildSegment(this); if (!circleInter[builder.planeIndex].HasValue) { // that segment doesn't end on a side circle, // we have to make the junction with the next one SegmentBuilder nextBuilder = lsb[(index + 1) % lsb.Count]; SegmentBuilder junction = new SegmentBuilder(-1, builder.end, nextBuilder.start); junction.BuildSegment(this); } } }
public void Compute() { main.CalculateFrustumCorners(main.rect, main.farClipPlane, Camera.MonoOrStereoscopicEye.Mono, corners); //centerInter = new RaySphereIntersection(camPosition, center-camPosition, center, radius); // compute world space coordinates for frustum for (var index = 0; index < 4; index++) { corners[index] = camTransform.TransformPoint(corners[index]); } corners[4] = corners[0]; Vector3 p0 = camPosition; float distanceSqr = (p0 - center).sqrMagnitude; if (distanceSqr > radius * radius) { backPlane = Plane.SphereBackPlaneSeenFromPosition(p0, center, radius); backPlaneInter = new PlaneSphereIntersection(backPlane, center, radius); seed = center; for (int i = 0; i < 4; ++i) { Vector3 p1 = corners[i]; Vector3 p2 = corners[i + 1]; Plane p = new Plane(p0, p2, p1); p.SetName(Vector3.Lerp(p1, p2, 0.5f), "SidePl" + i); plane[i] = p; planeInter[i] = new PlaneSphereIntersection(p, center, radius); cornersInter[i] = new RaySphereIntersection(p0, p1 - p0, center, radius); moved[i] = MoveToPlaneIfOnNegativeSide(ref plane[i], ref seed); } seedInter = new RaySphereIntersection(camPosition, seed - camPosition, center, radius); ComputeAllSegments(); } else { for (int i = 0; i < 4; ++i) { Vector3 p1 = corners[i]; Vector3 p2 = corners[i + 1]; Plane p = new Plane(p0, p1, p2); p.SetName(Vector3.Lerp(p1, p2, 0.5f), "SidePl" + i); plane[i] = p; planeInter[i] = new PlaneSphereIntersection(p, center, radius); cornersInter[i] = new RaySphereIntersection(p0, p1 - p0, center, radius); } allSegments.Clear(); for (int i = 0; i < 4; ++i) { Vector3 start = cornersInter[i].I; Vector3 end = cornersInter.Modulo(i + 1).I; SegmentBuilder builder = new SegmentBuilder(i, start, end); builder.BuildSegment(this); } } barycenter = Vector3.zero; if (allSegments.Count > 0) { foreach (CircleSegment circleSegment in allSegments) { //for(float angle = 0; angle < circleSegment.angle; angle += 5) { barycenter += circleSegment.Start; } } barycenter /= allSegments.Count; barycenter = center + (barycenter - center).normalized * radius; } }