示例#1
0
        /// <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());
            }
        }
示例#2
0
        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}");
            }
        }
示例#3
0
 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));
        }
示例#5
0
 /// <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 + "`");*/
 }
示例#6
0
        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;
                    }
                }
            }
        }
示例#7
0
        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}");
            }
        }
示例#9
0
            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;
                                    }
                    }
                }
            }
示例#10
0
    // 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.");
                }
            }
        }
    }
示例#11
0
        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));
        }
示例#12
0
        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();
        }
示例#13
0
        /// <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;
        }
示例#14
0
        /// <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;
        }
示例#15
0
        /// <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;
        }
示例#16
0
        /// <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);
            }
        }
示例#17
0
            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);
                        }
                }
            }
示例#18
0
        /// <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());
            }
        }
示例#19
0
        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}");
            }
        }
示例#20
0
            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;
                            }
                        }
                }
            }
示例#21
0
        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();
                                                                    }
                                                                }
        }