using System; using System.Diagnostics; using UnityEngine; using UnityEngine.Rendering; namespace Leap.Unity { [RequireComponent(typeof(Camera))] [ExecuteInEditMode] public class LeapVRCameraControl : MonoBehaviour { [DebuggerBrowsable(DebuggerBrowsableState.Never)] public static event Action OnValidCameraParams; [DebuggerBrowsable(DebuggerBrowsableState.Never)] public static event Action OnLeftPreRender; [DebuggerBrowsable(DebuggerBrowsableState.Never)] public static event Action OnRightPreRender; public bool OverrideEyePosition { get { return this._overrideEyePosition; } set { this._overrideEyePosition = value; } } private Camera _camera { get { if (this._cachedCamera == null) { this._cachedCamera = base.GetComponent(); } return this._cachedCamera; } } private void Start() { this._deviceInfo = new LeapDeviceInfo(LeapDeviceType.Peripheral); } private void Update() { LeapVRCameraControl._hasDispatchedValidCameraParams = false; } private void OnPreCull() { this._camera.ResetWorldToCameraMatrix(); this._finalCenterMatrix = this._camera.worldToCameraMatrix; if (!LeapVRCameraControl._hasDispatchedValidCameraParams) { LeapVRCameraControl.CameraParams obj = new LeapVRCameraControl.CameraParams(this._cachedCamera); if (LeapVRCameraControl.OnValidCameraParams != null) { LeapVRCameraControl.OnValidCameraParams(obj); } LeapVRCameraControl._hasDispatchedValidCameraParams = true; } } private void OnPreRender() { this._eyeType.BeginCamera(); if (this._eyeType.IsLeftEye) { Shader.SetGlobalVector("_LeapGlobalStereoUVOffset", LeapVRCameraControl.LEFT_EYE_UV_OFFSET); if (LeapVRCameraControl.OnLeftPreRender != null) { LeapVRCameraControl.OnLeftPreRender(this._cachedCamera); } } else { Shader.SetGlobalVector("_LeapGlobalStereoUVOffset", LeapVRCameraControl.RIGHT_EYE_UV_OFFSET); if (LeapVRCameraControl.OnRightPreRender != null) { LeapVRCameraControl.OnRightPreRender(this._cachedCamera); } } Matrix4x4 matrix4x; if (this._overrideEyePosition) { matrix4x = this._finalCenterMatrix; Vector3 a = (float)((!this._eyeType.IsLeftEye) ? -1 : 1) * base.transform.right * this._deviceInfo.baseline * 0.5f; Vector3 b = -base.transform.forward * this._deviceInfo.focalPlaneOffset; matrix4x *= Matrix4x4.TRS(a + b, Quaternion.identity, Vector3.one); } else { matrix4x = this._camera.worldToCameraMatrix; } this._camera.worldToCameraMatrix = matrix4x; } public const string GLOBAL_EYE_UV_OFFSET_NAME = "_LeapGlobalStereoUVOffset"; private static Vector2 LEFT_EYE_UV_OFFSET = new Vector2(0f, 0f); private static Vector2 RIGHT_EYE_UV_OFFSET = new Vector2(0f, 0.5f); private static bool _hasDispatchedValidCameraParams = false; [SerializeField] private EyeType _eyeType = new EyeType(EyeType.OrderType.CENTER); [SerializeField] private bool _overrideEyePosition = true; private Camera _cachedCamera; private Matrix4x4 _finalCenterMatrix; private LeapDeviceInfo _deviceInfo; public struct CameraParams { public CameraParams(Camera camera) { this.CenterEyeTransform = camera.transform; this.ProjectionMatrix = camera.projectionMatrix; GraphicsDeviceType graphicsDeviceType = SystemInfo.graphicsDeviceType; if (graphicsDeviceType == GraphicsDeviceType.Direct3D9 || graphicsDeviceType == GraphicsDeviceType.Direct3D11 || graphicsDeviceType == GraphicsDeviceType.Direct3D12) { for (int i = 0; i < 4; i++) { this.ProjectionMatrix[1, i] = -this.ProjectionMatrix[1, i]; } for (int j = 0; j < 4; j++) { this.ProjectionMatrix[2, j] = this.ProjectionMatrix[2, j] * 0.5f + this.ProjectionMatrix[3, j] * 0.5f; } } this.Width = camera.pixelWidth; this.Height = camera.pixelHeight; } public readonly Transform CenterEyeTransform; public readonly Matrix4x4 ProjectionMatrix; public readonly int Width; public readonly int Height; } } }