//private void GenerateHeightMapObject(float[,] heightData, Color4[] positionColorsArray) private void GenerateHeightMapSceneNodes(MeshBase heightMapMesh, Ab3d.DirectX.Material dxMaterial) { var meshObjectNode = new Ab3d.DirectX.MeshObjectNode(heightMapMesh, dxMaterial); meshObjectNode.Name = "HeightMeshObjectNode"; _disposables.Add(meshObjectNode); var sceneNodeVisual3D = new SceneNodeVisual3D(meshObjectNode); RootContentVisual3D.Children.Add(sceneNodeVisual3D); // If you also want to render back faces of the height map you need to create another MeshObjectNode and set its IsBackFaceMaterial to true. // You can reuse the mesh. But this still requires almost twice the GPU power. var backDiffuseMaterial = new DiffuseMaterial(Brushes.Gray); var backDXMaterial = new Ab3d.DirectX.Materials.WpfMaterial(backDiffuseMaterial); meshObjectNode = new Ab3d.DirectX.MeshObjectNode(heightMapMesh, backDXMaterial); meshObjectNode.IsBackFaceMaterial = true; meshObjectNode.Name = "HeightBackMeshObjectNode"; _disposables.Add(meshObjectNode); sceneNodeVisual3D = new SceneNodeVisual3D(meshObjectNode); RootContentVisual3D.Children.Add(sceneNodeVisual3D); }
private Ab3d.DirectX.Material GeneratePositionColorMaterial(Color4[] positionColorsArray, DXDevice dxDevice) { Ab3d.DirectX.Material dxMaterial; if (positionColorsArray != null) { dxMaterial = new Ab3d.DirectX.Materials.VertexColorMaterial() { PositionColors = positionColorsArray, // The PositionColors property is used to specify colors for each vertex CreateDynamicBuffer = false, // We will not update the colors frequently // To show specular effect set the specular data here: //SpecularPower = 16, //SpecularColor = Color3.White, //HasSpecularColor = true }; } else { // Solid color material: var diffuseMaterial = new DiffuseMaterial(Brushes.Green); // Texture material: //var imageBrush = new ImageBrush(); //imageBrush.ImageSource = new BitmapImage(new Uri("pack://application:,,,/Resources/GrassTexture.jpg")); //var diffuseMaterial = new DiffuseMaterial(imageBrush); dxMaterial = new Ab3d.DirectX.Materials.WpfMaterial(diffuseMaterial); } // If DXDevice is already initialized, then we can also initialize (create DirectX resources) for the SimpleMesh. // This will create the DirectX resources and send them to the GPU if (dxDevice != null) { dxMaterial.InitializeResources(dxDevice); } return(dxMaterial); }
private void AddSimpleMesh() { // To show _meshGeometry3D with using low level DXEngine object we will do the following: // 1) Create a array of PositionNormalTexture data - this will represent a managed vertex buffer array. // 2) Create a SimpleMesh<PositionNormalTexture> object that will create an unmanaged vertex buffer from managed vertex buffer. // 3) Create a MeshObjectNode (derived from SceneNode) from the SimpleMesh. // 4) Create a SceneNodeVisual3D that will allow us to add the MeshObjectNode to the Viewport3D children. // 1) Create a array of PositionNormalTexture data - this will represent a managed vertex buffer array. int positionsCount = _meshGeometry3D.Positions.Count; _vertexBufferArray = new PositionNormalTexture[positionsCount]; FillVertexBuffer(_vertexBufferArray, _meshGeometry3D.Positions, _meshGeometry3D.Normals, _meshGeometry3D.TextureCoordinates); var indexBuffer = new int[_meshGeometry3D.TriangleIndices.Count]; _meshGeometry3D.TriangleIndices.CopyTo(indexBuffer, 0); // 2) Create a SimpleMesh<PositionNormalTexture> object that will create an unmanaged vertex buffer from managed vertex buffer. bool createDynamicVertexBuffer = UseDynamicBufferCheckBox.IsChecked ?? false; _simpleMesh = new SimpleMesh <PositionNormalTexture>(_vertexBufferArray, indexBuffer, inputLayoutType: InputLayoutType.Position | InputLayoutType.Normal | InputLayoutType.TextureCoordinate, name: "SimpleMesh-from-PositionNormalTexture-array", createDynamicVertexBuffer: createDynamicVertexBuffer); // We can also manually specify the bounds of the mesh // If this is not done, then the SimpleMesh will go through all positions and calculate that. // But because the bounds are already calculated by MeshGeometry3D, we can just use that value (we only need to convert that to DXEngine's bounds). _simpleMesh.Bounds = _meshGeometry3D.Bounds.ToDXEngineBounds(); _originalMeshSizeY = _simpleMesh.Bounds.BoundingBox.Maximum.Y - _simpleMesh.Bounds.BoundingBox.Minimum.Y; _disposables.Add(_simpleMesh); var diffuseMaterial = new DiffuseMaterial(Brushes.Silver); var dxMaterial = new Ab3d.DirectX.Materials.WpfMaterial(diffuseMaterial); _disposables.Add(dxMaterial); // 3) Create a MeshObjectNode (derived from SceneNode) from the SimpleMesh. _meshObjectNode = new Ab3d.DirectX.MeshObjectNode(_simpleMesh, dxMaterial); _meshObjectNode.Name = "MeshObjectNode-from-SimpleMesh"; _disposables.Add(_meshObjectNode); // 4) Create a SceneNodeVisual3D that will allow us to add the MeshObjectNode to the Viewport3D children. var sceneNodeVisual3D = new SceneNodeVisual3D(_meshObjectNode); // Scale and translate the sceneNodeVisual3D and than add it to the scene AddVisual3D(sceneNodeVisual3D); }
private void UpdateFogUsage() { if (MainDXViewportView.DXScene == null) // probably WPF 3D rendering is used { return; } // First make sure that we have the StandardEffect that is used by default if (_defaultStandardEffect == null) { _defaultStandardEffect = MainDXViewportView.DXScene.DXDevice.EffectsManager.GetStandardEffect(); } // First reset the changes of previously changed SceneNodes if (_changedDXMaterial != null) { _changedDXMaterial.Effect = null; _changedDXMaterial = null; } if (_yellowFogWpfMaterial != null) { // Replace _yellowFogWpfMaterial with default YellowMaterial var yellowMaterial = this.FindResource("YellowMaterial") as DiffuseMaterial; foreach (var baseModelVisual3D in MainViewport.Children.OfType <BaseModelVisual3D>()) { if (ReferenceEquals(baseModelVisual3D.Material, _yellowFogWpfMaterial)) { baseModelVisual3D.Material = yellowMaterial; } } _yellowFogWpfMaterial = null; } // NOTES: // We can use two ways to use custom FogEffect: // // 1) Set FogEffect as StandardEffect on EffectsManager. // StandardEffect is used when DXEngine is rendering standard WPF materials (diffuse, specular, emissive). // This means that if we change the StandardEffect, then all standard objects will be rendered with FogEffect. // Other objects like 3D lines will still be rendered with their special effects. // // 2) Set FogEffect to the Effect property on the WpfMaterial object that is a DXEngine's material object created from WPF's material. // When setting Effect property on DXEngine's material, the material will be rendered with the specified effect (instead of StandardEffect). // Additional notes: // 1) EffectsManager is created when the DXDevice is created. // This means that you cannot access it in the constructor of this class. // If you need to change the StandardEffect (or some other setting on DXDevice) before the first frame is rendered, // you need to use DXSceneDeviceCreated or DXSceneInitialized event handler to do that (as in this case). Effect newStandardEffect; if (StandardEffectRadioButton.IsChecked ?? false) { newStandardEffect = _fogEffect; } else if (RootBoxRadioButton.IsChecked ?? false) { newStandardEffect = _defaultStandardEffect; // Get the DXEngine's material that is created from the WPF's Material used for BaseBoxVisual3D var dxMaterial = Ab3d.DirectX.Materials.WpfMaterial.GetUsedDXMaterial(BaseBoxVisual3D.Material, MainDXViewportView.DXScene.DXDevice); if (dxMaterial != null) { // Now we can specify the exact effect that will be used to render dxMaterial (if this is not specified, then StandardEffect is used) dxMaterial.Effect = _fogEffect; _changedDXMaterial = dxMaterial; } } else if (ReplaceRadioButton.IsChecked ?? false) { newStandardEffect = _defaultStandardEffect; // Create a clone of YellowMaterial var yellowMaterial = this.FindResource("YellowMaterial") as DiffuseMaterial; if (yellowMaterial != null) { _yellowFogWpfMaterial = yellowMaterial.Clone(); // Now create a DXEngine's material that is created from WPF's material: var yellowFogDXEngineMaterial = new Ab3d.DirectX.Materials.WpfMaterial(_yellowFogWpfMaterial); // Specify the exact effect that will be used to render this material (if not specified, then the StandardEffect is used) yellowFogDXEngineMaterial.Effect = _fogEffect; // Now that we have both WPF material and DXEngine's material, // we can specify that whenever the _yellowFogWpfMaterial will be used (and when our DXDevice is used), // we should use the specified yellowFogDXEngineMaterial. // This is done with the static SetUsedDXMaterial method. // // TIP: The same approach can be used to use some other rendering technique to render on material - for example to use ModelColorLineEffect, ThickLineEffect or SolidColorEffect. Ab3d.DirectX.Materials.WpfMaterial.SetUsedDXMaterial(_yellowFogWpfMaterial, yellowFogDXEngineMaterial); // NOTE: // Instead of calling SetUsedDXMaterial, we could also specify the DXDevice in the WpfMaterial constructor. // This would call the SetUsedDXMaterial behind the scenes. But we did it here in the long way to better demonstrate what is going on. // The following code would call SetUsedDXMaterial in the constructor: // var yellowFogDXEngineMaterial = new Ab3d.DirectX.Materials.WpfMaterial(_yellowFogWpfMaterial, MainDXViewportView.DXScene.DXDevice); // After the _yellowFogWpfMaterial is "connected" to the yellowFogDXEngineMaterial, we can assign it insetad of yellow material: foreach (var baseModelVisual3D in MainViewport.Children.OfType <BaseModelVisual3D>()) { if (ReferenceEquals(baseModelVisual3D.Material, yellowMaterial)) { baseModelVisual3D.Material = _yellowFogWpfMaterial; } } } } else { newStandardEffect = _defaultStandardEffect; } MainDXViewportView.DXScene.DXDevice.EffectsManager.SetStandardEffect(newStandardEffect); }
private void GenerateHeightMapObject(float[,] heightData, Color4[] positionColorsArray) { PositionNormalTexture[] vertexBuffer; int[] indexBuffer; CreateHeightVertexAndIndexBuffer(heightData, centerPosition: new Vector3(0, 0, 0), size: new Vector3(1000, 20, 200), vertexBuffer: out vertexBuffer, indexBuffer: out indexBuffer); var simpleMesh = new SimpleMesh <PositionNormalTexture>(vertexBuffer, indexBuffer, inputLayoutType: InputLayoutType.Position | InputLayoutType.Normal | InputLayoutType.TextureCoordinate, name: "HeightSimpleMesh"); _disposables.Add(simpleMesh); Ab3d.DirectX.Material dxMaterial; if (positionColorsArray != null) { dxMaterial = new Ab3d.DirectX.Materials.VertexColorMaterial() { PositionColors = positionColorsArray, // The PositionColors property is used to specify colors for each vertex CreateDynamicBuffer = false, // We will not update the colors frequently // To show specular effect set the specular data here: //SpecularPower = 16, //SpecularColor = Color3.White, //HasSpecularColor = true }; } else { // Solid color material: var diffuseMaterial = new DiffuseMaterial(Brushes.Green); // Texture material: //var imageBrush = new ImageBrush(); //imageBrush.ImageSource = new BitmapImage(new Uri("pack://application:,,,/Resources/GrassTexture.jpg")); //var diffuseMaterial = new DiffuseMaterial(imageBrush); dxMaterial = new Ab3d.DirectX.Materials.WpfMaterial(diffuseMaterial); } _disposables.Add(dxMaterial); var meshObjectNode = new Ab3d.DirectX.MeshObjectNode(simpleMesh, dxMaterial); meshObjectNode.Name = "HeightMeshObjectNode"; _disposables.Add(meshObjectNode); var sceneNodeVisual3D = new SceneNodeVisual3D(meshObjectNode); MainViewport.Children.Add(sceneNodeVisual3D); // If you also want to render back faces of the height map you need to create another MeshObjectNode and set its IsBackFaceMaterial to true. // You can reuse the mesh. But this still requires almost twice the GPU power. var backDiffuseMaterial = new DiffuseMaterial(Brushes.Gray); var backDXMaterial = new Ab3d.DirectX.Materials.WpfMaterial(backDiffuseMaterial); meshObjectNode = new Ab3d.DirectX.MeshObjectNode(simpleMesh, backDXMaterial); meshObjectNode.IsBackFaceMaterial = true; meshObjectNode.Name = "HeightBackMeshObjectNode"; _disposables.Add(meshObjectNode); sceneNodeVisual3D = new SceneNodeVisual3D(meshObjectNode); MainViewport.Children.Add(sceneNodeVisual3D); }