public static void DrawCameraBounds(LeiaCamera controller, GizmoType gizmoType) { #if UNITY_4_6 || UNITY_4_7 || UNITY_5_0_0 || UNITY_5_0_1 GizmoType notSelected = GizmoType.NotSelected; #elif UNITY_5_0_2 || UNITY_5_0_3 || UNITY_5_0_4 GizmoType notSelected = GizmoType.NotInSelectionHierarchy; #else GizmoType notSelected = GizmoType.NonSelected; #endif if ((gizmoType & notSelected) != 0 && controller.DrawCameraBounds == false) { return; } var camera = controller.GetComponent <Camera>(); if (camera == null) { return; } DisplayConfig displayConfig; if (Application.isPlaying) { displayConfig = LeiaDisplay.Instance.GetDisplayConfig(); } else { displayConfig = Object.FindObjectOfType <LeiaDisplay>().GetDisplayConfig(); } LeiaCameraData leiaCameraData = LeiaCameraUtils.ComputeLeiaCamera( camera, controller.ConvergenceDistance, controller.BaselineScaling, displayConfig); LeiaBoundsData leiaBoundsData = LeiaCameraUtils.ComputeLeiaBounds(camera, leiaCameraData, controller.ConvergenceDistance, controller.CameraShift, displayConfig); if (((gizmoType & notSelected) != 0 && controller.DrawCameraBounds) || (gizmoType & GizmoType.Selected) != 0) { // draw convergence plane in editor play mode Handles.DrawSolidRectangleWithOutline(leiaBoundsData.screen, _leiaScreenPlaneColor, _leiaScreenWireColor); } if (((gizmoType & notSelected) != 0 && controller.DrawCameraBounds) || (gizmoType & GizmoType.Selected) != 0) { // draw frustum outline in white Handles.DrawSolidRectangleWithOutline(leiaBoundsData.north, _leiaBoundsPlaneColor, _leiaBoundsWireColor); Handles.DrawSolidRectangleWithOutline(leiaBoundsData.south, _leiaBoundsPlaneColor, _leiaBoundsWireColor); Handles.DrawSolidRectangleWithOutline(leiaBoundsData.east, _leiaBoundsPlaneColor, _leiaBoundsWireColor); Handles.DrawSolidRectangleWithOutline(leiaBoundsData.west, _leiaBoundsPlaneColor, _leiaBoundsWireColor); Handles.DrawSolidRectangleWithOutline(leiaBoundsData.top, _leiaBoundsPlaneColor, _leiaBoundsWireColor); Handles.DrawSolidRectangleWithOutline(leiaBoundsData.bottom, _leiaBoundsPlaneColor, _leiaBoundsWireColor); } }
public static LeiaBoundsData ComputeLeiaBounds(Camera camera, LeiaCameraData leiaCamera, float convergenceDistance, Vector2 cameraShift, DisplayConfig displayConfig) { LeiaBoundsData leiaBounds = new LeiaBoundsData(); var localToWorldMatrix = camera.transform.localToWorldMatrix; localToWorldMatrix.SetColumn(0, localToWorldMatrix.GetColumn(0).normalized); localToWorldMatrix.SetColumn(1, localToWorldMatrix.GetColumn(1).normalized); localToWorldMatrix.SetColumn(2, localToWorldMatrix.GetColumn(2).normalized); if (camera.orthographic) { // assumes baseline = (baseline scaling) * (width of view in world units) * (system disparity in pixels) * (convergence distance) / (view width in pixels) float halfSizeY = camera.orthographicSize; float halfSizeX = halfSizeY * camera.aspect; Vector3 screenTopLeft = localToWorldMatrix.MultiplyPoint(new Vector3(-halfSizeX, halfSizeY, convergenceDistance)); Vector3 screenTopRight = localToWorldMatrix.MultiplyPoint(new Vector3(halfSizeX, halfSizeY, convergenceDistance)); Vector3 screenBottomLeft = localToWorldMatrix.MultiplyPoint(new Vector3(-halfSizeX, -halfSizeY, convergenceDistance)); Vector3 screenBottomRight = localToWorldMatrix.MultiplyPoint(new Vector3(halfSizeX, -halfSizeY, convergenceDistance)); float negativeSystemDisparityZ = convergenceDistance - 1.0f / leiaCamera.baselineScaling; Vector3 nearTopLeft = localToWorldMatrix.MultiplyPoint(new Vector3(-halfSizeX, halfSizeY, negativeSystemDisparityZ)); Vector3 nearTopRight = localToWorldMatrix.MultiplyPoint(new Vector3(halfSizeX, halfSizeY, negativeSystemDisparityZ)); Vector3 nearBottomLeft = localToWorldMatrix.MultiplyPoint(new Vector3(-halfSizeX, -halfSizeY, negativeSystemDisparityZ)); Vector3 nearBottomRight = localToWorldMatrix.MultiplyPoint(new Vector3(halfSizeX, -halfSizeY, negativeSystemDisparityZ)); float positiveSystemDisparityZ = convergenceDistance + 1.0f / leiaCamera.baselineScaling; Vector3 farTopLeft = localToWorldMatrix.MultiplyPoint(new Vector3(-halfSizeX, halfSizeY, positiveSystemDisparityZ)); Vector3 farTopRight = localToWorldMatrix.MultiplyPoint(new Vector3(halfSizeX, halfSizeY, positiveSystemDisparityZ)); Vector3 farBottomLeft = localToWorldMatrix.MultiplyPoint(new Vector3(-halfSizeX, -halfSizeY, positiveSystemDisparityZ)); Vector3 farBottomRight = localToWorldMatrix.MultiplyPoint(new Vector3(halfSizeX, -halfSizeY, positiveSystemDisparityZ)); leiaBounds.screen = new [] { screenTopLeft, screenTopRight, screenBottomRight, screenBottomLeft }; leiaBounds.south = new [] { nearTopLeft, nearTopRight, nearBottomRight, nearBottomLeft }; leiaBounds.north = new [] { farTopLeft, farTopRight, farBottomRight, farBottomLeft }; leiaBounds.top = new [] { nearTopLeft, nearTopRight, farTopRight, farTopLeft }; leiaBounds.bottom = new [] { nearBottomLeft, nearBottomRight, farBottomRight, farBottomLeft }; leiaBounds.east = new [] { nearTopRight, nearBottomRight, farBottomRight, farTopRight }; leiaBounds.west = new [] { nearTopLeft, nearBottomLeft, farBottomLeft, farTopLeft }; } else { cameraShift = leiaCamera.baseline * cameraShift; Vector3 screenTopLeft = localToWorldMatrix.MultiplyPoint(new Vector3(-leiaCamera.screenHalfWidth, leiaCamera.screenHalfHeight, convergenceDistance)); Vector3 screenTopRight = localToWorldMatrix.MultiplyPoint(new Vector3(leiaCamera.screenHalfWidth, leiaCamera.screenHalfHeight, convergenceDistance)); Vector3 screenBottomLeft = localToWorldMatrix.MultiplyPoint(new Vector3(-leiaCamera.screenHalfWidth, -leiaCamera.screenHalfHeight, convergenceDistance)); Vector3 screenBottomRight = localToWorldMatrix.MultiplyPoint(new Vector3(leiaCamera.screenHalfWidth, -leiaCamera.screenHalfHeight, convergenceDistance)); float nearPlaneZ = (leiaCamera.baselineScaling * convergenceDistance) / (leiaCamera.baselineScaling + 1f); float nearRatio = nearPlaneZ / convergenceDistance; float nearShiftRatio = 1f - nearRatio; Bounds localNearPlaneBounds = new Bounds( new Vector3(nearShiftRatio * cameraShift.x, nearShiftRatio * cameraShift.y, nearPlaneZ), new Vector3(leiaCamera.screenHalfWidth * nearRatio * 2, leiaCamera.screenHalfHeight * nearRatio * 2, 0)); Vector3 nearTopLeft = localToWorldMatrix.MultiplyPoint(new Vector3(localNearPlaneBounds.min.x, localNearPlaneBounds.max.y, localNearPlaneBounds.center.z)); Vector3 nearTopRight = localToWorldMatrix.MultiplyPoint(new Vector3(localNearPlaneBounds.max.x, localNearPlaneBounds.max.y, localNearPlaneBounds.center.z)); Vector3 nearBottomLeft = localToWorldMatrix.MultiplyPoint(new Vector3(localNearPlaneBounds.min.x, localNearPlaneBounds.min.y, localNearPlaneBounds.center.z)); Vector3 nearBottomRight = localToWorldMatrix.MultiplyPoint(new Vector3(localNearPlaneBounds.max.x, localNearPlaneBounds.min.y, localNearPlaneBounds.center.z)); float farPlaneZ = (leiaCamera.baselineScaling * convergenceDistance) / (leiaCamera.baselineScaling - 1f); farPlaneZ = 1f / Mathf.Max(1f / farPlaneZ, 1e-5f); float farRatio = farPlaneZ / convergenceDistance; float farShiftRatio = 1f - farRatio; Bounds localFarPlaneBounds = new Bounds( new Vector3(farShiftRatio * cameraShift.x, farShiftRatio * cameraShift.y, farPlaneZ), new Vector3(leiaCamera.screenHalfWidth * farRatio * 2, leiaCamera.screenHalfHeight * farRatio * 2, 0)); Vector3 farTopLeft = localToWorldMatrix.MultiplyPoint(new Vector3(localFarPlaneBounds.min.x, localFarPlaneBounds.max.y, localFarPlaneBounds.center.z)); Vector3 farTopRight = localToWorldMatrix.MultiplyPoint(new Vector3(localFarPlaneBounds.max.x, localFarPlaneBounds.max.y, localFarPlaneBounds.center.z)); Vector3 farBottomLeft = localToWorldMatrix.MultiplyPoint(new Vector3(localFarPlaneBounds.min.x, localFarPlaneBounds.min.y, localFarPlaneBounds.center.z)); Vector3 farBottomRight = localToWorldMatrix.MultiplyPoint(new Vector3(localFarPlaneBounds.max.x, localFarPlaneBounds.min.y, localFarPlaneBounds.center.z)); leiaBounds.screen = new [] { screenTopLeft, screenTopRight, screenBottomRight, screenBottomLeft }; leiaBounds.south = new [] { nearTopLeft, nearTopRight, nearBottomRight, nearBottomLeft }; leiaBounds.north = new [] { farTopLeft, farTopRight, farBottomRight, farBottomLeft }; leiaBounds.top = new [] { nearTopLeft, nearTopRight, farTopRight, farTopLeft }; leiaBounds.bottom = new [] { nearBottomLeft, nearBottomRight, farBottomRight, farBottomLeft }; leiaBounds.east = new [] { nearTopRight, nearBottomRight, farBottomRight, farTopRight }; leiaBounds.west = new [] { nearTopLeft, nearBottomLeft, farBottomLeft, farTopLeft }; } return(leiaBounds); }