private DXDevice CreateDXDevice()
        {
            DXDevice dxDevice;

            // To use the same resources (Vertex, Index buffers and Textures) on multiple DXViewportViews,
            // we need to first creat a DXDevice and then initialize all DXViewportViews with that DXDevice instance.

            var dxDeviceConfiguration = new DXDeviceConfiguration();

            dxDeviceConfiguration.DriverType = DriverType.Hardware; // We could also specify Software rendering here

            try
            {
                dxDevice = new DXDevice(dxDeviceConfiguration);
                dxDevice.InitializeDevice();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Cannot create required DirectX device.\r\n" + ex.Message);
                return(null);
            }

            if (dxDevice.Device == null)
            {
                MessageBox.Show("Cannot create required DirectX device.");
                return(null);
            }

            return(dxDevice);
        }
Exemplo n.º 2
0
        /// <summary>
        /// InitializeOvrAndDXDevice method initializes the Oculus OVR and creates a new DXDevice that uses the same adapter (graphic card) as Oculus Rift.
        /// User need to dispose the created DXDevice when it is not needed any more.
        /// This method can throw exceptions in case initialization of OVR or DirectX failes.
        /// </summary>
        /// <param name="requestedOculusSdkMinorVersion">minimal version of Oculus SKD that is required for this application (default value is 17)</param>
        /// <returns>Created DXDevice that needs to be disposed by the user</returns>
        public DXDevice InitializeOvrAndDXDevice(int requestedOculusSdkMinorVersion = 17)
        {
            if (_sessionPtr != IntPtr.Zero)
            {
                throw new Exception("InitializeOvrAndDXDevice cannot be called after the sessionPtr was already set.");
            }


            // Define initialization parameters with debug flag.
            var initializationParameters = new InitParams();

            // In Oculus SDK 1.8 and newer versions, it is required to specify to which version the application is build
            initializationParameters.Flags = InitFlags.RequestVersion;
            initializationParameters.RequestedMinorVersion = (uint)requestedOculusSdkMinorVersion;

            // Initialize the Oculus runtime.
            var result = _ovr.Initialize(initializationParameters);

            if (result < Result.Success)
            {
                throw new OvrException("Failed to initialize the Oculus runtime library.", result);
            }


            // Use the head mounted display.
            var adapterLuid = new GraphicsLuid();

            result = _ovr.Create(ref _sessionPtr, ref adapterLuid);

            if (result < Result.Success)
            {
                throw new OvrException("Oculus Rift not detected", result);
            }


            _hmdDesc = _ovr.GetHmdDesc(_sessionPtr);


            // Get adapter (graphics card) used by Oculus
            Adapter1 hmdAdapter;

            if (adapterLuid.Reserved != null && adapterLuid.Reserved.Length == 4)
            {
                var allSystemAdapters = DXDevice.GetAllSystemAdapters();

                long adapterUid = Convert.ToInt64(adapterLuid.Reserved); // adapterLuid.Reserved is byte array
                hmdAdapter = allSystemAdapters.FirstOrDefault(a => a.Description1.Luid == adapterUid);
            }
            else
            {
                hmdAdapter = null;
            }

            // Create DXEngine's DirectX Device with the same adapter (graphics card) that is used for Oculus Rift
            var dxDeviceConfiguration = new DXDeviceConfiguration();

            if (hmdAdapter != null)
            {
                dxDeviceConfiguration.Adapter = hmdAdapter;
            }

            dxDeviceConfiguration.DriverType             = DriverType.Hardware;
            dxDeviceConfiguration.SupportedFeatureLevels = new FeatureLevel[] { FeatureLevel.Level_11_0 };

            // Create DirectX device
            var dxDevice = new DXDevice(dxDeviceConfiguration);

            dxDevice.InitializeDevice();

            return(dxDevice);
        }
        /// <summary>
        /// CreateDXViewportView
        /// </summary>
        /// <param name="clientWindowWidth">clientWindowWidth</param>
        /// <param name="clientWindowHeight">clientWindowHeight</param>
        /// <param name="dpiScaleX">DPI scale: 1 means no scale (96 DPI)</param>
        /// <param name="dpiScaleY">DPI scale: 1 means no scale (96 DPI)</param>
        /// <param name="preferedMultisamplingCount">preferedMultisamplingCount</param>
        public void InitializeDXViewportView(int clientWindowWidth,
                                             int clientWindowHeight,
                                             double dpiScaleX,
                                             double dpiScaleY,
                                             int preferedMultisamplingCount)
        {
            // To render the 3D scene to the custom hWnd, we need to create the DXViewportView with a custom DXScene,
            // that was initialized with calling InitializeSwapChain mathod (with passed hWnd).

            // To create a custom DXScene we first need to create a DXDevice objects (wrapper around DirectX Device object)
            var dxDeviceConfiguration = new DXDeviceConfiguration();

            dxDeviceConfiguration.DriverType = DriverType.Hardware; // We could also specify Software rendering here

            try
            {
                _dxDevice = new DXDevice(dxDeviceConfiguration);
                _dxDevice.InitializeDevice();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Cannot create required DirectX device.\r\n" + ex.Message);
                return;
            }

            if (_dxDevice.Device == null)
            {
                MessageBox.Show("Cannot create required DirectX device.");
                return;
            }


            // Now we can create the DXScene
            dxScene = new Ab3d.DirectX.DXScene(_dxDevice);

            // ensure we have a valid size; we will resize later to the correct size
            if (clientWindowWidth <= 0)
            {
                clientWindowWidth = 1;
            }
            if (clientWindowHeight <= 0)
            {
                clientWindowHeight = 1;
            }

            dxScene.InitializeSwapChain(_hWnd,
                                        (int)(clientWindowWidth * dpiScaleX),
                                        (int)(clientWindowHeight * dpiScaleY),
                                        preferedMultisamplingCount,
                                        (float)dpiScaleX,
                                        (float)dpiScaleY);


            wpfViewport3D = new Viewport3D();

            dxViewportView = new DXViewportView(dxScene, wpfViewport3D);


            // Because _dxViewportView is not shown in the UI, the DXEngineShoop (DXEngine's diagnostics tool) cannot find it
            // To enable using DXEngineSnoop in such cases, we can set the Application's Property:
            Application.Current.Properties["DXView"] = new WeakReference(dxViewportView);

            OnDXViewportViewInitialized();
        }
