/// <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()); } }
public void RenderFrame(params IVRDrawable[] drawables) { if (graphics == null) { throw new InvalidOperationException("Cannot render a frame until graphics are initialized"); } EyeTextures eyeTextures = graphics.RenderToTextures( CurrentViewProjMatrix(EVREye.Eye_Left), CurrentViewProjMatrix(EVREye.Eye_Right), LeftEyePos, RightEyePos, drawables); Texture_t leftEye = eyeTextures.LeftEye; Texture_t rightEye = eyeTextures.RightEye; // send to the headset VRTextureBounds_t bounds = new VRTextureBounds_t() { uMin = 0, vMin = 0, uMax = 1f, vMax = 1f }; // is this right? EVRCompositorError compErr = OpenVR.Compositor.Submit(EVREye.Eye_Left, ref leftEye, ref bounds, EVRSubmitFlags.Submit_Default); if (compErr != EVRCompositorError.None) { throw new InvalidOperationException($"Failed to submit image to compositor: {compErr}"); } compErr = OpenVR.Compositor.Submit(EVREye.Eye_Right, ref rightEye, ref bounds, EVRSubmitFlags.Submit_Default); if (compErr != EVRCompositorError.None) { throw new InvalidOperationException($"Failed to submit image to compositor: {compErr}"); } }
private void Check(EVRCompositorError error, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0) { if (error != EVRCompositorError.None) { throw new Exception($"OpenVR error {error} in {memberName} at {filePath}:{lineNumber}"); } }
public override HmdPoseState WaitForPoses() { EVRCompositorError compositorError = _compositor.WaitGetPoses(_devicePoses, new TrackedDevicePose_t[0]); TrackedDevicePose_t hmdPose = _devicePoses[OVR.k_unTrackedDeviceIndex_Hmd]; Matrix deviceToAbsolute = ToSysMatrix(hmdPose.mDeviceToAbsoluteTracking); deviceToAbsolute.Decompose(out _, out Quaternion deviceRotation, out Vector3 devicePosition); Matrix.Invert(ref deviceToAbsolute, out Matrix absoluteToDevice); Matrix viewLeft = absoluteToDevice * _headToEyeLeft; Matrix viewRight = absoluteToDevice * _headToEyeRight; Matrix.Invert(ref viewLeft, out Matrix invViewLeft); invViewLeft.Decompose(out Vector3 scale, out Quaternion leftRotation, out Vector3 leftPosition); Matrix.Invert(ref viewRight, out Matrix invViewRight); invViewRight.Decompose(out _, out Quaternion rightRotation, out Vector3 rightPosition); // HMD (meters) vs Flax (centimeters) scaling leftPosition *= 100; rightPosition *= 100; // TODO: Expose mDeviceToAbsoluteTracking as "Head position/rotation" so we can move master actor properly return(new HmdPoseState( devicePosition, deviceRotation, _projLeft, _projRight, leftPosition, rightPosition, leftRotation, rightRotation)); }
/// <summary> /// Reports the compositor error. /// </summary> /// <param name="error">The error.</param> public static void ReportCompositeError(EVRCompositorError error) { /*if (error == EVRCompositorError.None) * return; * * //TODO: Don't log to Debug, since this is visible in editor console * Debug.LogError("[VR] Compositor error: `" + error + "`");*/ }
public void OnLateUpdate() { dispatchOpenVREvents(); EVRCompositorError compositorError = OpenVR.Compositor.WaitGetPoses(VRManager.RenderPoses, VRManager.GamePoses); if (compositorError != EVRCompositorError.None) { throw new Exception("OpenVr error: " + compositorError.ToString()); } OpenVR.System.GetDeviceToAbsoluteTrackingPose(ETrackingUniverseOrigin.TrackingUniverseStanding, Utils.CalculatePredictedSecondsToPhotons(), VRManager.DevicePoses); SteamVR_Events.NewPoses.Send(VRManager.DevicePoses); for (int i = 0; i < VRManager.DevicePoses.Length; i++) { TrackedDevicePose_t devicePose = VRManager.DevicePoses[i]; if (!devicePose.bDeviceIsConnected || !devicePose.bPoseIsValid) { continue; } SteamVR_Utils.RigidTransform rigidTransform = new SteamVR_Utils.RigidTransform(devicePose.mDeviceToAbsoluteTracking); ETrackedDeviceClass deviceType = OpenVR.System.GetTrackedDeviceClass((uint)i); if (deviceType == ETrackedDeviceClass.HMD) { Head.transform.localPosition = rigidTransform.pos; Head.transform.localRotation = rigidTransform.rot; Head.Velocity = fromHmdVector3_t(devicePose.vVelocity); Head.AngularVelocity = fromHmdVector3_t(devicePose.vAngularVelocity); Head.DeviceIndex = (uint)i; } else if (deviceType == ETrackedDeviceClass.Controller) { ETrackedControllerRole role = OpenVR.System.GetControllerRoleForTrackedDeviceIndex((uint)i); if (role == ETrackedControllerRole.LeftHand) { LeftController.transform.localPosition = rigidTransform.pos; LeftController.transform.localRotation = rigidTransform.rot; LeftController.Velocity = fromHmdVector3_t(devicePose.vVelocity); LeftController.AngularVelocity = fromHmdVector3_t(devicePose.vAngularVelocity); LeftController.DeviceIndex = (uint)i; } else if (role == ETrackedControllerRole.RightHand) { RightController.transform.localPosition = rigidTransform.pos; RightController.transform.localRotation = rigidTransform.rot; RightController.Velocity = fromHmdVector3_t(devicePose.vVelocity); RightController.AngularVelocity = fromHmdVector3_t(devicePose.vAngularVelocity); RightController.DeviceIndex = (uint)i; } } } }
public static void ReportCompositeError(EVRCompositorError error) { switch (error) { case EVRCompositorError.None: break; default: Debug.WriteLine("OpenVR Render error! {0}", error); break; } }
private void SubmitTexture(CVRCompositor compositor, GPUTexture colorTex, EVREye eye) { Texture_t texT; var renderer = GPUDevice.RendererType; if (renderer == RendererType.DirectX10 || renderer == RendererType.DirectX10_1 || renderer == RendererType.DirectX11) { texT.handle = colorTex.NativePtr; texT.eColorSpace = EColorSpace.Gamma; texT.eType = ETextureType.DirectX; } else { throw new Exception($"Renderer '{renderer}' is not yet supported"); } /*if (rt == RendererType.DirectX12) * { * texT.handle = colorTex.NativePtr; * texT.eColorSpace = EColorSpace.Gamma; * texT.eType = ETextureType.DirectX12; * } * * if(rt == RendererType.Vulkan) * { * texT.handle = colorTex.NativePtr; * texT.eColorSpace = EColorSpace.Gamma; * texT.eType = ETextureType.Vulkan; * }*/ VRTextureBounds_t boundsT; boundsT.uMin = 0; boundsT.uMax = 1; boundsT.vMin = 0; boundsT.vMax = 1; EVRCompositorError compositorError = EVRCompositorError.None; compositorError = compositor.Submit(eye, ref texT, ref boundsT, EVRSubmitFlags.Submit_Default); if (compositorError != EVRCompositorError.None) { throw new Exception($"Failed to submit to the OpenVR Compositor: {compositorError}"); } }
void OnRenderImage(RenderTexture r, RenderTexture r2) { if (HmdOn) { EVRCompositorError vrCompositorError = EVRCompositorError.None; if (left && !leftReady) { // log("left"); lock (KerbalVRPlugin.hmdRightEyeRenderTexture) lock (KerbalVRPlugin.hmdLeftEyeRenderTexture) lock (r) lock (vrCompositor) { // log("leftLOCK"); // log("left"); hmdLeftEyeTexture.handle = r.GetNativeTexturePtr(); vrCompositorError = vrCompositor.Submit(EVREye.Eye_Left, ref hmdLeftEyeTexture, ref hmdTextureBounds, EVRSubmitFlags.Submit_Default); leftReady = true; if (vrCompositorError != EVRCompositorError.None && vrCompositorError != lastError) { lastError = vrCompositorError; warn("Submit (Eye_Left) failed: " + vrCompositorError.ToString()); } } } else if (!rightReady) { // log("right"); lock (KerbalVRPlugin.hmdRightEyeRenderTexture) lock (KerbalVRPlugin.hmdLeftEyeRenderTexture) lock (r) lock (vrCompositor) { // log("rightLOCK"); hmdRightEyeTexture.handle = r.GetNativeTexturePtr(); vrCompositorError = vrCompositor.Submit(EVREye.Eye_Right, ref hmdRightEyeTexture, ref hmdTextureBounds, EVRSubmitFlags.Submit_Default); rightReady = true; if (vrCompositorError != EVRCompositorError.None && vrCompositorError != lastError) { lastError = vrCompositorError; warn("Submit (Eye_Left) failed: " + vrCompositorError.ToString()); } posTracker.gotPoses = false; } } } }
// Token: 0x06000DF0 RID: 3568 RVA: 0x00058BA4 File Offset: 0x00056DA4 public static void SetOverride(Texture front = null, Texture back = null, Texture left = null, Texture right = null, Texture top = null, Texture bottom = null) { CVRCompositor compositor = OpenVR.Compositor; if (compositor != null) { Texture[] array = new Texture[] { front, back, left, right, top, bottom }; Texture_t[] array2 = new Texture_t[6]; for (int i = 0; i < 6; i++) { array2[i].handle = ((array[i] != null) ? array[i].GetNativeTexturePtr() : IntPtr.Zero); array2[i].eType = SteamVR.instance.textureType; array2[i].eColorSpace = EColorSpace.Auto; } EVRCompositorError evrcompositorError = compositor.SetSkyboxOverride(array2); if (evrcompositorError != EVRCompositorError.None) { Debug.LogError("Failed to set skybox override with error: " + evrcompositorError); if (evrcompositorError == EVRCompositorError.TextureIsOnWrongDevice) { Debug.Log("Set your graphics driver to use the same video card as the headset is plugged into for Unity."); return; } if (evrcompositorError == EVRCompositorError.TextureUsesUnsupportedFormat) { Debug.Log("Ensure skybox textures are not compressed and have no mipmaps."); } } } }
public override HmdPoseState WaitForPoses() { EVRCompositorError compositorError = _compositor.WaitGetPoses(_devicePoses, Array.Empty <TrackedDevicePose_t>()); TrackedDevicePose_t hmdPose = _devicePoses[OVR.k_unTrackedDeviceIndex_Hmd]; Matrix4x4 deviceToAbsolute = ToSysMatrix(hmdPose.mDeviceToAbsoluteTracking); Matrix4x4.Invert(deviceToAbsolute, out Matrix4x4 absoluteToDevice); Matrix4x4 viewLeft = absoluteToDevice * _headToEyeLeft; Matrix4x4 viewRight = absoluteToDevice * _headToEyeRight; Matrix4x4.Invert(viewLeft, out Matrix4x4 invViewLeft); Matrix4x4.Decompose(invViewLeft, out _, out Quaternion leftRotation, out Vector3 leftPosition); Matrix4x4.Invert(viewRight, out Matrix4x4 invViewRight); Matrix4x4.Decompose(invViewRight, out _, out Quaternion rightRotation, out Vector3 rightPosition); return(new HmdPoseState( _projLeft, _projRight, leftPosition, rightPosition, leftRotation, rightRotation)); }
void OnPostRender() { if (EyeType == EVREye.Eye_Left) { VRManager.Instance.LeftEyeTexture.handle = VRManager.Instance.LeftEyeRenderTexture.GetNativeTexturePtr(); EVRCompositorError error = OpenVR.Compositor.Submit(EVREye.Eye_Left, ref VRManager.Instance.LeftEyeTexture, ref _bounds, EVRSubmitFlags.Submit_Default); if (error != EVRCompositorError.None) { throw new Exception("OpenVR Sumbit error on left eye: " + error.ToString()); } } else { VRManager.Instance.RightEyeTexture.handle = VRManager.Instance.RightEyeRenderTexture.GetNativeTexturePtr(); EVRCompositorError error = OpenVR.Compositor.Submit(EVREye.Eye_Right, ref VRManager.Instance.RightEyeTexture, ref _bounds, EVRSubmitFlags.Submit_Default); if (error != EVRCompositorError.None) { throw new Exception("OpenVR Sumbit error on right eye: " + error.ToString()); } } _owner.OnEyeFinishedRendering(); }
/// <summary> /// Overrides the Update method, called every frame. /// </summary> void Update() { // do nothing unless we are in IVA hmdIsAllowed = (CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.IVA); // start HMD using the Y key if (Input.GetKeyDown(KeyCode.Y) && hmdIsAllowed) { if (!hmdIsInitialized) { Debug.Log("[KerbalVR] Initializing HMD..."); bool retVal = InitHMD(); if (retVal) { Debug.Log("[KerbalVR] HMD initialized."); } } else { ResetInitialHmdPosition(); } } // perform regular updates if HMD is initialized if (hmdIsAllowed && hmdIsInitialized) { EVRCompositorError vrCompositorError = EVRCompositorError.None; // get latest HMD pose //-------------------------------------------------------------- vrSystem.GetDeviceToAbsoluteTrackingPose(ETrackingUniverseOrigin.TrackingUniverseSeated, 0.0f, vrDevicePoses); HmdMatrix34_t vrLeftEyeTransform = vrSystem.GetEyeToHeadTransform(EVREye.Eye_Left); HmdMatrix34_t vrRightEyeTransform = vrSystem.GetEyeToHeadTransform(EVREye.Eye_Right); vrCompositorError = vrCompositor.WaitGetPoses(vrRenderPoses, vrGamePoses); if (vrCompositorError != EVRCompositorError.None) { Debug.Log("[KerbalVR] WaitGetPoses failed: " + (int)vrCompositorError); return; } // convert SteamVR poses to Unity coordinates var hmdTransform = new SteamVR_Utils.RigidTransform(vrDevicePoses[OpenVR.k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking); var hmdLeftEyeTransform = new SteamVR_Utils.RigidTransform(vrLeftEyeTransform); var hmdRightEyeTransform = new SteamVR_Utils.RigidTransform(vrRightEyeTransform); var ctrlPoseLeft = new SteamVR_Utils.RigidTransform(vrDevicePoses[ctrlIndexLeft].mDeviceToAbsoluteTracking); var ctrlPoseRight = new SteamVR_Utils.RigidTransform(vrDevicePoses[ctrlIndexRight].mDeviceToAbsoluteTracking); // Render the LEFT eye //-------------------------------------------------------------- // rotate camera according to the HMD orientation InternalCamera.Instance.transform.localRotation = hmdTransform.rot; // translate the camera to match the position of the left eye, from origin InternalCamera.Instance.transform.localPosition = new Vector3(0f, 0f, 0f); InternalCamera.Instance.transform.Translate(hmdLeftEyeTransform.pos); // translate the camera to match the position of the HMD InternalCamera.Instance.transform.localPosition += hmdTransform.pos; // move the FlightCamera to match the position of the InternalCamera (so the outside world moves accordingly) FlightCamera.fetch.transform.position = InternalSpace.InternalToWorld(InternalCamera.Instance.transform.position); FlightCamera.fetch.transform.rotation = InternalSpace.InternalToWorld(InternalCamera.Instance.transform.rotation); // render the set of cameras foreach (CameraProperties camStruct in camerasToRender) { // set projection matrix camStruct.camera.projectionMatrix = camStruct.hmdLeftProjMatrix; // set texture to render to camStruct.camera.targetTexture = hmdLeftEyeRenderTexture; RenderTexture.active = hmdLeftEyeRenderTexture; // render camera camStruct.camera.Render(); } // Render the RIGHT eye (see previous comments) //-------------------------------------------------------------- InternalCamera.Instance.transform.localRotation = hmdTransform.rot; InternalCamera.Instance.transform.localPosition = new Vector3(0f, 0f, 0f); InternalCamera.Instance.transform.Translate(hmdRightEyeTransform.pos); InternalCamera.Instance.transform.localPosition += hmdTransform.pos; FlightCamera.fetch.transform.position = InternalSpace.InternalToWorld(InternalCamera.Instance.transform.position); FlightCamera.fetch.transform.rotation = InternalSpace.InternalToWorld(InternalCamera.Instance.transform.rotation); foreach (CameraProperties camStruct in camerasToRender) { camStruct.camera.projectionMatrix = camStruct.hmdRightProjMatrix; camStruct.camera.targetTexture = hmdRightEyeRenderTexture; RenderTexture.active = hmdRightEyeRenderTexture; camStruct.camera.Render(); } var origTex = uiCamera.targetTexture; uiCamera.targetTexture = uiTexture; RenderTexture.active = uiTexture; uiCamera.Render(); uiCamera.targetTexture = origTex; RenderTexture.active = null; // Set camera position to an HMD-centered position (for regular screen rendering) //-------------------------------------------------------------- if (renderToScreen) { foreach (CameraProperties camStruct in camerasToRender) { camStruct.camera.targetTexture = null; RenderTexture.active = null; camStruct.camera.projectionMatrix = camStruct.originalProjMatrix; } InternalCamera.Instance.transform.localRotation = hmdTransform.rot; InternalCamera.Instance.transform.localPosition = hmdTransform.pos; FlightCamera.fetch.transform.position = InternalSpace.InternalToWorld(InternalCamera.Instance.transform.position); FlightCamera.fetch.transform.rotation = InternalSpace.InternalToWorld(InternalCamera.Instance.transform.rotation); } // Set position of the hand controller props //-------------------------------------------------------------- if (propLeftHand != null) { propLeftHand.transform.position = InternalCamera.Instance.transform.parent.position; propLeftHand.transform.rotation = InternalCamera.Instance.transform.parent.rotation; propLeftHand.transform.Translate(ctrlPoseLeft.pos); propLeftHand.transform.rotation *= ctrlPoseLeft.rot; propLeftHandRenderer.enabled = vrDevicePoses[ctrlIndexLeft].bDeviceIsConnected; uiScreen.transform.position = InternalSpace.InternalToWorld(propLeftHand.transform.position); uiScreen.transform.rotation = InternalSpace.InternalToWorld(propLeftHand.transform.rotation); uiScreen.transform.Rotate(90f, 0f, 0f); } if (propRightHand != null) { propRightHand.transform.position = InternalCamera.Instance.transform.parent.position; propRightHand.transform.rotation = InternalCamera.Instance.transform.parent.rotation; propRightHand.transform.Translate(ctrlPoseRight.pos); propRightHand.transform.rotation *= ctrlPoseRight.rot; propRightHandRenderer.enabled = vrDevicePoses[ctrlIndexRight].bDeviceIsConnected; InternalProp closestProp = null; float closestDistanceSqr = 10000f; foreach (InternalProp prop in activeVesselInternalProps) { if (!prop.name.Equals(propRightHand.name)) { Vector3 directionToTarget = prop.transform.position - gloveCollider.transform.position; float distanceToTargetSqr = directionToTarget.sqrMagnitude; if (distanceToTargetSqr < closestDistanceSqr) { closestDistanceSqr = distanceToTargetSqr; closestProp = prop; } } } } /* * if (closestProp != null && closestDistanceSqr < 0.005f) * { * Debug.Log("[KerbalVR] closest prop: " + closestProp + ", " + closestDistanceSqr + " m2"); * foreach (InternalModule mod in closestProp.internalModules) * { * Debug.Log("[KerbalVR] module: " + mod.name); * } * } */ // Submit frames to HMD //-------------------------------------------------------------- vrCompositorError = vrCompositor.Submit(EVREye.Eye_Left, ref hmdLeftEyeTexture, ref hmdTextureBounds, EVRSubmitFlags.Submit_Default); if (vrCompositorError != EVRCompositorError.None) { Debug.Log("[KerbalVR] Submit (Eye_Left) failed: " + (int)vrCompositorError); } vrCompositorError = vrCompositor.Submit(EVREye.Eye_Right, ref hmdRightEyeTexture, ref hmdTextureBounds, EVRSubmitFlags.Submit_Default); if (vrCompositorError != EVRCompositorError.None) { Debug.Log("[KerbalVR] Submit (Eye_Right) failed: " + (int)vrCompositorError); } // disable highlighting of parts due to mouse // TODO: there needs to be a better way to do this. this affects the Part permanently Part hoveredPart = Mouse.HoveredPart; if (hoveredPart != null) { hoveredPart.HighlightActive = false; hoveredPart.highlightColor.a = 0f;// = new Color(0f, 0f, 0f, 0f); //Debug.Log("[KerbalVR] hovered part: " + hoveredPart.name); } // DEBUG if (Input.GetKeyDown(KeyCode.O)) { Debug.Log("[KerbalVR] POSITION hmdTransform : " + hmdTransform.pos.x + ", " + hmdTransform.pos.y + ", " + hmdTransform.pos.z); Debug.Log("[KerbalVR] POSITION hmdLTransform : " + hmdLeftEyeTransform.pos.x + ", " + hmdLeftEyeTransform.pos.y + ", " + hmdLeftEyeTransform.pos.z); Debug.Log("[KerbalVR] POSITION hmdRTransform : " + hmdRightEyeTransform.pos.x + ", " + hmdRightEyeTransform.pos.y + ", " + hmdRightEyeTransform.pos.z); Debug.Log("[KerbalVR] POSITION ctrlPoseRight : " + ctrlPoseRight.pos.x + ", " + ctrlPoseRight.pos.y + ", " + ctrlPoseRight.pos.z); Debug.Log("[KerbalVR] POSITION InternalCamera.Instance.transform.abs : " + InternalCamera.Instance.transform.position.x + ", " + InternalCamera.Instance.transform.position.y + ", " + InternalCamera.Instance.transform.position.z); Debug.Log("[KerbalVR] POSITION InternalCamera.Instance.transform.rel : " + InternalCamera.Instance.transform.localPosition.x + ", " + InternalCamera.Instance.transform.localPosition.y + ", " + InternalCamera.Instance.transform.localPosition.z); //Debug.Log("[KerbalVR] POSITION myprop.transform : " + testProp.transform.position.x + ", " + testProp.transform.position.y + ", " + testProp.transform.position.z); uiScreen.layer = (uiScreen.layer == 31) ? 0 : uiScreen.layer + 1; Debug.Log("[KerbalVR] prop layer = " + propLeftHand.gameObject.layer + ", screen obj layer = " + uiScreen.layer); foreach (Camera c in Camera.allCameras) { Debug.Log("[KerbalVR] Camera: " + c.name + ", cullingMask = " + c.cullingMask); } } } // if we are exiting VR, restore the cameras if (!hmdIsAllowed && hmdIsAllowed_prev) { foreach (CameraProperties camStruct in camerasToRender) { camStruct.camera.projectionMatrix = camStruct.originalProjMatrix; camStruct.camera.targetTexture = null; RenderTexture.active = null; } } hmdIsAllowed_prev = hmdIsAllowed; }
/// <summary> /// On LateUpdate, dispatch OpenVR events, run the main HMD loop code. /// </summary> private void LateUpdate() { // dispatch any OpenVR events if (hmdState == HmdState.Initialized) { DispatchOpenVREvents(); } // check if the current scene allows VR HmdIsAllowed = Scene.Instance.SceneAllowsVR(); // process the state of OpenVR ProcessHmdState(); // check if we are running the HMD HmdIsRunning = HmdIsAllowed && (hmdState == HmdState.Initialized) && HmdIsEnabled; // perform regular updates if HMD is initialized if (HmdIsRunning) { EVRCompositorError vrCompositorError = EVRCompositorError.None; // we've just started VR if (!hmdIsRunningPrev) { Utils.Log("HMD is now on"); Scene.Instance.SetupScene(); ResetInitialHmdPosition(); } try { // get latest device poses, emit an event to indicate devices have been updated float secondsToPhotons = Utils.CalculatePredictedSecondsToPhotons(); OpenVR.System.GetDeviceToAbsoluteTrackingPose(Scene.Instance.TrackingSpace, secondsToPhotons, devicePoses); SteamVR_Events.NewPoses.Send(devicePoses); HmdMatrix34_t vrLeftEyeTransform = OpenVR.System.GetEyeToHeadTransform(EVREye.Eye_Left); HmdMatrix34_t vrRightEyeTransform = OpenVR.System.GetEyeToHeadTransform(EVREye.Eye_Right); vrCompositorError = OpenVR.Compositor.WaitGetPoses(renderPoses, gamePoses); if (vrCompositorError != EVRCompositorError.None) { throw new Exception("WaitGetPoses failed: (" + (int)vrCompositorError + ") " + vrCompositorError.ToString()); } // convert SteamVR poses to Unity coordinates var hmdTransform = new SteamVR_Utils.RigidTransform(devicePoses[OpenVR.k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking); SteamVR_Utils.RigidTransform[] hmdEyeTransform = new SteamVR_Utils.RigidTransform[2]; hmdEyeTransform[0] = new SteamVR_Utils.RigidTransform(vrLeftEyeTransform); hmdEyeTransform[1] = new SteamVR_Utils.RigidTransform(vrRightEyeTransform); // don't highlight parts with the mouse Mouse.HoveredPart = null; // render each eye for (int i = 0; i < 2; i++) { RenderHmdCameras( (EVREye)i, hmdTransform, hmdEyeTransform[i], hmdEyeRenderTexture[i], hmdEyeTexture[i]); } // [insert dark magic here] OpenVR.Compositor.PostPresentHandoff(); // render to the game screen if (RenderHmdToScreen) { Graphics.Blit(hmdEyeRenderTexture[0], null as RenderTexture); } } catch (Exception e) { // shut off VR when an error occurs Utils.LogError(e); HmdIsEnabled = false; HmdIsRunning = false; } } // reset cameras when HMD is turned off if (!HmdIsRunning && hmdIsRunningPrev) { Utils.Log("HMD is now off, resetting cameras..."); Scene.Instance.CloseScene(); // TODO: figure out why we can no longer manipulate the IVA camera in the regular game } #if DEBUG // debug hooks if (Input.GetKeyDown(KeyCode.Y)) { // Utils.PrintAllCameras(); // Utils.PrintAllLayers(); Utils.PrintDebug(); // Utils.PrintFonts(); // Utils.PrintCollisionMatrix(); } #endif // keep track of whether we were running the HMD hmdIsRunningPrev = HmdIsRunning; }
/// <summary> /// Overrides the LateUpdate method, called every frame after all objects' Update. /// </summary> void LateUpdate() { // dispatch any OpenVR events if (hmdIsInitialized) { DispatchOpenVREvents(); } // check if the current scene allows VR HmdIsAllowed = Scene.SceneAllowsVR(); // check if we are running the HMD HmdIsRunning = HmdIsAllowed && hmdIsInitialized && HmdIsEnabled; // perform regular updates if HMD is initialized if (HmdIsRunning) { EVRCompositorError vrCompositorError = EVRCompositorError.None; try { // TODO: investigate if we should really be capturing poses in LateUpdate // get latest device poses float secondsToPhotons = Utils.CalculatePredictedSecondsToPhotons(); OpenVR.System.GetDeviceToAbsoluteTrackingPose(Scene.TrackingSpace, secondsToPhotons, devicePoses); SteamVR_Events.NewPoses.Send(devicePoses); HmdMatrix34_t vrLeftEyeTransform = OpenVR.System.GetEyeToHeadTransform(EVREye.Eye_Left); HmdMatrix34_t vrRightEyeTransform = OpenVR.System.GetEyeToHeadTransform(EVREye.Eye_Right); vrCompositorError = OpenVR.Compositor.WaitGetPoses(renderPoses, gamePoses); if (vrCompositorError != EVRCompositorError.None) { throw new Exception("WaitGetPoses failed: (" + (int)vrCompositorError + ") " + vrCompositorError.ToString()); } // convert SteamVR poses to Unity coordinates var hmdTransform = new SteamVR_Utils.RigidTransform(devicePoses[OpenVR.k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking); SteamVR_Utils.RigidTransform[] hmdEyeTransform = new SteamVR_Utils.RigidTransform[2]; hmdEyeTransform[0] = new SteamVR_Utils.RigidTransform(vrLeftEyeTransform); hmdEyeTransform[1] = new SteamVR_Utils.RigidTransform(vrRightEyeTransform); // render each eye for (int i = 0; i < 2; i++) { RenderHmdCameras( (EVREye)i, hmdTransform, hmdEyeTransform[i], i == 0 ? leftEyeRenderTextures[qualityLevel]:rightEyeRenderTextures[qualityLevel], renderTextures[qualityLevel]); } OpenVR.Compositor.PostPresentHandoff(); } catch (Exception e) { Utils.LogError(e); HmdIsEnabled = false; HmdIsRunning = false; } // disable highlighting of parts due to mouse // TODO: there needs to be a better way to do this. this affects the Part permanently Part hoveredPart = Mouse.HoveredPart; if (hoveredPart != null) { hoveredPart.HighlightActive = false; hoveredPart.highlightColor.a = 0f; } } // reset cameras when HMD is turned off if (!HmdIsRunning && hmdIsRunningPrev) { Utils.Log("HMD is now off, resetting cameras..."); Scene.CloseScene(); } #if DEBUG if (Input.GetKeyDown(KeyCode.Y)) { Utils.PrintAllCameras(); Utils.PrintAllLayers(); Utils.PrintDebug(); } #endif hmdIsRunningPrev = HmdIsRunning; }
/// <summary> /// Submits the VR view to the screen. /// </summary> public void Submit() { VREvent_t evt = new VREvent_t(); while (VR.PollNextEvent(ref evt, (uint)Marshal.SizeOf(typeof(VREvent_t)))) { // No need to do anything here! } TrackedDevicePose_t[] rposes = new TrackedDevicePose_t[OpenVR.k_unMaxTrackedDeviceCount]; TrackedDevicePose_t[] gposes = new TrackedDevicePose_t[OpenVR.k_unMaxTrackedDeviceCount]; EVRCompositorError merr = Compositor.WaitGetPoses(rposes, gposes); if (rposes[OpenVR.k_unTrackedDeviceIndex_Hmd].bPoseIsValid) { HmdMatrix34_t tmat = rposes[OpenVR.k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking; headMat = new Matrix4(tmat.m0, tmat.m1, tmat.m2, tmat.m3, tmat.m4, tmat.m5, tmat.m6, tmat.m7, tmat.m8, tmat.m9, tmat.m10, tmat.m11, 0, 0, 0, 1); headMat.Transpose(); HeadMatRot = headMat * Matrix4.CreateRotationX((float)(Math.PI * 0.5)); headMat = headMat * Matrix4.CreateRotationX((float)(Math.PI * 0.5)); headMat = headMat.ClearTranslation() * Matrix4.CreateTranslation(headMat.ExtractTranslation() * VRScale); headMat.Invert(); } if (merr != EVRCompositorError.None) { SysConsole.Output(OutputType.WARNING, "Posing error: " + merr); } Left = GetController(true); Right = GetController(false); if (!Compositor.CanRenderScene()) { SysConsole.Output(OutputType.WARNING, "Can't render VR scene!"); } Texture_t left = new Texture_t() { eColorSpace = EColorSpace.Auto, eType = EGraphicsAPIConvention.API_OpenGL, handle = new IntPtr(TheClient.Engine3D.MainView.CurrentFBOTexture) }; VRTextureBounds_t bounds = new VRTextureBounds_t() { uMin = 0f, uMax = 0.5f, vMin = 0f, vMax = 1f }; EVRCompositorError lerr = Compositor.Submit(EVREye.Eye_Left, ref left, ref bounds, EVRSubmitFlags.Submit_Default); if (lerr != EVRCompositorError.None) { SysConsole.Output(OutputType.WARNING, "Left eye error: " + lerr); } Texture_t right = new Texture_t() { eColorSpace = EColorSpace.Auto, eType = EGraphicsAPIConvention.API_OpenGL, handle = new IntPtr(TheClient.Engine3D.MainView.CurrentFBOTexture) }; VRTextureBounds_t rbounds = new VRTextureBounds_t() { uMin = 0.5f, uMax = 1f, vMin = 0f, vMax = 1f }; EVRCompositorError rerr = Compositor.Submit(EVREye.Eye_Right, ref right, ref rbounds, EVRSubmitFlags.Submit_Default); if (rerr != EVRCompositorError.None) { SysConsole.Output(OutputType.WARNING, "Right eye error: " + rerr); } }
void OnPreRender() { if (!gotPoses && HmdOn) { Part hoveredPart = Mouse.HoveredPart; if (hoveredPart != null) { hoveredPart.HighlightActive = false; } lock (KerbalVRPlugin.hmdRightEyeRenderTexture) lock (KerbalVRPlugin.hmdLeftEyeRenderTexture) { //check if active kerbal changed if (CameraManager.Instance.currentCameraMode.Equals(CameraManager.CameraMode.IVA) && CameraManager.Instance.IVACameraActiveKerbalIndex != lastKerbalID) { //reenable last kerbal activeKerbal.SetVisibleInPortrait(true); activeKerbal.gameObject.active = true; activeKerbal = CameraManager.Instance.IVACameraActiveKerbal; lastKerbalID = CameraManager.Instance.IVACameraActiveKerbalIndex; //deactivate curent kerbal activeKerbal.SetVisibleInPortrait(false); activeKerbal.gameObject.active = false; } gotPoses = true; EVRCompositorError vrCompositorError = EVRCompositorError.None; //get poses from VR api vrSystem.GetDeviceToAbsoluteTrackingPose(ETrackingUniverseOrigin.TrackingUniverseSeated, predict, vrDevicePoses); HmdMatrix34_t vrLeftEyeTransform = vrSystem.GetEyeToHeadTransform(EVREye.Eye_Left); HmdMatrix34_t vrRightEyeTransform = vrSystem.GetEyeToHeadTransform(EVREye.Eye_Right); vrCompositorError = vrCompositor.WaitGetPoses(vrRenderPoses, vrGamePoses); RenderSlave.leftReady = false; RenderSlave.rightReady = false; if (vrCompositorError != EVRCompositorError.None) { KerbalVRPlugin.warn("WaitGetPoses failed: " + vrCompositorError.ToString()); } // convert SteamVR poses to Unity coordinates hmdTransform = new Utils.RigidTransform(vrDevicePoses[OpenVR.k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking); hmdLeftEyeTransform = new Utils.RigidTransform(vrLeftEyeTransform); hmdRightEyeTransform = new Utils.RigidTransform(vrRightEyeTransform); ctrlPoseLeft = new Utils.RigidTransform(vrDevicePoses[ctrlIndexLeft].mDeviceToAbsoluteTracking); ctrlPoseRight = new Utils.RigidTransform(vrDevicePoses[ctrlIndexRight].mDeviceToAbsoluteTracking); //calculate corect position acording to vessel orientation hmdTransform.rot = (O_Interior.transform.rotation) * hmdTransform.rot; hmdTransform.pos = (O_Interior.transform.rotation) * hmdTransform.pos + O_Interior.transform.position; //shema: //rotate Camera acording to Hmd rotation //reset local position //set new local position acording to eye position //add position of hmd //internal camera has no special transformations camLeft_Interior.transform.localRotation = hmdTransform.rot; camLeft_Interior.transform.localPosition = new Vector3(0f, 0f, 0f); camLeft_Interior.transform.Translate(hmdLeftEyeTransform.pos); camLeft_Interior.transform.localPosition += hmdTransform.pos; camRight_Interior.transform.localRotation = hmdTransform.rot; camRight_Interior.transform.localPosition = new Vector3(0f, 0f, 0f); camRight_Interior.transform.Translate(hmdRightEyeTransform.pos); camRight_Interior.transform.localPosition += hmdTransform.pos; //rotations and positions for all following cameras are converted from internal to wolrd space: camLeft_Near.transform.localRotation = InternalSpace.InternalToWorld(hmdTransform.rot); camLeft_Near.transform.localPosition = new Vector3(0f, 0f, 0f); camLeft_Near.transform.Translate(hmdLeftEyeTransform.pos); camLeft_Near.transform.localPosition += InternalSpace.InternalToWorld(hmdTransform.pos); camRight_Near.transform.localRotation = InternalSpace.InternalToWorld(hmdTransform.rot); camRight_Near.transform.localPosition = new Vector3(0f, 0f, 0f); camRight_Near.transform.Translate(hmdRightEyeTransform.pos); camRight_Near.transform.localPosition += InternalSpace.InternalToWorld(hmdTransform.pos); camLeft_Far.transform.localRotation = InternalSpace.InternalToWorld(hmdTransform.rot); camLeft_Far.transform.localPosition = new Vector3(0f, 0f, 0f); camLeft_Far.transform.Translate(hmdLeftEyeTransform.pos); camLeft_Far.transform.localPosition += InternalSpace.InternalToWorld(hmdTransform.pos); camRight_Far.transform.localRotation = InternalSpace.InternalToWorld(hmdTransform.rot); camRight_Far.transform.localPosition = new Vector3(0f, 0f, 0f); camRight_Far.transform.Translate(hmdRightEyeTransform.pos); camRight_Far.transform.localPosition += InternalSpace.InternalToWorld(hmdTransform.pos); //the sky and star Cameras are in ScaledSpace so the vectors have to be scaled down leftSky.transform.localRotation = InternalSpace.InternalToWorld(hmdTransform.rot); leftSky.transform.localPosition = new Vector3(0f, 0f, 0f); leftSky.transform.Translate(hmdLeftEyeTransform.pos * ScaledSpace.InverseScaleFactor); leftSky.transform.localPosition += (hmdTransform.pos * ScaledSpace.InverseScaleFactor); rightSky.transform.localRotation = InternalSpace.InternalToWorld(hmdTransform.rot); rightSky.transform.localPosition = new Vector3(0f, 0f, 0f); rightSky.transform.Translate(hmdRightEyeTransform.pos * ScaledSpace.InverseScaleFactor); rightSky.transform.localPosition += (hmdTransform.pos * ScaledSpace.InverseScaleFactor); leftStars.transform.localRotation = InternalSpace.InternalToWorld(hmdTransform.rot); leftStars.transform.localPosition = new Vector3(0f, 0f, 0f); leftStars.transform.Translate(hmdLeftEyeTransform.pos * ScaledSpace.InverseScaleFactor); leftStars.transform.localPosition += InternalSpace.InternalToWorld(hmdTransform.pos * ScaledSpace.InverseScaleFactor); rightStars.transform.localRotation = InternalSpace.InternalToWorld(hmdTransform.rot); rightStars.transform.localPosition = new Vector3(0f, 0f, 0f); rightStars.transform.Translate(hmdRightEyeTransform.pos * ScaledSpace.InverseScaleFactor); rightStars.transform.localPosition += InternalSpace.InternalToWorld(hmdTransform.pos * ScaledSpace.InverseScaleFactor); } } }
/// <summary> /// Overrides the Update method, called every frame. /// </summary> void LateUpdate() { try { // do nothing unless we are in IVA hmdIsAllowed = (CameraManager.Instance.currentCameraMode == CameraManager.CameraMode.IVA); // start HMD using the Y key if (Input.GetKeyDown(KeyCode.Y) && hmdIsAllowed) { if (!hmdIsInitialized) { log("Initializing HMD..."); try { bool retVal = InitHMD(); if (retVal) { log("HMD initialized."); } } catch (Exception e) { err(e.Message); } } else { ResetInitialHmdPosition(); } } // perform regular updates if HMD is initialized if (hmdIsAllowed && hmdIsInitialized) { EVRCompositorError vrCompositorError = EVRCompositorError.None; // get latest HMD pose //-------------------------------------------------------------- vrSystem.GetDeviceToAbsoluteTrackingPose(ETrackingUniverseOrigin.TrackingUniverseSeated, 0.0f, vrDevicePoses); HmdMatrix34_t vrLeftEyeTransform = vrSystem.GetEyeToHeadTransform(EVREye.Eye_Left); HmdMatrix34_t vrRightEyeTransform = vrSystem.GetEyeToHeadTransform(EVREye.Eye_Right); vrCompositorError = vrCompositor.WaitGetPoses(vrRenderPoses, vrGamePoses); if (vrCompositorError != EVRCompositorError.None) { warn("WaitGetPoses failed: " + (int)vrCompositorError); return; } // convert SteamVR poses to Unity coordinates var hmdTransform = new SteamVR_Utils.RigidTransform(vrDevicePoses[OpenVR.k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking); var hmdLeftEyeTransform = new SteamVR_Utils.RigidTransform(vrLeftEyeTransform); var hmdRightEyeTransform = new SteamVR_Utils.RigidTransform(vrRightEyeTransform); var ctrlPoseLeft = new SteamVR_Utils.RigidTransform(vrDevicePoses[ctrlIndexLeft].mDeviceToAbsoluteTracking); var ctrlPoseRight = new SteamVR_Utils.RigidTransform(vrDevicePoses[ctrlIndexRight].mDeviceToAbsoluteTracking); // Render the LEFT eye //-------------------------------------------------------------- // rotate camera according to the HMD orientation InternalCamera.Instance.transform.localRotation = hmdTransform.rot; // translate the camera to match the position of the left eye, from origin InternalCamera.Instance.transform.localPosition = new Vector3(0f, 0f, 0f); InternalCamera.Instance.transform.Translate(hmdLeftEyeTransform.pos); // translate the camera to match the position of the HMD InternalCamera.Instance.transform.localPosition += hmdTransform.pos; // move the FlightCamera to match the position of the InternalCamera (so the outside world moves accordingly) FlightCamera.fetch.transform.position = InternalSpace.InternalToWorld(InternalCamera.Instance.transform.position); FlightCamera.fetch.transform.rotation = InternalSpace.InternalToWorld(InternalCamera.Instance.transform.rotation); // render the set of cameras foreach (CameraProperties camStruct in camerasToRender) { // set projection matrix camStruct.camera.projectionMatrix = camStruct.hmdLeftProjMatrix; // set texture to render to camStruct.camera.targetTexture = hmdLeftEyeRenderTexture; // render camera camStruct.camera.Render(); } // Render the RIGHT eye (see previous comments) //-------------------------------------------------------------- InternalCamera.Instance.transform.localRotation = hmdTransform.rot; InternalCamera.Instance.transform.localPosition = new Vector3(0f, 0f, 0f); InternalCamera.Instance.transform.Translate(hmdRightEyeTransform.pos); InternalCamera.Instance.transform.localPosition += hmdTransform.pos; FlightCamera.fetch.transform.position = InternalSpace.InternalToWorld(InternalCamera.Instance.transform.position); FlightCamera.fetch.transform.rotation = InternalSpace.InternalToWorld(InternalCamera.Instance.transform.rotation); foreach (CameraProperties camStruct in camerasToRender) { camStruct.camera.projectionMatrix = camStruct.hmdRightProjMatrix; camStruct.camera.targetTexture = hmdRightEyeRenderTexture; camStruct.camera.Render(); } try { // Set camera position to an HMD-centered position (for regular screen rendering) //-------------------------------------------------------------- if (renderToScreen) { foreach (CameraProperties camStruct in camerasToRender) { camStruct.camera.targetTexture = null; camStruct.camera.projectionMatrix = camStruct.originalProjMatrix; } InternalCamera.Instance.transform.localRotation = hmdTransform.rot; InternalCamera.Instance.transform.localPosition = hmdTransform.pos; FlightCamera.fetch.transform.position = InternalSpace.InternalToWorld(InternalCamera.Instance.transform.position); FlightCamera.fetch.transform.rotation = InternalSpace.InternalToWorld(InternalCamera.Instance.transform.rotation); } // Submit frames to HMD //-------------------------------------------------------------- vrCompositorError = vrCompositor.Submit(EVREye.Eye_Left, ref hmdLeftEyeTexture, ref hmdTextureBounds, EVRSubmitFlags.Submit_Default); if (vrCompositorError != EVRCompositorError.None) { warn("Submit (Eye_Left) failed: " + (int)vrCompositorError); } vrCompositorError = vrCompositor.Submit(EVREye.Eye_Right, ref hmdRightEyeTexture, ref hmdTextureBounds, EVRSubmitFlags.Submit_Default); if (vrCompositorError != EVRCompositorError.None) { warn("Submit (Eye_Right) failed: " + (int)vrCompositorError); } vrCompositor.PostPresentHandoff(); // GL.Flush(); } catch (Exception e) { err("Exception! " + e.ToString()); } // disable highlighting of parts due to mouse // TODO: there needs to be a better way to do this. this affects the Part permanently Part hoveredPart = Mouse.HoveredPart; if (hoveredPart != null) { hoveredPart.HighlightActive = false; hoveredPart.highlightColor.a = 0f;// = new Color(0f, 0f, 0f, 0f); //Debug.Log("[KerbalVR] hovered part: " + hoveredPart.name); } // DEBUG if (Input.GetKeyDown(KeyCode.O)) { log("POSITION hmdTransform : " + hmdTransform.pos.x + ", " + hmdTransform.pos.y + ", " + hmdTransform.pos.z); log("POSITION hmdLTransform : " + hmdLeftEyeTransform.pos.x + ", " + hmdLeftEyeTransform.pos.y + ", " + hmdLeftEyeTransform.pos.z); log("POSITION hmdRTransform : " + hmdRightEyeTransform.pos.x + ", " + hmdRightEyeTransform.pos.y + ", " + hmdRightEyeTransform.pos.z); log("POSITION ctrlPoseRight : " + ctrlPoseRight.pos.x + ", " + ctrlPoseRight.pos.y + ", " + ctrlPoseRight.pos.z); log("POSITION InternalCamera.Instance.transform.abs : " + InternalCamera.Instance.transform.position.x + ", " + InternalCamera.Instance.transform.position.y + ", " + InternalCamera.Instance.transform.position.z); log("POSITION InternalCamera.Instance.transform.rel : " + InternalCamera.Instance.transform.localPosition.x + ", " + InternalCamera.Instance.transform.localPosition.y + ", " + InternalCamera.Instance.transform.localPosition.z); foreach (Camera c in Camera.allCameras) { log("Camera: " + c.name + ", cullingMask = " + c.cullingMask); } } } // if we are exiting VR, restore the cameras if (!hmdIsAllowed && hmdIsAllowed_prev) { foreach (CameraProperties camStruct in camerasToRender) { camStruct.camera.projectionMatrix = camStruct.originalProjMatrix; camStruct.camera.targetTexture = null; } } hmdIsAllowed_prev = hmdIsAllowed; } catch (Exception e) { err(e.ToString()); } }
private void SubmitTexture(CVRCompositor compositor, Texture colorTex, EVREye eye) { Texture_t texT; if (_gd.GetD3D11Info(out BackendInfoD3D11 d3dInfo)) { texT.eColorSpace = EColorSpace.Gamma; texT.eType = ETextureType.DirectX; texT.handle = d3dInfo.GetTexturePointer(colorTex); } else if (_gd.GetOpenGLInfo(out BackendInfoOpenGL openglInfo)) { texT.eColorSpace = EColorSpace.Gamma; texT.eType = ETextureType.OpenGL; texT.handle = (IntPtr)openglInfo.GetTextureName(colorTex); } else if (_gd.GetVulkanInfo(out BackendInfoVulkan vkInfo)) { vkInfo.TransitionImageLayout(colorTex, (uint)Vulkan.VkImageLayout.TransferSrcOptimal); VRVulkanTextureData_t vkTexData; vkTexData.m_nImage = vkInfo.GetVkImage(colorTex); vkTexData.m_pDevice = vkInfo.Device; vkTexData.m_pPhysicalDevice = vkInfo.PhysicalDevice; vkTexData.m_pInstance = vkInfo.Instance; vkTexData.m_pQueue = vkInfo.GraphicsQueue; vkTexData.m_nQueueFamilyIndex = vkInfo.GraphicsQueueFamilyIndex; vkTexData.m_nWidth = colorTex.Width; vkTexData.m_nHeight = colorTex.Height; vkTexData.m_nFormat = (uint)VkFormats.VdToVkPixelFormat( colorTex.Format, (colorTex.Usage & TextureUsage.DepthStencil) != 0); vkTexData.m_nSampleCount = GetSampleCount(colorTex.SampleCount); texT.eColorSpace = EColorSpace.Gamma; texT.eType = ETextureType.Vulkan; unsafe { texT.handle = (IntPtr)(&vkTexData); } } else { throw new NotSupportedException(); } VRTextureBounds_t boundsT; boundsT.uMin = 0; boundsT.uMax = 1; boundsT.vMin = 0; boundsT.vMax = 1; EVRCompositorError compositorError = EVRCompositorError.None; if (_gd.GetOpenGLInfo(out BackendInfoOpenGL glInfo)) { glInfo.ExecuteOnGLThread(() => { compositorError = compositor.Submit(eye, ref texT, ref boundsT, EVRSubmitFlags.Submit_Default); }); } else { compositorError = compositor.Submit(eye, ref texT, ref boundsT, EVRSubmitFlags.Submit_Default); } if (compositorError != EVRCompositorError.None) { throw new VeldridException($"Failed to submit to the OpenVR Compositor: {compositorError}"); } }
void OnPreRender() { // log("pre"); if (!gotPoses && HmdOn) { // log("get"); lock (KerbalVRPlugin.hmdRightEyeRenderTexture) lock (KerbalVRPlugin.hmdLeftEyeRenderTexture) { // log("getLOCK"); gotPoses = true; EVRCompositorError vrCompositorError = EVRCompositorError.None; vrSystem.GetDeviceToAbsoluteTrackingPose(ETrackingUniverseOrigin.TrackingUniverseSeated, predict, vrDevicePoses); HmdMatrix34_t vrLeftEyeTransform = vrSystem.GetEyeToHeadTransform(EVREye.Eye_Left); HmdMatrix34_t vrRightEyeTransform = vrSystem.GetEyeToHeadTransform(EVREye.Eye_Right); vrCompositorError = vrCompositor.WaitGetPoses(vrRenderPoses, vrGamePoses); RenderSlave.leftReady = false; RenderSlave.rightReady = false; if (vrCompositorError != EVRCompositorError.None) { KerbalVRPlugin.warn("WaitGetPoses failed: " + vrCompositorError.ToString()); } // convert SteamVR poses to Unity coordinates hmdTransform = new Utils.RigidTransform(vrDevicePoses[OpenVR.k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking); hmdLeftEyeTransform = new Utils.RigidTransform(vrLeftEyeTransform); hmdRightEyeTransform = new Utils.RigidTransform(vrRightEyeTransform); ctrlPoseLeft = new Utils.RigidTransform(vrDevicePoses[ctrlIndexLeft].mDeviceToAbsoluteTracking); ctrlPoseRight = new Utils.RigidTransform(vrDevicePoses[ctrlIndexRight].mDeviceToAbsoluteTracking); // log(hmdTransform.pos.ToString()); // foreach (Camera cam in leftCameras) { //camLeft_Interior.transform.localRotation = hmdTransform.rot; //camLeft_Interior.transform.localPosition = new Vector3(0f, 0f, 0f); //camLeft_Interior.transform.Translate(hmdLeftEyeTransform.pos); //camLeft_Interior.transform.localPosition += hmdTransform.pos; //camRight_Interior.transform.localRotation = hmdTransform.rot; //camRight_Interior.transform.localPosition = new Vector3(0f, 0f, 0f); //camRight_Interior.transform.Translate(hmdRightEyeTransform.pos); //camRight_Interior.transform.localPosition += hmdTransform.pos; //right cam camLeft_Near.transform.localRotation = hmdTransform.rot; //camRight.transform.RotateAround(new Vector3(0, 0, 0), new Vector3(1, 0, 0), -90); // translate the camera to match the position of the left eye, from origin camLeft_Near.transform.localPosition = new Vector3(0f, 0f, 0f); camLeft_Near.transform.Translate(hmdLeftEyeTransform.pos); // translate the camera to match the position of the HMD camLeft_Near.transform.localPosition += hmdTransform.pos; //right cam camRight_Near.transform.localRotation = hmdTransform.rot; //camRight.transform.RotateAround(new Vector3(0, 0, 0), new Vector3(1, 0, 0), -90); // translate the camera to match the position of the left eye, from origin camRight_Near.transform.localPosition = new Vector3(0f, 0f, 0f); camRight_Near.transform.Translate(hmdRightEyeTransform.pos); // translate the camera to match the position of the HMD camRight_Near.transform.localPosition += hmdTransform.pos; camLeft_Far.transform.localRotation = hmdTransform.rot; //camRight.transform.RotateAround(new Vector3(0, 0, 0), new Vector3(1, 0, 0), -90); // translate the camera to match the position of the left eye, from origin camLeft_Far.transform.localPosition = new Vector3(0f, 0f, 0f); camLeft_Far.transform.Translate(hmdLeftEyeTransform.pos); // translate the camera to match the position of the HMD camLeft_Far.transform.localPosition += hmdTransform.pos; camRight_Far.transform.localRotation = hmdTransform.rot; //camRight.transform.RotateAround(new Vector3(0, 0, 0), new Vector3(1, 0, 0), -90); // translate the camera to match the position of the left eye, from origin camRight_Far.transform.localPosition = new Vector3(0f, 0f, 0f); camRight_Far.transform.Translate(hmdRightEyeTransform.pos); // translate the camera to match the position of the HMD camRight_Far.transform.localPosition += hmdTransform.pos; leftSky.transform.localRotation = hmdTransform.rot; leftSky.transform.localPosition = new Vector3(0f, 0f, 0f); leftSky.transform.Translate(hmdLeftEyeTransform.pos); leftSky.transform.localPosition += hmdTransform.pos; rightSky.transform.localRotation = hmdTransform.rot; rightSky.transform.localPosition = new Vector3(0f, 0f, 0f); rightSky.transform.Translate(hmdRightEyeTransform.pos); rightSky.transform.localPosition += hmdTransform.pos; leftStars.transform.localRotation = hmdTransform.rot; leftStars.transform.localPosition = new Vector3(0f, 0f, 0f); leftStars.transform.Translate(hmdLeftEyeTransform.pos); leftStars.transform.localPosition += hmdTransform.pos; rightStars.transform.localRotation = hmdTransform.rot; rightStars.transform.localPosition = new Vector3(0f, 0f, 0f); rightStars.transform.Translate(hmdRightEyeTransform.pos); rightStars.transform.localPosition += hmdTransform.pos; //GalaxyCubeControl.Instance.transform.rotation = hmdTransform // sky.transform.position = ScaledSpace.Instance.transform.position; // sky.transform.rotation = hmdTransform.rot; // sky.farClipPlane = 3.0e7f; //sky.cullingMask = (1 << 10) | (1 << 23); /* foreach(var go in interiorModelList) * { * // = activeVessel.vesselTransform;// .rootPart.transform.rotation; * }*/ lastTransform = hmdTransform; } } } }
protected override void Render() { EnsureDllsLoaded(); Lock = true; EVRInitError initError = EVRInitError.None; Valve.VR.OpenVR.Init(ref initError); if (initError != EVRInitError.None) { throw new Exception("OpenVR init error " + initError + ": " + Valve.VR.OpenVR.GetStringForHmdError(initError)); } CVRSystem hmd = Valve.VR.OpenVR.System; CVRCompositor compositor = Valve.VR.OpenVR.Compositor; uint targetWidth = 0, targetHeight = 0; hmd.GetRecommendedRenderTargetSize(ref targetWidth, ref targetHeight); float sceneWidth = (float)targetWidth; float sceneHeight = (float)targetHeight; float l_left = 0.0f, l_right = 0.0f, l_top = 0.0f, l_bottom = 0.0f; hmd.GetProjectionRaw(EVREye.Eye_Left, ref l_left, ref l_right, ref l_top, ref l_bottom); float r_left = 0.0f, r_right = 0.0f, r_top = 0.0f, r_bottom = 0.0f; hmd.GetProjectionRaw(EVREye.Eye_Right, ref r_left, ref r_right, ref r_top, ref r_bottom); Vector2 tanHalfFov = new Vector2( Math.Max(Math.Max(-l_left, l_right), Math.Max(-r_left, r_right)), Math.Max(Math.Max(-l_top, l_bottom), Math.Max(-r_top, r_bottom)) ); VRTextureBounds_t[] textureBounds = new VRTextureBounds_t[2]; textureBounds[0].uMin = 0.5f + 0.5f * l_left / tanHalfFov.X; textureBounds[0].uMax = 0.5f + 0.5f * l_right / tanHalfFov.X; textureBounds[0].vMin = 0.5f - 0.5f * l_bottom / tanHalfFov.Y; textureBounds[0].vMax = 0.5f - 0.5f * l_top / tanHalfFov.Y; textureBounds[1].uMin = 0.5f + 0.5f * r_left / tanHalfFov.X; textureBounds[1].uMax = 0.5f + 0.5f * r_right / tanHalfFov.X; textureBounds[1].vMin = 0.5f - 0.5f * r_bottom / tanHalfFov.Y; textureBounds[1].vMax = 0.5f - 0.5f * r_top / tanHalfFov.Y; float aspect = tanHalfFov.X / tanHalfFov.Y; float lookFov = (float)(2.0f * Math.Atan(tanHalfFov.Y) * 180 / Math.PI); Texture2DDescription eyeTextureDescription = new Texture2DDescription() { Format = Format.R8G8B8A8_UNorm_SRgb, ArraySize = 1, MipLevels = 1, Width = (int)targetWidth, Height = (int)targetHeight, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default, BindFlags = BindFlags.RenderTarget, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None }; Texture2DDescription eyeDepthTextureDescription = new Texture2DDescription() { Format = Format.D32_Float_S8X24_UInt, ArraySize = 1, MipLevels = 1, Width = (int)targetWidth, Height = (int)targetHeight, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default, BindFlags = BindFlags.DepthStencil, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None }; ///// CUBE //var cubeEffect = new SharpDX.Toolkit.Graphics.BasicEffect(_gd) //{ // //PreferPerPixelLighting = false, // //TextureEnabled = false, // LightingEnabled = true, // //DiffuseColor = new Vector4(0.5f,0.5f,0.5f,1f), // Sampler = _gd.SamplerStates.AnisotropicClamp //}; //cubeEffect.EnableDefaultLighting(); //var cube = SharpDX.Toolkit.Graphics.GeometricPrimitive.Teapot.New(_gd, 1, 8, false); ///// END using (_device = new Device(DriverType.Hardware, DeviceCreationFlags.BgraSupport, new FeatureLevel[] { FeatureLevel.Level_10_0 })) using (DeviceContext context = _device.ImmediateContext) using (_gd = SharpDX.Toolkit.Graphics.GraphicsDevice.New(_device)) //using (SharpDX.Toolkit.Graphics.GeometricPrimitive primitive = GraphicTools.CreateGeometry(_projection, _gd, false)) using (customEffectL = GetCustomEffect(_gd)) using (customEffectR = GetCustomEffect(_gd)) using (Texture2D leftEye = new Texture2D(_device, eyeTextureDescription)) using (RenderTargetView leftEyeView = new RenderTargetView(_device, leftEye)) using (Texture2D leftEyeDepth = new Texture2D(_device, eyeDepthTextureDescription)) using (DepthStencilView leftEyeDepthView = new DepthStencilView(_device, leftEyeDepth)) using (Texture2D rightEye = new Texture2D(_device, eyeTextureDescription)) using (RenderTargetView rightEyeView = new RenderTargetView(_device, rightEye)) using (Texture2D rightEyeDepth = new Texture2D(_device, eyeDepthTextureDescription)) using (DepthStencilView rightEyeDepthView = new DepthStencilView(_device, rightEyeDepth)) using (vrui = new VRUI(_device, _gd)) { //primitive = GraphicTools.CreateGeometry(Projection, _gd, false); Stopwatch stopwatch = new Stopwatch(); Texture_t leftEyeTex = new Texture_t() { eColorSpace = EColorSpace.Gamma, eType = EGraphicsAPIConvention.API_DirectX, handle = leftEye.NativePointer }; Texture_t rightEyeTex = new Texture_t() { eColorSpace = EColorSpace.Gamma, eType = EGraphicsAPIConvention.API_DirectX, handle = rightEye.NativePointer }; TrackedDevicePose_t[] renderPoseArray = new TrackedDevicePose_t[16]; TrackedDevicePose_t[] gamePoseArray = new TrackedDevicePose_t[16]; TrackedDevicePose_t pose = new TrackedDevicePose_t(); try { // Start with default background SetDefaultScene(); while (!abort) { UpdateContentIfRequested(); float deltaTime = (float)stopwatch.Elapsed.TotalSeconds; stopwatch.Restart(); compositor.WaitGetPoses(renderPoseArray, gamePoseArray); if (renderPoseArray[Valve.VR.OpenVR.k_unTrackedDeviceIndex_Hmd].bPoseIsValid) { pose = gamePoseArray[Valve.VR.OpenVR.k_unTrackedDeviceIndex_Hmd]; } foreach (EVREye eye in new EVREye[] { EVREye.Eye_Left, EVREye.Eye_Right }) { DepthStencilView currentEyeDepthView = (eye == EVREye.Eye_Left) ? leftEyeDepthView : rightEyeDepthView; RenderTargetView currentEyeView = (eye == EVREye.Eye_Left) ? leftEyeView : rightEyeView; // Setup targets and viewport for rendering context.OutputMerger.SetTargets(currentEyeDepthView, currentEyeView); context.ClearDepthStencilView(currentEyeDepthView, DepthStencilClearFlags.Depth, 1.0f, 0); context.ClearRenderTargetView(currentEyeView, Color.Black); context.Rasterizer.SetViewport(new Viewport(0, 0, (int)targetWidth, (int)targetHeight, 0.0f, 1.0f)); Quaternion lookRotation; // = pose.mDeviceToAbsoluteTracking.GetRotation(); Vector3 lookPosition; // = pose.mDeviceToAbsoluteTracking.GetPosition(); Vector3 scale; Matrix eyePose = hmd.GetEyeToHeadTransform(eye).RebuildTRSMatrix() * pose.mDeviceToAbsoluteTracking.RebuildTRSMatrix(); eyePose.Decompose(out scale, out lookRotation, out lookPosition); Matrix rotationMatrix = Matrix.RotationQuaternion(lookRotation); Vector3 lookUp = Vector3.Transform(Vector3.Up, rotationMatrix).ToVector3(); Vector3 lookAt = Vector3.Transform(Vector3.ForwardRH, rotationMatrix).ToVector3(); //Console.WriteLine($"OpenVR {eye} up: {lookUp:00.00} at: {lookAt:00.00} position:{lookPosition:00.00}"); Matrix viewMatrix = Matrix.LookAtRH(lookPosition, lookPosition + lookAt, lookUp); Matrix pm1 = Matrix.PerspectiveFovLH(lookFov * ((float)Math.PI / 180f), aspect, 0.001f, 100.0f); //Matrix pm2 = hmd.GetProjectionMatrix(eye, 0.001f, 100f, EGraphicsAPIConvention.API_DirectX).ToProjMatrix(); Matrix projectionMatrix = pm1; Matrix worldMatrix = Matrix.Translation(lookPosition); if (Logic.Instance.settings.OpenVRReverse) { worldMatrix = Matrix.RotationY(180) * worldMatrix; } Matrix MVP = worldMatrix * viewMatrix * projectionMatrix; customEffectL.Parameters["WorldViewProj"].SetValue(MVP); customEffectR.Parameters["WorldViewProj"].SetValue(MVP); lock (localCritical) { if (eye == EVREye.Eye_Left) { primitive?.Draw(customEffectL); } if (eye == EVREye.Eye_Right) { primitive?.Draw(customEffectR); } } if (eye == EVREye.Eye_Left) { Vector3 fixedLookPosition = Vector3.Transform(lookPosition, MVP).ToVector3(); Vector3 fixedLookAt = Vector3.Transform(lookPosition + Vector3.ForwardLH, MVP).ToVector3() - fixedLookPosition; Vector3 fixedLookUp = Vector3.Transform(lookPosition + Vector3.Up, MVP).ToVector3() - fixedLookPosition; fixedLookAt.Normalize(); fixedLookUp.Normalize(); Quaternion fixedLookRotation = Quaternion.LookAtRH(Vector3.Zero, fixedLookAt, fixedLookUp); //fixedLookRotation.X *= -1; //fixedLookRotation.Y *= -1; fixedLookRotation.Z *= -1; //if(eye == EVREye.Eye_Left) // fixedLookRotation.Invert(); //Mirror effect of rotation along z axis by flipping x and y elements of the quaternion. //http://stackoverflow.com/a/32482386/785171 //float t = fixedLookRotation.X; //fixedLookRotation.X = fixedLookRotation.Y; //fixedLookRotation.Y = t; //fixedLookRotation = new Quaternion(1, 0, 0, 0) * fixedLookRotation; //fixedLookRotation = new Quaternion(0, 0, 1, 0) * fixedLookRotation; LoggerManager.Publish("openvr.forward", fixedLookAt); LoggerManager.Publish("openvr.up", fixedLookUp); // TODO: normalize ProvideLook?.Invoke(fixedLookPosition, fixedLookRotation, lookFov); } // reset UI position every frame if it is not visible if (vrui.isUIHidden) { vrui.SetWorldPosition(viewMatrix.Forward, lookPosition, false); } vrui.Draw(Media, currentTime, Duration); vrui.Render(deltaTime, viewMatrix, projectionMatrix, lookPosition, ShouldShowVRUI); //// controllers: //cubeEffect.View = viewMatrix; //cubeEffect.Projection = projectionMatrix; //for (uint controller = 1 /*skip hmd*/; controller < Valve.VR.OpenVR.k_unMaxTrackedDeviceCount; controller++) //{ // VRControllerState_t controllerState = default(VRControllerState_t); // //var controllerPose = renderPoseArray[controller]; // //if (hmd.GetControllerState(controller, ref controllerState)) { // Vector3 pos = renderPoseArray[controller].mDeviceToAbsoluteTracking.GetPosition(); // Quaternion rot = renderPoseArray[controller].mDeviceToAbsoluteTracking.GetRotation(); // rot = rot * new Quaternion(0, 1, 0, 0); // float s = controllerState.ulButtonPressed > 0 ? 0.5f : 0.1f; // cubeEffect.World = Matrix.Scaling(s) * Matrix.RotationQuaternion(rot) * Matrix.Translation(pos); // cube.Draw(cubeEffect); // //} //} } // RENDER TO HMD EVRCompositorError errorLeft = compositor.Submit( EVREye.Eye_Left, ref leftEyeTex, ref textureBounds[0], EVRSubmitFlags.Submit_Default ); EVRCompositorError errorRight = compositor.Submit( EVREye.Eye_Right, ref rightEyeTex, ref textureBounds[1], EVRSubmitFlags.Submit_Default ); if (errorLeft != EVRCompositorError.None) { throw new HeadsetError("VR Compositor failure (left): " + errorLeft); } if (errorRight != EVRCompositorError.None) { throw new HeadsetError("VR Compositor failure (right): " + errorRight); } } ; } finally { Valve.VR.OpenVR.Shutdown(); primitive?.Dispose(); context.ClearState(); context.Flush(); } } }