/// <summary> /// Populates the list of cameras according to the cameras that should be used for /// the current game scene. /// </summary> /// <param name="cameraNames">An array of camera names to use for this VR scene.</param> private void PopulateCameraList(string[] cameraNames) { // search for the cameras to render NumVRCameras = cameraNames.Length; VRCameras = new Types.CameraData[NumVRCameras]; for (int i = 0; i < NumVRCameras; i++) { Camera foundCamera = Array.Find(Camera.allCameras, cam => cam.name.Equals(cameraNames[i])); if (foundCamera == null) { Utils.LogError("Could not find camera \"" + cameraNames[i] + "\" in the scene!"); } else { // determine clip plane and new projection matrices float nearClipPlane = (foundCamera.name.Equals("Camera 01")) ? 0.05f : foundCamera.nearClipPlane; HmdMatrix44_t projectionMatrixL = OpenVR.System.GetProjectionMatrix(EVREye.Eye_Left, nearClipPlane, foundCamera.farClipPlane); HmdMatrix44_t projectionMatrixR = OpenVR.System.GetProjectionMatrix(EVREye.Eye_Right, nearClipPlane, foundCamera.farClipPlane); // store information about the camera VRCameras[i].camera = foundCamera; VRCameras[i].originalProjectionMatrix = foundCamera.projectionMatrix; VRCameras[i].hmdProjectionMatrixL = MathUtils.Matrix4x4_OpenVr2UnityFormat(ref projectionMatrixL); VRCameras[i].hmdProjectionMatrixR = MathUtils.Matrix4x4_OpenVr2UnityFormat(ref projectionMatrixR); // disable the camera so we can call Render directly foundCamera.enabled = false; } } }
/// <summary> /// Renders a set of cameras onto a RenderTexture, and submit the frame to the HMD. /// </summary> private void RenderHmdCameras( EVREye eye, SteamVR_Utils.RigidTransform hmdTransform, SteamVR_Utils.RigidTransform hmdEyeTransform, RenderTexture hmdEyeRenderTexture, Texture_t hmdEyeTexture) { /** * hmdEyeTransform is in a coordinate system that follows the headset, where * the origin is the headset device position. Therefore the eyes are at a constant * offset from the device. hmdEyeTransform does not change (per eye). * hmdEyeTransform.x+ towards the right of the headset * hmdEyeTransform.y+ towards the top the headset * hmdEyeTransform.z+ towards the front of the headset * * hmdTransform is in a coordinate system set in physical space, where the * origin is the initial seated position. Or for room-scale, the physical origin of the room. * hmdTransform.x+ towards the right * hmdTransform.y+ upwards * hmdTransform.z+ towards the front * * Scene.InitialPosition and Scene.InitialRotation are the Unity world coordinates where * we initialize the VR scene, i.e. the origin of a coordinate system that maps * 1-to-1 with physical space. * * 1. Calculate the position of the eye in the physical coordinate system. * 2. Transform the calculated position into Unity world coordinates, offset from * InitialPosition and InitialRotation. */ // position of the eye in the VR reference frame Vector3 positionToEye = hmdTransform.pos + hmdTransform.rot * hmdEyeTransform.pos; // update position of the cameras Scene.Instance.UpdateScene(eye, hmdTransform, hmdEyeTransform); // render the set of cameras for (int i = 0; i < Scene.Instance.NumVRCameras; i++) { Types.CameraData camData = Scene.Instance.VRCameras[i]; // set projection matrix camData.camera.projectionMatrix = (eye == EVREye.Eye_Left) ? camData.hmdProjectionMatrixL : camData.hmdProjectionMatrixR; // set texture to render to, then render camData.camera.targetTexture = hmdEyeRenderTexture; camData.camera.Render(); } hmdEyeTexture.handle = hmdEyeRenderTexture.GetNativeTexturePtr(); // Submit frames to HMD EVRCompositorError vrCompositorError = OpenVR.Compositor.Submit(eye, ref hmdEyeTexture, ref hmdTextureBounds, EVRSubmitFlags.Submit_Default); if (vrCompositorError != EVRCompositorError.None) { throw new Exception("Submit (" + eye + ") failed: (" + (int)vrCompositorError + ") " + vrCompositorError.ToString()); } }
/// <summary> /// Populates the list of cameras according to the cameras that should be used for /// the current game scene. /// </summary> /// <param name="cameraNames">An array of camera names to use for this VR scene.</param> private void PopulateCameraList(string[] cameraNames) { // search for the cameras to render NumVRCameras = cameraNames.Length; VRCameras = new Types.CameraData[NumVRCameras]; for (int i = 0; i < NumVRCameras; i++) { Camera foundCamera = Array.Find(Camera.allCameras, cam => cam.name.Equals(cameraNames[i])); if (foundCamera == null) { Utils.LogError("Could not find camera \"" + cameraNames[i] + "\" in the scene!"); } else { // determine clip plane and new projection matrices HmdMatrix44_t projectionMatrixL = OpenVR.System.GetProjectionMatrix(EVREye.Eye_Left, foundCamera.nearClipPlane, foundCamera.farClipPlane); HmdMatrix44_t projectionMatrixR = OpenVR.System.GetProjectionMatrix(EVREye.Eye_Right, foundCamera.nearClipPlane, foundCamera.farClipPlane); // store information about the camera VRCameras[i].camera = foundCamera; VRCameras[i].originalProjectionMatrix = foundCamera.projectionMatrix; VRCameras[i].hmdProjectionMatrixL = MathUtils.Matrix4x4_OpenVr2UnityFormat(ref projectionMatrixL); VRCameras[i].hmdProjectionMatrixR = MathUtils.Matrix4x4_OpenVr2UnityFormat(ref projectionMatrixR); // disable the camera so we can call Render directly foundCamera.enabled = false; // cache the galaxy camera object, we'll need to call on it directly during eyeball positioning if (foundCamera.name == "GalaxyCamera") { galaxyCamera = foundCamera.gameObject; } else if (foundCamera.name == "Landscape Camera") { landscapeCamera = foundCamera.gameObject; } } } }