Exemplo n.º 1
0
        override protected void Render()
        {
            Lock = true;

            int           mainRetry = 5;
            ClientContext context;

            do
            {
                context = new ClientContext("com.bivrost360.desktopplayer");
                Thread.Sleep(50);
            }while (context == null && mainRetry-- > 0);

            DisplayConfig displayConfig = null;

            for (int retry = 0; retry < 12; retry++)
            {
                if (abort)
                {
                    context.Dispose();
                    Lock = false;
                    return;
                }

                displayConfig = context.GetDisplayConfig();

                if (displayConfig != null)
                {
                    int contextRetry = 0;
                    do
                    {
                        context.update();
                        contextRetry++;
                        if (abort)
                        {
                            context.Dispose();
                            Lock = false;
                            return;
                        }
                        Thread.Sleep(1);
                    } while (!displayConfig.CheckDisplayStartup() || contextRetry < 300);
                    if (displayConfig.CheckDisplayStartup())
                    {
                        break;
                    }
                }
            }
            if (displayConfig == null)
            {
                context.Dispose();
                Lock = false;
                return;
            }

            var numDisplayInputs = displayConfig.GetNumDisplayInputs();

            if (numDisplayInputs != 1)
            {
                context.Dispose();
                Lock = false;
                return;
            }

            var displayDimensions = displayConfig.GetDisplayDimensions(0);
            var numViewers        = displayConfig.GetNumViewers();

            if (numViewers != 1)
            {
                context.Dispose();
                Lock = false;
                return;
            }


            var form = new RenderForm("BIVROST - OSVR");

            form.Width         = displayDimensions.Width;
            form.Height        = displayDimensions.Height;
            form.ShowInTaskbar = false;


            var desc = new SwapChainDescription()
            {
                BufferCount     = 1,
                ModeDescription =
                    new ModeDescription(displayDimensions.Width, displayDimensions.Height,
                                        new Rational(60, 1), Format.R8G8B8A8_UNorm),
                IsWindowed        = true,
                OutputHandle      = form.Handle,
                SampleDescription = new SampleDescription(1, 0),
                SwapEffect        = SwapEffect.Discard,
                Usage             = Usage.RenderTargetOutput
            };

            SwapChain swapChain;

            // Create DirectX drawing device.
            //SharpDX.Direct3D11.Device device = new Device(SharpDX.Direct3D.DriverType.Hardware, DeviceCreationFlags.BgraSupport, new SharpDX.Direct3D.FeatureLevel[] { SharpDX.Direct3D.FeatureLevel.Level_10_0 });
            Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.BgraSupport, desc, out _device, out swapChain);

            // Create DirectX Graphics Interface factory, used to create the swap chain.
            Factory factory = swapChain.GetParent <Factory>();

            factory.MakeWindowAssociation(form.Handle, WindowAssociationFlags.IgnoreAll);
            form.FormBorderStyle = FormBorderStyle.None;
            form.TopMost         = true;

            DeviceContext immediateContext = _device.ImmediateContext;

            using (SharpDX.DXGI.Device2 dxgiDevice = _device.QueryInterface <SharpDX.DXGI.Device2>())
            {
                //var bounds = dxgiDevice.Adapter.Outputs[1].Description.DesktopBounds;
                //form.DesktopBounds = new System.Drawing.Rectangle(bounds.X, bounds.Y, bounds.Width, bounds.Height);

                //dxgiDevice.Adapter.Outputs.ToList().ForEach(o =>
                //{
                //    if (o.Description.DeviceName.EndsWith("2"))
                //    {
                //        swapChain.SetFullscreenState(true, o);
                //    }
                //});

                Rectangle bounds;

                if (Features.IsDebug)
                {
                    log.Info("OSVR: available screens: " + string.Join("\n", dxgiDevice.Adapter.Outputs.ToList().ConvertAll(o => o.Description.DeviceName + " (" + o.Description.DesktopBounds + ")")));
                }

                if (Logic.Instance.settings.OSVRScreen == ScreenSelection.Autodetect)
                {
                    // start with last screen
                    Output output = dxgiDevice.Adapter.Outputs[dxgiDevice.Adapter.Outputs.Length - 1];

                    // but something resembling a HDK 1.4 (1920x1080) will be better
                    foreach (var o in dxgiDevice.Adapter.Outputs)
                    {
                        var b = o.Description.DesktopBounds;
                        if (b.Width == 1920 && b.Height == 1080)
                        {
                            log.Info("OSVR: found a 1920x1080 candidate for a HDK 1.4");
                            output = o;
                        }
                    }

                    // and something resembling a HDK 2.0 (2160x1200) will be even more better
                    foreach (var o in dxgiDevice.Adapter.Outputs)
                    {
                        var b = o.Description.DesktopBounds;
                        if (b.Width == 2160 && b.Height == 1200)
                        {
                            log.Info("OSVR: found a 2160x1200 candidate for a HDK 2.0");
                            output = o;
                        }
                    }

                    bounds = output.Description.DesktopBounds;
                    log.Info($"OSVR: guessed output ({bounds})");
                }
                else
                {
                    int osvrScreen = (int)Logic.Instance.settings.OSVRScreen;
                    if (osvrScreen >= dxgiDevice.Adapter.Outputs.Length)
                    {
                        osvrScreen = dxgiDevice.Adapter.Outputs.Length - 1;
                    }
                    bounds = dxgiDevice.Adapter.Outputs[osvrScreen].Description.DesktopBounds;
                    log.Info($"OSVR: selected output #{osvrScreen} ({bounds})");
                }

                form.DesktopBounds = new System.Drawing.Rectangle(bounds.X, bounds.Y, bounds.Width, bounds.Height);

                if (dxgiDevice.Adapter.Outputs.Length <= 1)
                {
                    Logic.Notify("Only one screen is active. Press Control+S to stop the movie if needed.");
                }
            }

            // Create a depth buffer, using the same width and height as the back buffer.
            Texture2DDescription depthBufferDescription = new Texture2DDescription()
            {
                Format            = Format.D32_Float,
                ArraySize         = 1,
                MipLevels         = 1,
                Width             = displayDimensions.Width,
                Height            = displayDimensions.Height,
                SampleDescription = new SampleDescription(1, 0),
                Usage             = ResourceUsage.Default,
                BindFlags         = BindFlags.DepthStencil,
                CpuAccessFlags    = CpuAccessFlags.None,
                OptionFlags       = ResourceOptionFlags.None
            };



            // Retrieve the DXGI device, in order to set the maximum frame latency.
            using (SharpDX.DXGI.Device1 dxgiDevice = _device.QueryInterface <SharpDX.DXGI.Device1>())
                dxgiDevice.MaximumFrameLatency = 1;

            using (_gd = SharpDX.Toolkit.Graphics.GraphicsDevice.New(_device))
                using (customEffectL = GetCustomEffect(_gd))
                    using (customEffectR = GetCustomEffect(_gd))
                        //using (var primitive = GraphicTools.CreateGeometry(_projection, _gd))
                        using (vrui = new VRUI(_device, _gd))
                            using (Texture2D depthBuffer = new Texture2D(_device, depthBufferDescription))
                                using (DepthStencilView depthView = new DepthStencilView(_device, depthBuffer))
                                    using (Texture2D backBuffer = Texture2D.FromSwapChain <Texture2D>(swapChain, 0))
                                        using (RenderTargetView renderView = new RenderTargetView(_device, backBuffer))
                                        {
                                            //primitive = GraphicTools.CreateGeometry(Projection, _gd);

                                            DateTime startTime = DateTime.Now;
                                            Vector3  position  = new Vector3(0, 0, -1);

                                            #region Render loop

                                            DateTime lastTime  = DateTime.Now;
                                            float    deltaTime = 0;


                                            immediateContext.OutputMerger.SetTargets(depthView, renderView);


                                            form.GotFocus += (s, e) => OnGotFocus();
                                            bool first = true;

                                            RenderLoop.Run(form, () =>
                                            {
                                                if (abort)
                                                {
                                                    form.Close();
                                                    return;
                                                }

                                                if (first)
                                                {
                                                    // Start with default background
                                                    SetDefaultScene();

                                                    OnGotFocus();
                                                    first = false;
                                                }

                                                UpdateContentIfRequested();

                                                context.update();

                                                float timeSinceStart = (float)(DateTime.Now - startTime).TotalSeconds;
                                                deltaTime            = (float)(DateTime.Now - lastTime).TotalSeconds;
                                                lastTime             = DateTime.Now;

                                                immediateContext.ClearDepthStencilView(depthView, DepthStencilClearFlags.Depth, 1.0f, 0);
                                                immediateContext.ClearRenderTargetView(renderView, Color.Black);

                                                uint viewer = 0;

                                                for (int eyeIndex = 0; eyeIndex < 2; eyeIndex++)
                                                {
                                                    var numEyes    = displayConfig.GetNumEyesForViewer(viewer);
                                                    var viewerPose = displayConfig.GetViewerPose(viewer);



                                                    for (byte eye = 0; eye < numEyes; eye++)
                                                    {
                                                        uint numSurfaces           = displayConfig.GetNumSurfacesForViewerEye(viewer, eye);
                                                        Pose3 viewerEyePose        = displayConfig.GetViewerEyePose(viewer, eye);
                                                        Matrix44f viewerEyeMatrixf = displayConfig.GetViewerEyeViewMatrixf(viewer, eye, MatrixConventionsFlags.Default);
                                                        uint surface = 0;
                                                        OSVR.ClientKit.Viewport viewport = displayConfig.GetRelativeViewportForViewerEyeSurface(viewer, eye, surface);
                                                        Matrix44f projectionf            = displayConfig.GetProjectionMatrixForViewerEyeSurfacef(viewer, eye, surface, 0.001f, 1000.0f, MatrixConventionsFlags.Default);
                                                        ProjectionClippingPlanes projectionClippingPlanes = displayConfig.GetViewerEyeSurfaceProjectionClippingPlanes(viewer, eye, surface);

                                                        ViewportF vp = new ViewportF(viewport.Left, viewport.Bottom, viewport.Width, viewport.Height);
                                                        immediateContext.Rasterizer.SetViewport(vp);

                                                        Vector3 lookPosition = viewerEyePose.translation.ToVector3();

                                                        SharpDX.Quaternion lookRotation = viewerEyePose.rotation.ToQuaternion();
                                                        Matrix rotationMatrix           = Matrix.RotationQuaternion(lookRotation);
                                                        Vector3 lookUp    = Vector3.Transform(new Vector3(0, 1, 0), rotationMatrix).ToVector3();
                                                        Vector3 lookAt    = Vector3.Transform(new Vector3(0, 0, -1), rotationMatrix).ToVector3();
                                                        Matrix viewMatrix = Matrix.LookAtRH(lookPosition, lookPosition + lookAt, lookUp);

                                                        Matrix projectionMatrix = projectionf.ToMatrix();

                                                        Matrix worldMatrix = Matrix.Translation(lookPosition);

                                                        Matrix MVP = worldMatrix * viewMatrix * projectionMatrix;
                                                        customEffectL.Parameters["WorldViewProj"].SetValue(MVP);
                                                        customEffectR.Parameters["WorldViewProj"].SetValue(MVP);

                                                        lock (localCritical)
                                                        {
                                                            if (eye == 0)
                                                            {
                                                                primitive?.Draw(customEffectL);
                                                            }
                                                            if (eye == 1)
                                                            {
                                                                primitive?.Draw(customEffectR);
                                                            }
                                                        }

                                                        // reset UI position every frame if it is not visible
                                                        if (vrui.isUIHidden)
                                                        {
                                                            vrui.SetWorldPosition(viewMatrix.Forward, lookPosition, true);
                                                        }

                                                        if (eye == 0)
                                                        {
                                                            lookRotation.Invert();
                                                            ProvideLook?.Invoke(lookPosition, lookRotation, OSVRFOV);
                                                        }

                                                        vrui.Draw(Media, currentTime, Duration);
                                                        vrui.Render(deltaTime, viewMatrix, projectionMatrix, lookPosition, ShouldShowVRUI);
                                                    }
                                                }

                                                swapChain.Present(0, PresentFlags.None);
                                            });

                                            #endregion
                                            //debugWindow.Stop();

                                            waitForRendererStop.Set();

                                            //swapChain.SetFullscreenState(false, null);



                                            immediateContext.ClearState();
                                            immediateContext.Flush();
                                            immediateContext.Dispose();

                                            swapChain.Dispose();

                                            factory.Dispose();

                                            //swapChain.Dispose();

                                            // Disposing the device, before the hmd, will cause the hmd to fail when disposing.
                                            // Disposing the device, after the hmd, will cause the dispose of the device to fail.
                                            // It looks as if the hmd steals ownership of the device and destroys it, when it's shutting down.
                                            // device.Dispose();
                                            base._device.Dispose();

                                            //hmd.Dispose();
                                            //oculus.Dispose();

                                            displayConfig.Dispose();
                                            context.Dispose();
                                        }

            Lock = false;
        }
Exemplo n.º 2
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();
                                                                    }
                                                                }
        }