// This method is called approximately 60 times per second but only when RenderAt90Fps const is false private void CompositionTargetOnRendering(object sender, EventArgs eventArgs) { // It's possible for Rendering to call back twice in the same frame. // So only render when we haven't already rendered in this frame. var renderingEventArgs = eventArgs as System.Windows.Media.RenderingEventArgs; if (renderingEventArgs != null) { if (renderingEventArgs.RenderingTime == _lastRenderTime) { return; } _lastRenderTime = renderingEventArgs.RenderingTime; } if (_dxViewportView == null || _dxViewportView.IsDisposed) { return; // Window closed } if (_oculusRiftVirtualRealityProvider != null && _oculusRiftVirtualRealityProvider.LastSessionStatus.ShouldQuit) { this.Close(); // Exit the application } if (_oculusRiftVirtualRealityProvider == null) { return; } UpdateScene(); // Render the scene again _dxViewportView.Refresh(); }
private void OnShowObjectOutlineCheckBoxCheckedChanged(object sender, RoutedEventArgs e) { if (!this.IsLoaded || _renderObjectOutlinesRenderingStep == null) { return; } _renderObjectOutlinesRenderingStep.IsEnabled = ShowObjectOutlineCheckBox.IsChecked ?? false; _mainDXViewportView.Refresh(); }
private void CreateTestScene(int totalModelsCount) { Mouse.OverrideCursor = Cursors.Wait; // Creating Model3DGroup takes too much time when a lot of objects are created. // Therefore we are creating SceneNodes (MeshObjectNode) directly. //var model3DGroup = CreateModel3DGroup(boxMesh, new Point3D(0, 0, 0), new Size3D(400, 100, 400), 5, 40, 40, 40); //var model3DGroup = CreateModel3DGroup(boxMesh, new Point3D(0, 0, 0), new Size3D(400, 200, 400), 5, 40, 20, 40); //var model3DGroup = CreateModel3DGroup(boxMesh, new Point3D(0, 0, 0), new Size3D(400, 200, 400), 10, 10, 5, 10); //modelsCount = model3DGroup.Children.Count; //MainViewport.Children.Add(model3DGroup.CreateModelVisual3D()); try { if (_sceneNodeVisual3D != null) { _mainViewport3D.Children.Remove(_sceneNodeVisual3D); _sceneNodeVisual3D.SceneNode.Dispose(); } var boxMesh = new BoxMesh3D(new Point3D(0, 0, 0), new Size3D(1, 1, 1), 1, 1, 1).Geometry; int modelsXZCount = totalModelsCount < 2500 ? 10 : 50; int modelsYCount = totalModelsCount / (modelsXZCount * modelsXZCount); var sceneNode = CreateSceneNodes(boxMesh, new Point3D(0, 0, 0), new Size3D(500, modelsYCount * 10, 500), 5, modelsXZCount, modelsYCount, modelsXZCount); _objectsCount = sceneNode.ChildNodesCount; _sceneNodeVisual3D = new SceneNodeVisual3D(sceneNode); _mainViewport3D.Children.Add(_sceneNodeVisual3D); _mainDXViewportView.Refresh(); } finally { Mouse.OverrideCursor = null; } }
private void CreateTestScene(int totalModelsCount) { Mouse.OverrideCursor = Cursors.Wait; // Creating Model3DGroup takes too much time when a lot of objects are created. // Therefore we are creating SceneNodes (MeshObjectNode) directly. //var model3DGroup = CreateModel3DGroup(boxMesh, new Point3D(0, 0, 0), new Size3D(400, 100, 400), 5, 40, 40, 40); //var model3DGroup = CreateModel3DGroup(boxMesh, new Point3D(0, 0, 0), new Size3D(400, 200, 400), 5, 40, 20, 40); //var model3DGroup = CreateModel3DGroup(boxMesh, new Point3D(0, 0, 0), new Size3D(400, 200, 400), 10, 10, 5, 10); //modelsCount = model3DGroup.Children.Count; //MainViewport.Children.Add(model3DGroup.CreateModelVisual3D()); try { if (_disposables != null) { _disposables.Dispose(); } if (_sceneNodeVisual3D != null) { _mainViewport3D.Children.Remove(_sceneNodeVisual3D); _sceneNodeVisual3D.SceneNode.Dispose(); _sceneNodeVisual3D = null; } _disposables = new DisposeList(); var boxMesh = new BoxMesh3D(new Point3D(0, 0, 0), new Size3D(1, 1, 1), 1, 1, 1).Geometry; int modelsXZCount = totalModelsCount < 2500 ? 10 : 50; int modelsYCount = totalModelsCount / (modelsXZCount * modelsXZCount); bool useSingleColor = _currentObjectsType == ObjectsTypes.SingleColorBoxes || _currentObjectsType == ObjectsTypes.SingleColorLines; SceneNode sceneNode; if (_currentObjectsType == ObjectsTypes.MultiColorBoxes || _currentObjectsType == ObjectsTypes.SingleColorBoxes) { sceneNode = CreateBoxSceneNodes(boxMesh, new Point3D(0, 0, 0), new Size3D(500, modelsYCount * 10, 500), 5, useSingleColor, modelsXZCount, modelsYCount, modelsXZCount); } else if (_currentObjectsType == ObjectsTypes.MultiColorLines || _currentObjectsType == ObjectsTypes.SingleColorLines) { sceneNode = CreateLineSceneNodes(new Point3D(0, 0, 0), new Size3D(500, modelsYCount * 10, 500), useSingleColor, modelsXZCount, modelsYCount, modelsXZCount, _disposables); } else if (_currentObjectsType == ObjectsTypes.MultiColorBoxesAndLines) { sceneNode = new SceneNode(); var sceneNode1 = CreateBoxSceneNodes(boxMesh, new Point3D(0, -modelsYCount * 2.5 - 10, 0), new Size3D(500, modelsYCount * 5, 500), 5, useSingleColor, modelsXZCount, modelsYCount / 2, modelsXZCount); var sceneNode2 = CreateLineSceneNodes(new Point3D(0, modelsYCount * 2.5 + 10, 0), new Size3D(500, modelsYCount * 5, 500), useSingleColor, modelsXZCount, modelsYCount / 2, modelsXZCount, _disposables); sceneNode.AddChild(sceneNode1); sceneNode.AddChild(sceneNode2); } else { sceneNode = null; } if (sceneNode == null) { return; } _objectsCount = totalModelsCount; _sceneNodeVisual3D = new SceneNodeVisual3D(sceneNode); _mainViewport3D.Children.Add(_sceneNodeVisual3D); _mainDXViewportView.Refresh(); } finally { Mouse.OverrideCursor = null; } }
private void RenderSceneInternal() { dxViewportView.Refresh(); isSceneDirty = false; }
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; } }
private DXViewportView AddNewDXViewportView(DXViewportView masterDXViewportView, int rowIndex, int columnIndex, RenderingTypes renderingType, bool addToRootGrid = true, bool addDrawSelectionComboBox = true) { TargetPositionCamera targetPositionCamera; MouseCameraController mouseCameraController; DXViewportView dxViewportView = CreateSimpleDXSceneViewFromCode(masterDXViewportView, renderingType, out targetPositionCamera, out mouseCameraController); // Set random BackgroundColor - but do not make it to dark so start with 128 dxViewportView.BackgroundColor = Color.FromRgb((byte)(_rnd.Next(128) + 128), (byte)(_rnd.Next(128) + 128), (byte)(_rnd.Next(128) + 128)); _dxViewportViews.Add(dxViewportView); if (addToRootGrid) { var viewRootGrid = new Grid(); var border = new Border() { Background = Brushes.Transparent, Margin = new Thickness(1, 1, 3, 3) }; border.Child = dxViewportView; mouseCameraController.EventsSourceElement = border; viewRootGrid.Children.Add(border); viewRootGrid.Children.Add(targetPositionCamera); viewRootGrid.Children.Add(mouseCameraController); Grid.SetColumn(viewRootGrid, columnIndex); Grid.SetRow(viewRootGrid, rowIndex); ViewsGrid.Children.Add(viewRootGrid); var textBlock = new TextBlock() { HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Top, Margin = new Thickness(5, 5, 0, 0) }; textBlock.Text = masterDXViewportView == null ? "Master DXScene:" : "Child DXScene:"; viewRootGrid.Children.Add(textBlock); if (addDrawSelectionComboBox) { var comboBox = new ComboBox() { HorizontalAlignment = HorizontalAlignment.Right, VerticalAlignment = VerticalAlignment.Top, Margin = new Thickness(0, 3, 5, 0) }; comboBox.ItemsSource = RenderingTypeStrings; comboBox.SelectedIndex = (int)renderingType; if (masterDXViewportView == null) { comboBox.IsEditable = false; // Lock Standard for master view } comboBox.SelectionChanged += delegate(object sender, SelectionChangedEventArgs args) { var newRenderingType = (RenderingTypes)comboBox.SelectedIndex; SetSpecialRenderingType(dxViewportView, newRenderingType); dxViewportView.Refresh(); // Render the scene again }; viewRootGrid.Children.Add(comboBox); } } return(dxViewportView); }