private void RecreateTargetModel() { MainViewport.Children.Clear(); Visual3D targetModelVisual3D; // Setup VisualBrush as the material for the model var visualBrush = new VisualBrush(DrawingCanvas); var material = new DiffuseMaterial(visualBrush); if (HeightMapModelTypeRadioButton.IsChecked ?? false) { var heightMapVisual3D = new Ab3d.Visuals.HeightMapVisual3D() { Size = new Size3D(100, 50, 100), IsWireframeShown = false, IsSolidSurfaceShown = true, Material = material, BackMaterial = new DiffuseMaterial(Brushes.DimGray) }; // Create height data from bitmap string heightMapFileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources\\HeightMaps\\simpleHeightMap.png"); BitmapImage heightImage = new BitmapImage(new Uri(heightMapFileName, UriKind.RelativeOrAbsolute)); double[,] heightData = Ab3d.PowerToys.Samples.Objects3D.HeightMapSample.OpenHeightMapDataFile(heightImage, invertData: false); if (heightData != null) { heightMapVisual3D.HeightData = heightData; } targetModelVisual3D = heightMapVisual3D; } else if (BoxModelTypeRadioButton.IsChecked ?? false) { var boxVisual3D = new Ab3d.Visuals.BoxVisual3D() { Size = new Size3D(100, 50, 100), Material = material }; targetModelVisual3D = boxVisual3D; } else //if (SphereModelTypeRadioButton.IsChecked ?? false) { var sphereVisual3D = new Ab3d.Visuals.SphereVisual3D() { Radius = 40, Material = material }; targetModelVisual3D = sphereVisual3D; } MainViewport.Children.Add(targetModelVisual3D); SetupMouseEventHandlers(targetModelVisual3D); }
private void Setup3DObjects() { // The event manager will be used to manage the mouse events on our boxes _eventManager3D = new Ab3d.Utilities.EventManager3D(_viewport3D); // Add a wire grid var wireGridVisual3D = new Ab3d.Visuals.WireGridVisual3D() { Size = new System.Windows.Size(1000, 1000), HeightCellsCount = 10, WidthCellsCount = 10, LineThickness = 3 }; _viewport3D.Children.Add(wireGridVisual3D); // Create 7 x 7 boxes with different height for (int y = -3; y <= 3; y++) { for (int x = -3; x <= 3; x++) { // Height is based on the distance from the center double height = (5 - Math.Sqrt(x * x + y * y)) * 60; // Create the 3D Box visual element var boxVisual3D = new Ab3d.Visuals.BoxVisual3D() { CenterPosition = new Point3D(x * 100, height / 2, y * 100), Size = new Size3D(80, height, 80), Material = _normalMaterial }; _viewport3D.Children.Add(boxVisual3D); // With EventManager we can subscribe to mouse events as we would have standard 2D controls: var visualEventSource3D = new VisualEventSource3D(boxVisual3D); visualEventSource3D.MouseEnter += BoxOnMouseEnter; visualEventSource3D.MouseLeave += BoxOnMouseLeave; visualEventSource3D.MouseClick += BoxOnMouseClick; _eventManager3D.RegisterEventSource3D(visualEventSource3D); } } ToggleCameraAnimation(); // Start camer animation }
private void CreateTestScene() { ContentModelVisual3D.Children.Clear(); ContentModelVisual3D.Content = null; var greenMaterial = new DiffuseMaterial(Brushes.Green); var redMaterial = new DiffuseMaterial(Brushes.Red); _namedObjects = new Dictionary <string, object>(); // Create 7 x 7 boxes with different height for (int y = -3; y <= 3; y++) { for (int x = -3; x <= 3; x++) { // Height is based on the distance from the center double height = (5 - Math.Sqrt(x * x + y * y)) * 60; // Create the 3D Box visual element var boxVisual3D = new Ab3d.Visuals.BoxVisual3D() { CenterPosition = new Point3D(x * 100, height / 2, y * 100), Size = new Size3D(80, height, 80), }; if (height > 200) { boxVisual3D.Material = redMaterial; } else { boxVisual3D.Material = greenMaterial; } // To preserve the object names we can fill the names into the _namedObjects dictionary _namedObjects.Add(string.Format("Box_{0}_{1}", x + 4, y + 4), boxVisual3D); // We could also use the SetName method (extension added by Ab3d.PowerToys) //boxVisual3D.SetName(string.Format("Box_{0}_{1}", x + 4, y + 4)); ContentModelVisual3D.Children.Add(boxVisual3D); } } }
private void CreateSceneObjects() { for (int x = 0; x < 10; x++) { for (int y = 0; y < 4; y++) { var boxVisual3D = new Ab3d.Visuals.BoxVisual3D() { CenterPosition = new Point3D(-100 + 20 * x, 50 + y * 30, 0), Size = new Size3D(10, 10, 10), Material = _standardMaterial }; if (x == 4 && y == 2) { boxVisual3D.Material = _selectedMaterial; _selectedModel = boxVisual3D; } SelectionRootModelVisual3D.Children.Add(boxVisual3D); } } var eventManager3D = new Ab3d.Utilities.EventManager3D(MainViewport); var multiVisualEventSource3D = new MultiVisualEventSource3D(SelectionRootModelVisual3D.Children); multiVisualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs args) { Mouse.OverrideCursor = Cursors.Hand; }; multiVisualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs args) { Mouse.OverrideCursor = null; }; multiVisualEventSource3D.MouseClick += delegate(object sender, MouseButton3DEventArgs e) { if (_selectedModel != null) { _selectedModel.Material = _standardMaterial; } var baseModelVisual3D = e.HitObject as Ab3d.Visuals.BaseModelVisual3D; if (baseModelVisual3D != null) { baseModelVisual3D.Material = _selectedMaterial; _selectedModel = baseModelVisual3D; } else { _selectedModel = null; } string logText = string.Format("Camera1.TurnTo(new Point3D({0:0}, {1:0}, {2:0})", e.FinalPointHit.X, e.FinalPointHit.Y, e.FinalPointHit.Z); if (AnimateCheckBox.IsChecked ?? false) { // Animate the camera turn. Animation duration is 0.5 second and use QuadraticEaseInOutFunction for easing. Camera1.TurnTo(position: e.FinalPointHit, animationDurationInMilliseconds: 500, easingFunction: Ab3d.Animation.EasingFunctions.QuadraticEaseInOutFunction); logText += ", 500, QuadraticEaseInOutFunction)"; } else { Camera1.TurnTo(e.FinalPointHit); // Turn immediately logText += ")"; } LogCommandText(logText); // You can also call this with direction vector - for example: //var directionVector = e.FinalPointHit - Camera1.Position; //Camera1.TurnTo(directionVector); }; eventManager3D.RegisterEventSource3D(multiVisualEventSource3D); }
private void CreateSampleScene() { _physicallyBasedMaterial = new PhysicallyBasedMaterial(); // We need to dispose the PhysicallyBasedMaterial when this sample is uloaded _disposables.Add(_physicallyBasedMaterial); UpdateBaseColor(); UpdateMetalness(); UpdateRoughness(); var normalMapShaderResourceView = GetNormalMapShaderResourceView(); if (normalMapShaderResourceView != null) { _physicallyBasedMaterial.SetTextureMap(TextureMapTypes.NormalMap, normalMapShaderResourceView, "bricks_normal.png"); } var ambientOcclusionShaderResourceView = AmbientOcclusionShaderResourceView(); if (ambientOcclusionShaderResourceView != null) { _physicallyBasedMaterial.SetTextureMap(TextureMapTypes.AmbientOcclusion, ambientOcclusionShaderResourceView, "bricks_ao.png"); } var wpfMaterial = new DiffuseMaterial(Brushes.Red); wpfMaterial.SetUsedDXMaterial(_physicallyBasedMaterial); ModelPlaceholder.Content = null; ModelPlaceholder.Children.Clear(); var sphereVisual3D = new Ab3d.Visuals.SphereVisual3D() { CenterPosition = new Point3D(40, 12, 0), Radius = 12, Segments = 50, Material = wpfMaterial, FreezeMeshGeometry3D = false, UseCachedMeshGeometry3D = false }; ModelPlaceholder.Children.Add(sphereVisual3D); var boxVisual3D = new Ab3d.Visuals.BoxVisual3D() { CenterPosition = new Point3D(-40, 10, 0), Size = new Size3D(20, 20, 20), Material = wpfMaterial, FreezeMeshGeometry3D = false, UseCachedMeshGeometry3D = false }; ModelPlaceholder.Children.Add(boxVisual3D); var readerObj = new Ab3d.ReaderObj(); var readModel3D = (GeometryModel3D)readerObj.ReadModel3D(_modelsFolder + "teapot-hires.obj"); Ab3d.Utilities.ModelUtils.CenterAndScaleModel3D(readModel3D, new Point3D(0, 10, 0), new Size3D(40, 40, 40), true); //// This code is called for each GeometryModel3D inside Plane1 //var tangentVectors = Ab3d.DirectX.Utilities.MeshUtils.CalculateTangentVectors((MeshGeometry3D)readModel3D.Geometry); ////// Assign tangent array to the MeshGeometry3D //readModel3D.Geometry.SetDXAttribute(DXAttributeType.MeshTangentArray, tangentVectors); readModel3D.Material = wpfMaterial; //ModelPlaceholder.Content = null; ModelPlaceholder.Children.Add(readModel3D.CreateModelVisual3D()); // Rendering normal (bump) maps require tangent vectors. // The following code will generate tangent vectors and assign them to the MeshGeometry3D that form our 3D model. // If tangent vectors are not provided, they will be calculated on-demand in the pixel shader (slightly reducing performance). Ab3d.Utilities.ModelIterator.IterateGeometryModel3DObjects(ModelPlaceholder, delegate(GeometryModel3D geometryModel3D, Transform3D transform3D) { // This code is called for each GeometryModel3D inside Plane1 var tangentVectors = Ab3d.DirectX.Utilities.MeshUtils.CalculateTangentVectors((MeshGeometry3D)geometryModel3D.Geometry); // Assign tangent array to the MeshGeometry3D geometryModel3D.Geometry.SetDXAttribute(DXAttributeType.MeshTangentArray, tangentVectors); }); Camera1.Distance = 150; UpdateLights(); }
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 //} }