private void CreateMouseCameraController() { // To support mouse camera rotation and movement // we create a dummy Viewport3D, a TargetPositionCamera and a MouseCameraController. // We subscribe to the TargetPositionCamera changes and propagate all the changes to the camera in the background rendering thread. var dummyViewport3D = new Viewport3D(); _targetPositionCamera = new TargetPositionCamera() { TargetViewport3D = dummyViewport3D, ShowCameraLight = ShowCameraLightType.Never }; // Because the camera will not be added to the UI three, we need to manually Refresh it _targetPositionCamera.Refresh(); // On each camera change we update the camera in the background rendering thread _targetPositionCamera.CameraChanged += delegate(object sender, CameraChangedRoutedEventArgs args) { UpdateBackgroundRendererCamera(_targetPositionCamera); }; var mouseCameraController = new Ab3d.Controls.MouseCameraController() { TargetCamera = _targetPositionCamera, EventsSourceElement = DXViewportBorder, RotateCameraConditions = Ab3d.Controls.MouseCameraController.MouseAndKeyboardConditions.LeftMouseButtonPressed, MoveCameraConditions = Ab3d.Controls.MouseCameraController.MouseAndKeyboardConditions.LeftMouseButtonPressed | Ab3d.Controls.MouseCameraController.MouseAndKeyboardConditions.ControlKey, }; mouseCameraController.CameraRotateStarted += delegate(object sender, EventArgs args) { // When the rotation is stared we need to synchronize the camera's data UpdateMainUICamera(); // If background camera is retating, we pause the rotation during the user's mouse rotation if (_isBackgroundThreadCameraRotating) { _backgroundDXEngineRenderer.StopCameraRotation(); } }; mouseCameraController.CameraRotateEnded += delegate(object sender, EventArgs args) { // resume the background camera rotation if (_isBackgroundThreadCameraRotating) { _backgroundDXEngineRenderer.StartCameraRotation(headingChangeInSecond: 40); } }; }
private void CreateCamera() { _targetPositionCamera = new TargetPositionCamera() { TargetViewport3D = wpfViewport3D, TargetPosition = new Point3D(0, 0.5, 0), Distance = 8, Heading = 30, Attitude = -10, ShowCameraLight = ShowCameraLightType.Never }; // Because this _targetPositionCamera is never added to the UI three, we need to manually call Refresh method _targetPositionCamera.Refresh(); }
private void SphereRadiusComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { if (!this.IsLoaded) { return; } double selectedRadius = (double)SphereRadiusComboBox.SelectedItem; double selectedDepthBias = (double)DepthBiasComboBox.SelectedItem; bool showSphere = ShowSphereRadioButton.IsChecked ?? false; CreateScene(_customViewport3D, selectedRadius, selectedDepthBias, _customCamera, showSphere); // With DXEngine v2.0 and newer we can also change the LineDepthBias DXAttribute after the _shownLineVisual3D was already shown _shownLineVisual3D.SetDXAttribute(DXAttributeType.LineDepthBias, selectedDepthBias); // It would be also possible to set the depth with changing the DepthBias on the WpfWireframeVisual3DNode. // This is done with using the SetDepthBias method //SetDepthBias(_customDXViewportView, _shownLineVisual3D, selectedDepthBias); _customCamera.Refresh(); // This will regenerate the camera light that was removed in the CreateScene: parentViewport3D.Children.Clear(); }
private void RenderOfflineViewportButton_OnClick(object sender, RoutedEventArgs e) { // This method shows how to render a bitmap from a Viewport3D that is not shown in WPF visual tree (offline Viewport3D) // First create a new instance of Viewport3D var viewport3D = new Viewport3D(); // IMPORTANT !!! // You need to specify the size of the Viewport3D (this is needed because projection matrix requires an aspect ratio value). viewport3D.Width = 600; viewport3D.Height = 400; // It is recommended to create the camera before the objects are added to the scene. // This is especially true for 3D lines because this will generate the initial line geometry with the correct camera setting. // If the camera is added later or changed after the 3D lines are added to the scene, you need to manually call Refresh on LinesUpdater to regenerate 3D lines: // Ab3d.Utilities.LinesUpdater.Instance.Refresh(); // // This is not needed when the Viewport3D is shown in WPF visual tree. var targetPositionCamera = new TargetPositionCamera() { Heading = 30, Attitude = -20, Distance = 50, ShowCameraLight = ShowCameraLightType.Always, TargetViewport3D = viewport3D }; // When Viewport3D is not shown, we need to manually refresh the camera to initialize property and add the light to the scene. targetPositionCamera.Refresh(); // Now add 3D objects var boxVisual3D = new Ab3d.Visuals.BoxVisual3D() { CenterPosition = new Point3D(0, 0, 0), Size = new Size3D(8, 8, 8), Material = new DiffuseMaterial(Brushes.Orange), }; viewport3D.Children.Add(boxVisual3D); var wireBoxVisual3D = new Ab3d.Visuals.WireBoxVisual3D() { CenterPosition = new Point3D(0, 0, 0), Size = new Size3D(10, 10, 10), LineColor = Colors.Red, LineThickness = 1 }; viewport3D.Children.Add(wireBoxVisual3D); // If the camera was changed after the 3D lines were added, we need to manually regenerate 3D line geometry by calling Refresh on LinesUpdater: //Ab3d.Utilities.LinesUpdater.Instance.Refresh(); // // This is not needed when the Viewport3D is shown in WPF visual tree. // Now we can render Viewport3D to bitmap // When using Ab3d.DXEngine, then use the DXViewportView.RenderToBitmap method to also render DXEngine's objects // and get support for super-sampling that gets superior image quality. var renderedBitmap = RenderToBitmap(targetPositionCamera); SaveBitmap(renderedBitmap); // To make a simple demonstration on how to create a sequence of bitmaps // with changes the camera and object uncomment the following coed (you can also comment calling the SaveBitmap method in the RenderToBitmap) //for (int i = 1; i < 5; i++) //{ // targetPositionCamera.Heading = i * 20; // boxVisual3D.Transform = new ScaleTransform3D(1, (double)i / 4, 1); // // Now we can render Viewport3D to bitmap // var bitmap = RenderToBitmap(targetPositionCamera); // SaveBitmap(bitmap, $"c:\\temp\\bitmap_{i}.png"); // Change the path to a path that exist on your computer //} }
private void UpdateCamera() { _camera.Heading = HeadingSlider.Value; _camera.Refresh(); }
private void CreateOffline3DScene() { var viewport3D = new Viewport3D(); // IMPORTANT !!! // Because this Viewport3D will not be actually shown, we need to manually set its size // because this is needed for projection matrix. viewport3D.Width = 800; viewport3D.Height = 600; var targetPositionCamera = new TargetPositionCamera() { Heading = 0, Attitude = 0, CameraType = BaseCamera.CameraTypes.OrthographicCamera, CameraWidth = viewport3D.Width, // Use same width as viewport3D so we get 1:1 scale TargetViewport3D = viewport3D }; var polyLineVisual3D = new PolyLineVisual3D() { Positions = new Point3DCollection(new Point3D[] { //new Point3D(-100, 0, -50), //new Point3D(100, 0, -50), //new Point3D(100, 0, 50), //new Point3D(50, 0, 0), //new Point3D(-100, 0, 50), new Point3D(-100, -50, 0), new Point3D(100, -50, 0), new Point3D(100, 50, 0), new Point3D(50, 0, 0), new Point3D(-100, 50, 0), }), LineColor = Colors.Green, LineThickness = 30, // NOTE: // If you require that each line segment uses exactly 4 positions, // then you need to disable turning mitered joints into beveled joints // (beveled joints have 3 additional positions that cut the sharp joint). // It is not possible to know in advance how many bevel joints will be // because this also depends on the angle of the camera. // To disable creating beveled joints set MiterLimit to some high number // (for example the following will create a beveled joint when the joint length is 100 times the line thickness). //MiterLimit = 100 }; viewport3D.Children.Add(polyLineVisual3D); targetPositionCamera.Refresh(); Ab3d.Utilities.LinesUpdater.Instance.Refresh(); // Force regeneration of all 3D lines var geometryModel3D = polyLineVisual3D.Content as GeometryModel3D; if (geometryModel3D != null) { var lineMesh = (MeshGeometry3D)geometryModel3D.Geometry; _shownLineModel3D = new GeometryModel3D(); _shownLineModel3D.Geometry = lineMesh; _shownLineModel3D.Material = new DiffuseMaterial(Brushes.LightGray); _shownLineModel3D.BackMaterial = new DiffuseMaterial(Brushes.Black); if (BillboardCheckbox.IsChecked ?? false) { ApplyBillboardMatrix(); } MainViewport.Children.Add(_shownLineModel3D.CreateContentVisual3D()); MeshInspector.MeshGeometry3D = lineMesh; } }
public Grid CreateScene() { var rootGrid = new Grid(); var textBlock = new TextBlock() { Text = _title, FontSize = 16, FontWeight = FontWeights.Bold, Margin = new Thickness(10, 5, 10, 10), VerticalAlignment = VerticalAlignment.Top, HorizontalAlignment = HorizontalAlignment.Left }; _reportTextBlock = new TextBlock() { Text = "", FontSize = 10, Margin = new Thickness(10, 30, 10, 10), VerticalAlignment = VerticalAlignment.Top, HorizontalAlignment = HorizontalAlignment.Left, TextWrapping = TextWrapping.Wrap }; var rootBorder = new Border() { Background = Brushes.Transparent, BorderBrush = Brushes.Black, BorderThickness = new Thickness(2, 2, 2, 2), Margin = new Thickness(1, 2, 1, 2) }; MainViewport3D = new Viewport3D(); var rootModel3DGroup = Create3DScene(new Point3D(0, -300, 0), XCount, YCount, ZCount, 30); MainCamera = new TargetPositionCamera() { TargetViewport3D = MainViewport3D, TargetPosition = new Point3D(0, 0, 0), Heading = 130, // start from back where sorting errors are most obvious Attitude = -20, Distance = 500, ShowCameraLight = ShowCameraLightType.Always }; MainCamera.CameraChanged += OnMainCameraChanged; var mouseCameraController = new MouseCameraController() { TargetCamera = MainCamera, EventsSourceElement = rootBorder, RotateCameraConditions = MouseCameraController.MouseAndKeyboardConditions.LeftMouseButtonPressed, MoveCameraConditions = MouseCameraController.MouseAndKeyboardConditions.Disabled // disable mouse move }; if (_useDXEngine) { _dxViewportView = new DXViewportView(); _dxViewportView.Viewport3D = MainViewport3D; rootBorder.Child = _dxViewportView; _dxViewportView.DXSceneDeviceCreated += delegate(object sender, EventArgs e) { // Always disable transparency sorting on start // If _useDXEngineSorting the IsTransparencySortingEnabled will be set to true after // the first rendering statistics will be collected (see CollectStatistics method for more info) _dxViewportView.DXScene.IsTransparencySortingEnabled = false; }; _dxViewportView.SceneRendered += delegate(object sender, EventArgs e) { CollectStatistics(); }; // To manually change the order of objects after they have been sorted use SortingCompleted event: //_dxViewportView.DXScene.TransparentRenderingQueue.SortingCompleted += delegate(object sender, RenderingQueueSortingCompletedEventArgs e) //{ // // Here it is possible to change the order of item with changing the indexes in the e.SortedIndexes array. // // IMPORTANT: // // To get objects count use e.RenderablePrimitives.Count and not e.SortedIndexes.Length as it may be too big! //}; Ab3d.DirectX.DXDiagnostics.IsCollectingStatistics = true; } else { rootBorder.Child = MainViewport3D; } if (_useTransparencySorter) { _transparencySorter = new TransparencySorter(rootModel3DGroup, MainCamera); } MainCamera.Refresh(); rootGrid.Children.Add(rootBorder); rootGrid.Children.Add(textBlock); rootGrid.Children.Add(_reportTextBlock); return(rootGrid); }