Exemplo n.º 4
0
        private void InitializeOvrAndDirectX()
        {
            if (UseOculusRift)
            {
                // Initializing Oculus VR is very simple when using OculusWrapVirtualRealityProvider
                // First we create an instance of OculusWrapVirtualRealityProvider
                _oculusRiftVirtualRealityProvider = new OculusWrapVirtualRealityProvider(_ovr, multisamplingCount: 4);

                try
                {
                    // Then we initialize Oculus OVR and create a new DXDevice that uses the same adapter (graphic card) as Oculus Rift
                    _dxDevice = _oculusRiftVirtualRealityProvider.InitializeOvrAndDXDevice(requestedOculusSdkMinorVersion: 17);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Failed to initialize the Oculus runtime library.\r\nError: " + ex.Message, "Oculus error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                string ovrVersionString = _ovr.GetVersionString();
                _originalWindowTitle = string.Format("DXEngine OculusWrap Sample (OVR v{0})", ovrVersionString);
                this.Title           = _originalWindowTitle;


                // Reset tracking origin at startup
                _ovr.RecenterTrackingOrigin(_oculusRiftVirtualRealityProvider.SessionPtr);
            }
            else
            {
                // Create DXDevice that will be used to create DXViewportView
                var dxDeviceConfiguration = new DXDeviceConfiguration();
                dxDeviceConfiguration.DriverType             = DriverType.Hardware;
                dxDeviceConfiguration.SupportedFeatureLevels = new FeatureLevel[] { FeatureLevel.Level_11_0 }; // Oculus requires at least feature level 11.0

                _dxDevice = new DXDevice(dxDeviceConfiguration);
                _dxDevice.InitializeDevice();

                _originalWindowTitle = this.Title;
            }



            // Create WPF's Viewport3D
            _viewport3D = new Viewport3D();

            // Create DXViewportView - a control that will enable DirectX 11 rendering of standard WPF 3D content defined in Viewport3D.
            // We use a specified DXDevice that was created by the _oculusRiftVirtualRealityProvider.InitializeOvrAndDXDevice (this way the same adapter is used by Oculus and DXEngine).
            _dxViewportView = new DXViewportView(_dxDevice, _viewport3D);

            _dxViewportView.BackgroundColor = Colors.Aqua;

            // Currently DXEngine support showing Oculus mirror texture only with DirectXOverlay presentation type (not with DirectXImage)
            _dxViewportView.PresentationType = DXView.PresentationTypes.DirectXOverlay;

            if (UseOculusRift)
            {
                // The _dxViewportView will show Oculus mirrow window.
                // The mirror window can be any size, for this sample we use 1/2 the HMD resolution.
                _dxViewportView.Width  = _oculusRiftVirtualRealityProvider.HmdDescription.Resolution.Width / 2.0;
                _dxViewportView.Height = _oculusRiftVirtualRealityProvider.HmdDescription.Resolution.Height / 2.0;
            }


            // When the DXViewportView is initialized, we set the _oculusRiftVirtualRealityProvider to the DXScene object
            _dxViewportView.DXSceneInitialized += delegate(object sender, EventArgs args)
            {
                if (_dxViewportView.UsedGraphicsProfile.DriverType != GraphicsProfile.DriverTypes.Wpf3D &&
                    _dxViewportView.DXScene != null &&
                    _oculusRiftVirtualRealityProvider != null)
                {
                    // Initialize Virtual reality rendering
                    _dxViewportView.DXScene.InitializeVirtualRealityRendering(_oculusRiftVirtualRealityProvider);


                    // Initialized shadow rendering (see Ab3d.DXEngine.Wpf.Samples project - DXEngine/ShadowRenderingSample for more info
                    _varianceShadowRenderingProvider = new VarianceShadowRenderingProvider()
                    {
                        ShadowMapSize          = 1024,
                        ShadowDepthBluringSize = 2,
                        ShadowTreshold         = 0.2f
                    };

                    _dxViewportView.DXScene.InitializeShadowRendering(_varianceShadowRenderingProvider);
                }
            };


            // Enable collecting rendering statistics (see _dxViewportView.DXScene.Statistics class)
            DXDiagnostics.IsCollectingStatistics = true;

            // Subscribe to SceneRendered to collect FPS statistics
            _dxViewportView.SceneRendered += DXViewportViewOnSceneRendered;

            // Add _dxViewportView to the RootGrid
            // Before that we resize the window to be big enough to show the mirrored texture
            this.Width  = _dxViewportView.Width + 30;
            this.Height = _dxViewportView.Height + 50;

            RootGrid.Children.Add(_dxViewportView);


            // Create FirstPersonCamera
            _camera = new FirstPersonCamera()
            {
                TargetViewport3D = _viewport3D,
                Position         = new Point3D(0, 1, 4),
                Heading          = 0,
                Attitude         = 0,
                ShowCameraLight  = ShowCameraLightType.Never
            };

            RootGrid.Children.Add(_camera);


            // Initialize XBOX controller that will control the FirstPersonCamera
            _xInputCameraController = new XInputCameraController();
            _xInputCameraController.TargetCamera  = _camera;
            _xInputCameraController.MovementSpeed = 0.02;
            _xInputCameraController.MoveVerticallyWithDPadButtons = true;

            // We handle the rotation by ourself to prevent rotating the camera up and down - this is done only by HMD
            _xInputCameraController.RightThumbChanged += delegate(object sender, XInputControllerThumbChangedEventArgs e)
            {
                // Apply only horizontal rotation
                _camera.Heading += e.NormalizedX * _xInputCameraController.RotationSpeed;

                // Mark the event as handled
                e.IsHandled = true;
            };

            _xInputCameraController.StartCheckingController();


            // Now we can create our sample 3D scene
            CreateSceneObjects();

            // Add lights
            var lightsVisual3D = new ModelVisual3D();
            var lightsGroup    = new Model3DGroup();

            var directionalLight = new DirectionalLight(Colors.White, new Vector3D(0.5, -0.3, -0.3));

            directionalLight.SetDXAttribute(DXAttributeType.IsCastingShadow, true); // Set this light to cast shadow
            lightsGroup.Children.Add(directionalLight);

            var ambientLight = new AmbientLight(System.Windows.Media.Color.FromRgb(30, 30, 30));

            lightsGroup.Children.Add(ambientLight);

            lightsVisual3D.Content = lightsGroup;
            _viewport3D.Children.Add(lightsVisual3D);


            // Start rendering
            if (RenderAt90Fps)
            {
                // WPF do not support rendering at more the 60 FPS.
                // But with a trick where a rendering loop is created in a background thread, it is possible to achieve more than 60 FPS.
                // In case of sumbiting frames to Oculus Rift, the ovr.SubmitFrame method will limit rendering to 90 FPS.
                //
                // NOTE:
                // When using DXEngine, it is also possible to render the scene in a background thread.
                // This requires that the 3D scene is also created in the background thread and that the events and other messages are
                // passed between UI and background thread in a thread safe way. This is too complicated for this simple sample project.
                // To see one possible implementation of background rendering, see the BackgroundRenderingSample in the Ab3d.DXEngine.Wpf.Samples project.
                var backgroundWorker = new BackgroundWorker();
                backgroundWorker.DoWork += (object sender, DoWorkEventArgs args) =>
                {
                    // Create an action that will be called by Dispatcher
                    var refreshDXEngineAction = new Action(() =>
                    {
                        UpdateScene();

                        // Render DXEngine's 3D scene again
                        if (_dxViewportView != null)
                        {
                            _dxViewportView.Refresh();
                        }
                    });

                    while (_dxViewportView != null && !_dxViewportView.IsDisposed)                                                       // Render until window is closed
                    {
                        if (_oculusRiftVirtualRealityProvider != null && _oculusRiftVirtualRealityProvider.LastSessionStatus.ShouldQuit) // Stop rendering - this will call RunWorkerCompleted where we can quit the application
                        {
                            break;
                        }

                        // Sleep for 1 ms to allow WPF tasks to complete (for example handling XBOX controller events)
                        System.Threading.Thread.Sleep(1);

                        // Call Refresh to render the DXEngine's scene
                        // This is a synchronous call and will wait until the scene is rendered.
                        // Because Oculus is limited to 90 fps, the call to ovr.SubmitFrame will limit rendering to 90 FPS.
                        Dispatcher.Invoke(refreshDXEngineAction);
                    }
                };

                backgroundWorker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs args)
                {
                    if (_oculusRiftVirtualRealityProvider != null && _oculusRiftVirtualRealityProvider.LastSessionStatus.ShouldQuit)
                    {
                        this.Close(); // Exit the application
                    }
                };

                backgroundWorker.RunWorkerAsync();
            }
            else
            {
                // Subscribe to WPF rendering event (called approximately 60 times per second)
                CompositionTarget.Rendering += CompositionTargetOnRendering;
            }
        }