void Update() { //{ // pointDisplay.transform.position = pointPosition; // pointDisplay.transform.localScale = 0.1f * Vector3.one; // Vector3? intersection = Math.Geometry.Intersections.Intersects(frustum, pointPosition); // if (intersection.HasValue) // { // pointDisplay.GetComponent<Renderer>().material = insideMaterial; // } // else // { // pointDisplay.GetComponent<Renderer>().material = outsideMaterial; // } //} //sphereCameraPlaneDisplay.transform.position = spherePosition; //sphereCameraPlaneDisplay.transform.rotation = Quaternion.FromToRotation(Vector3.up, cameraPosition - spherePosition); { sphereDisplay.transform.position = spherePosition; sphereDisplay.transform.localScale = 2f * sphereRadius * Vector3.one; bool intersects = Math.Geometry.Intersections.Intersects(frustum, new Math.Geometry.Sphere(spherePosition, sphereRadius)).All((intersection) => intersection != null); if (intersects) { sphereDisplay.GetComponent <Renderer>().material = insideMaterial; } else { sphereDisplay.GetComponent <Renderer>().material = outsideMaterial; } } int countInside = 0; for (int i = 0; i < samples.Length; i++) { Vector3 position = samples[i] * sphereRadius + spherePosition; bool inside = true; if (!Math.Geometry.Intersections.Intersects(frustum, position).HasValue) { inside = false; } Vector3 cameraPlaneNormal = (cameraPosition - spherePosition).normalized; Math.Geometry.Plane plane = new Math.Geometry.Plane(cameraPlaneNormal, -Vector3.Dot(cameraPlaneNormal, spherePosition)); if (plane.PlaneEquation(position) < 0.0f) { inside = false; } if (inside) { countInside += 1; } } debugText.text = "Area visible: " + ((float)countInside / samples.Length * 100f) + "%"; }
void OnDrawGizmos() { if (sphereDisplay) { sphereDisplay.transform.position = spherePosition; sphereDisplay.transform.localScale = 2f * sphereRadius * Vector3.one; sphereDisplay.GetComponent <Renderer>().material = insideMaterial; } //Math.Geometry.Intersections.FrustumSphereIntersection?[] intersections = Math.Geometry.Intersections.Intersects(frustum, new Math.Geometry.Sphere(spherePosition, sphereRadius)); //foreach (Math.Geometry.Intersections.FrustumSphereIntersection intersection in intersections.Where((intersection) => intersection.HasValue).Select((intersection) => intersection.Value)) //{ // Gizmos.color = Color.blue; // Gizmos.DrawLine(spherePosition + intersection.normal * sphereRadius, spherePosition - intersection.normal * intersection.distance); //} //Vector3[] vertices = sphereDisplay.GetComponent<MeshFilter>().mesh.vertices; //foreach (Vector3 vertex in vertices) //{ // Vector3 position = sphereDisplay.transform.TransformPoint(vertex); // Color color = Color.green; // for (int i = 0; i < 6; i++) // { // if (frustum[i].PlaneEquation(position) < 0.0f) // { // color = Color.red; // } // } // Vector3 cameraPlaneNormal = (cameraPosition - spherePosition).normalized; // // if (new Geometry.Plane(cameraPlaneNormal, -Vector3.Dot(cameraPlaneNormal, spherePosition)).PlaneEquation(position) < 0.0f) // if (Vector3.Dot(cameraPlaneNormal, position) - Vector3.Dot(cameraPlaneNormal, spherePosition) < 0.0f) // { // color = Color.red; // } // Gizmos.color = color; // Gizmos.DrawSphere(position, 0.05f); //} { Vector3 cameraPosition = Camera.main.transform.position; // Vector3 cameraPlaneNormal = (cameraPosition - spherePosition).normalized; Vector3 cameraPlaneNormal = GeometryUtility.CalculateFrustumPlanes(Camera.main)[5].normal.normalized; // Math.Geometry.Plane plane = new Math.Geometry.Plane(cameraPlaneNormal, -Vector3.Dot(cameraPlaneNormal, spherePosition)); Math.Geometry.Plane plane = new Math.Geometry.Plane(cameraPlaneNormal, -Vector3.Dot(cameraPlaneNormal, cameraPosition - cameraPlaneNormal * Vector3.Distance(spherePosition, cameraPosition))); Gizmos.color = Color.blue; Gizmos.DrawLine(spherePosition + plane.normal * sphereRadius, spherePosition - plane.normal * plane.PlaneEquation(spherePosition)); // Math.Geometry.Plane plane = frustum.bottom; Vector3 closestPointOnPlane = spherePosition - plane.PlaneEquation(spherePosition) * plane.normal; // Vector3 perpendicularPlaneNormal = new Vector3(1f, 1f, -(plane.normal.x + plane.normal.y) / plane.normal.z).normalized; float theta = Mathf.Acos(plane.normal.z) + Mathf.PI / 2f; float phi = Mathf.Atan2(plane.normal.y, plane.normal.x); // Debug.Log(theta + " " + phi); // Vector3 planePerpendicular1 = new Vector3(Mathf.Sin(theta) * Mathf.Cos(phi), Mathf.Sin(theta) * Mathf.Sin(phi), Mathf.Cos(theta)); Vector3 planePerpendicular1 = Vector3.Cross(Camera.main.transform.up.normalized, -plane.normal); Vector3 planePerpendicular2 = Vector3.Cross(planePerpendicular1, plane.normal); float halfHeightAtSphere = Vector3.Distance(spherePosition, cameraPosition) * Mathf.Tan(Camera.main.fieldOfView * Mathf.Deg2Rad / 2f); float halfWidthAtSphere = halfHeightAtSphere * Camera.main.aspect; float intersectionCircleRadius = Mathf.Sqrt(Mathf.Pow(sphereRadius, 2) - Mathf.Pow(plane.PlaneEquation(spherePosition), 2)); Gizmos.color = Color.magenta; Gizmos.DrawSphere(closestPointOnPlane, 0.1f); Gizmos.DrawSphere(closestPointOnPlane + planePerpendicular1 * intersectionCircleRadius, 0.1f); Gizmos.DrawSphere(closestPointOnPlane + planePerpendicular2 * intersectionCircleRadius, 0.1f); Mesh mesh = new Mesh(); mesh.vertices = new Vector3[] { cameraPosition - plane.normal * Vector3.Distance(spherePosition, cameraPosition) + planePerpendicular1 * halfWidthAtSphere + planePerpendicular2 * halfHeightAtSphere, cameraPosition - plane.normal * Vector3.Distance(spherePosition, cameraPosition) + planePerpendicular1 * halfWidthAtSphere + planePerpendicular2 * -halfHeightAtSphere, cameraPosition - plane.normal * Vector3.Distance(spherePosition, cameraPosition) + planePerpendicular1 * -halfWidthAtSphere + planePerpendicular2 * -halfHeightAtSphere, cameraPosition - plane.normal * Vector3.Distance(spherePosition, cameraPosition) + planePerpendicular1 * -halfWidthAtSphere + planePerpendicular2 * halfHeightAtSphere }; mesh.triangles = new int[] { 0, 1, 3, 1, 2, 3 }; mesh.normals = new Vector3[] { plane.normal, plane.normal, plane.normal, plane.normal }; Gizmos.color = new Color(1f, 1f, 1f, 0.5f); Gizmos.DrawMesh(mesh); float size = Mathf.Max(halfWidthAtSphere, halfHeightAtSphere); // Gizmos.DrawCube(spherePosition, new Vector3(halfWidthAtSphere * 2f, halfHeightAtSphere * 2f, 0.1f)); DrawCircleGizmos(closestPointOnPlane, planePerpendicular1 * Mathf.Min(1f, size), planePerpendicular2 * Mathf.Min(1f, size)); } }