OVRExternalComposition.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. using UnityEngine;
  2. using System.Collections;
  3. #if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN
  4. public class OVRExternalComposition : OVRComposition
  5. {
  6. private GameObject foregroundCameraGameObject;
  7. private Camera foregroundCamera;
  8. private GameObject backgroundCameraGameObject;
  9. private Camera backgroundCamera;
  10. private GameObject cameraProxyPlane;
  11. public override OVRManager.CompositionMethod CompositionMethod() { return OVRManager.CompositionMethod.External; }
  12. public OVRExternalComposition(GameObject parentObject, Camera mainCamera)
  13. {
  14. Debug.Assert(backgroundCameraGameObject == null);
  15. backgroundCameraGameObject = new GameObject();
  16. backgroundCameraGameObject.name = "MRBackgroundCamera";
  17. backgroundCameraGameObject.transform.parent = parentObject.transform;
  18. backgroundCamera = backgroundCameraGameObject.AddComponent<Camera>();
  19. backgroundCamera.stereoTargetEye = StereoTargetEyeMask.None;
  20. backgroundCamera.depth = float.MaxValue;
  21. backgroundCamera.rect = new Rect(0.0f, 0.0f, 0.5f, 1.0f);
  22. backgroundCamera.clearFlags = mainCamera.clearFlags;
  23. backgroundCamera.backgroundColor = mainCamera.backgroundColor;
  24. backgroundCamera.cullingMask = mainCamera.cullingMask & (~OVRManager.instance.extraHiddenLayers);
  25. backgroundCamera.nearClipPlane = mainCamera.nearClipPlane;
  26. backgroundCamera.farClipPlane = mainCamera.farClipPlane;
  27. Debug.Assert(foregroundCameraGameObject == null);
  28. foregroundCameraGameObject = new GameObject();
  29. foregroundCameraGameObject.name = "MRForgroundCamera";
  30. foregroundCameraGameObject.transform.parent = parentObject.transform;
  31. foregroundCamera = foregroundCameraGameObject.AddComponent<Camera>();
  32. foregroundCamera.stereoTargetEye = StereoTargetEyeMask.None;
  33. foregroundCamera.depth = float.MaxValue;
  34. foregroundCamera.rect = new Rect(0.5f, 0.0f, 0.5f, 1.0f);
  35. foregroundCamera.clearFlags = CameraClearFlags.Color;
  36. foregroundCamera.backgroundColor = OVRMixedReality.chromaKeyColor;
  37. foregroundCamera.cullingMask = mainCamera.cullingMask & (~OVRManager.instance.extraHiddenLayers);
  38. foregroundCamera.nearClipPlane = mainCamera.nearClipPlane;
  39. foregroundCamera.farClipPlane = mainCamera.farClipPlane;
  40. // Create cameraProxyPlane for clipping
  41. Debug.Assert(cameraProxyPlane == null);
  42. cameraProxyPlane = GameObject.CreatePrimitive(PrimitiveType.Quad);
  43. cameraProxyPlane.name = "MRProxyClipPlane";
  44. cameraProxyPlane.transform.parent = parentObject.transform;
  45. cameraProxyPlane.GetComponent<Collider>().enabled = false;
  46. cameraProxyPlane.GetComponent<MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
  47. Material clipMaterial = new Material(Shader.Find("Oculus/OVRMRClipPlane"));
  48. cameraProxyPlane.GetComponent<MeshRenderer>().material = clipMaterial;
  49. clipMaterial.SetColor("_Color", OVRMixedReality.chromaKeyColor);
  50. clipMaterial.SetFloat("_Visible", 0.0f);
  51. cameraProxyPlane.transform.localScale = new Vector3(1000, 1000, 1000);
  52. cameraProxyPlane.SetActive(true);
  53. OVRMRForegroundCameraManager foregroundCameraManager = foregroundCameraGameObject.AddComponent<OVRMRForegroundCameraManager>();
  54. foregroundCameraManager.clipPlaneGameObj = cameraProxyPlane;
  55. }
  56. public override void Update(Camera mainCamera)
  57. {
  58. OVRPlugin.SetHandNodePoseStateLatency(0.0); // the HandNodePoseStateLatency doesn't apply to the external composition. Always enforce it to 0.0
  59. backgroundCamera.clearFlags = mainCamera.clearFlags;
  60. backgroundCamera.backgroundColor = mainCamera.backgroundColor;
  61. backgroundCamera.cullingMask = mainCamera.cullingMask & (~OVRManager.instance.extraHiddenLayers);
  62. backgroundCamera.nearClipPlane = mainCamera.nearClipPlane;
  63. backgroundCamera.farClipPlane = mainCamera.farClipPlane;
  64. foregroundCamera.cullingMask = mainCamera.cullingMask & (~OVRManager.instance.extraHiddenLayers);
  65. foregroundCamera.nearClipPlane = mainCamera.nearClipPlane;
  66. foregroundCamera.farClipPlane = mainCamera.farClipPlane;
  67. if (OVRMixedReality.useFakeExternalCamera || OVRPlugin.GetExternalCameraCount() == 0)
  68. {
  69. OVRPose worldSpacePose = new OVRPose();
  70. OVRPose trackingSpacePose = new OVRPose();
  71. trackingSpacePose.position = OVRMixedReality.fakeCameraPositon;
  72. trackingSpacePose.orientation = OVRMixedReality.fakeCameraRotation;
  73. worldSpacePose = OVRExtensions.ToWorldSpacePose(trackingSpacePose);
  74. backgroundCamera.fieldOfView = OVRMixedReality.fakeCameraFov;
  75. backgroundCamera.aspect = OVRMixedReality.fakeCameraAspect;
  76. backgroundCamera.transform.FromOVRPose(worldSpacePose);
  77. foregroundCamera.fieldOfView = OVRMixedReality.fakeCameraFov;
  78. foregroundCamera.aspect = OVRMixedReality.fakeCameraAspect;
  79. foregroundCamera.transform.FromOVRPose(worldSpacePose);
  80. }
  81. else
  82. {
  83. OVRPlugin.CameraExtrinsics extrinsics;
  84. OVRPlugin.CameraIntrinsics intrinsics;
  85. // So far, only support 1 camera for MR and always use camera index 0
  86. if (OVRPlugin.GetMixedRealityCameraInfo(0, out extrinsics, out intrinsics))
  87. {
  88. OVRPose worldSpacePose = ComputeCameraWorldSpacePose(extrinsics);
  89. float fovY = Mathf.Atan(intrinsics.FOVPort.UpTan) * Mathf.Rad2Deg * 2;
  90. float aspect = intrinsics.FOVPort.LeftTan / intrinsics.FOVPort.UpTan;
  91. backgroundCamera.fieldOfView = fovY;
  92. backgroundCamera.aspect = aspect;
  93. backgroundCamera.transform.FromOVRPose(worldSpacePose);
  94. foregroundCamera.fieldOfView = fovY;
  95. foregroundCamera.aspect = intrinsics.FOVPort.LeftTan / intrinsics.FOVPort.UpTan;
  96. foregroundCamera.transform.FromOVRPose(worldSpacePose);
  97. }
  98. else
  99. {
  100. Debug.LogError("Failed to get external camera information");
  101. return;
  102. }
  103. }
  104. // Assume player always standing straightly
  105. Vector3 externalCameraToHeadXZ = mainCamera.transform.position - foregroundCamera.transform.position;
  106. externalCameraToHeadXZ.y = 0;
  107. cameraProxyPlane.transform.position = mainCamera.transform.position;
  108. cameraProxyPlane.transform.LookAt(cameraProxyPlane.transform.position + externalCameraToHeadXZ);
  109. }
  110. public override void Cleanup()
  111. {
  112. OVRCompositionUtil.SafeDestroy(ref backgroundCameraGameObject);
  113. backgroundCamera = null;
  114. OVRCompositionUtil.SafeDestroy(ref foregroundCameraGameObject);
  115. foregroundCamera = null;
  116. OVRCompositionUtil.SafeDestroy(ref cameraProxyPlane);
  117. Debug.Log("ExternalComposition deactivated");
  118. }
  119. }
  120. /// <summary>
  121. /// Helper internal class for foregroundCamera, don't call it outside
  122. /// </summary>
  123. internal class OVRMRForegroundCameraManager : MonoBehaviour
  124. {
  125. public GameObject clipPlaneGameObj;
  126. private Material clipPlaneMaterial;
  127. void OnPreRender()
  128. {
  129. // the clipPlaneGameObj should be only visible to foreground camera
  130. if (clipPlaneGameObj)
  131. {
  132. if (clipPlaneMaterial == null)
  133. clipPlaneMaterial = clipPlaneGameObj.GetComponent<MeshRenderer>().material;
  134. clipPlaneGameObj.GetComponent<MeshRenderer>().material.SetFloat("_Visible", 1.0f);
  135. }
  136. }
  137. void OnPostRender()
  138. {
  139. if (clipPlaneGameObj)
  140. {
  141. Debug.Assert(clipPlaneMaterial);
  142. clipPlaneGameObj.GetComponent<MeshRenderer>().material.SetFloat("_Visible", 0.0f);
  143. }
  144. }
  145. }
  146. #endif