private void AddTestModel()
        {
            var boxMesh3D = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(1, 1, 1), 1, 1, 1).Geometry;

            int positionsCount = boxMesh3D.Positions.Count;
            var bounds         = boxMesh3D.Bounds;

            // Create positionColorsArray that will define colors for each position
            var positionColorsArray = new Color4[positionsCount];

            for (int i = 0; i < positionsCount; i++)
            {
                var position = boxMesh3D.Positions[i];

                // Get colors based on the relative position inside the Bounds - in range from (0, 0, 0) to (1, 1, 1)
                float red   = (float)((position.X - bounds.X) / bounds.SizeX);
                float green = (float)((position.Y - bounds.Y) / bounds.SizeY);
                float blue  = (float)((position.Z - bounds.Z) / bounds.SizeZ);

                // Set Color this position
                positionColorsArray[i] = new Color4(red, green, blue, alpha: 1.0f);
            }


            // Now create the VertexColorMaterial that will be used instead of standard material
            // and will make the model render with special effect where each vertex can have its own color.
            _vertexColorMaterial = new VertexColorMaterial()
            {
                PositionColors = positionColorsArray, // The PositionColors property is used to specify colors for each vertex

                // To show specular effect set the specular data here:
                //SpecularPower = 16,
                //SpecularColor = Color3.White,
                //HasSpecularColor = true

                // If we would update the positionColorsArray very often, then set CreateDynamicBuffer to true
                //CreateDynamicBuffer = true,
            };


            // Create standard WPF material and set the _vertexColorMaterial to be used when the model is rendered in DXEngine.
            var vertexColorDiffuseMaterial = new DiffuseMaterial();

            vertexColorDiffuseMaterial.SetUsedDXMaterial(_vertexColorMaterial);


            // Create a GeometryModel3D that will be rendered with _vertexColorMaterial
            var vertexColorGeometryModel3D = new GeometryModel3D(boxMesh3D, vertexColorDiffuseMaterial);

            vertexColorGeometryModel3D.Transform = new ScaleTransform3D(100, 50, 80); // Scale the box

            var vertexColorModelVisual3D = new ModelVisual3D()
            {
                Content = vertexColorGeometryModel3D
            };

            MainViewport.Children.Add(vertexColorModelVisual3D);
        }
        public VertexColorRenderingSample()
        {
            InitializeComponent();

            AddTestModel();

            Camera1.StartRotation(45, 0);


            // Cleanup
            this.Unloaded += delegate(object sender, RoutedEventArgs args)
            {
                // We need to dispose all DXEngine objects that are created here - in this case _vertexColorMaterial
                if (_vertexColorMaterial != null)
                {
                    _vertexColorMaterial.Dispose();
                    _vertexColorMaterial = null;
                }

                MainDXViewportView.Dispose();
            };
        }
        public VertexColorRenderingSample()
        {
            InitializeComponent();

            CreateGradientColorsArray();

            // Use CameraControllerInfo to show that we can use left mouse button to set custom beam destination on the 3D model
            CameraControllerInfo.AddCustomInfoLine(0, MouseCameraController.MouseAndKeyboardConditions.LeftMouseButtonPressed, "SET BEAM DESTINATION");

            // When the ViewportBorder size is change the size of the overlay Canvas (drawn over the 3D scene)
            ViewportBorder.SizeChanged += delegate(object sender, SizeChangedEventArgs args)
            {
                UpdateOverlayCanvasSize();
            };


            // Process mouse events
            ViewportBorder.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e)
            {
                // Start user beam control
                _isUserBeamControl = true;

                ViewportBorder.CaptureMouse();

                var position = e.GetPosition(ViewportBorder);
                ProcessMouseHit(position);
            };

            ViewportBorder.MouseLeftButtonUp += delegate(object sender, MouseButtonEventArgs e)
            {
                // Stop user beam control
                _isUserBeamControl = false;
                ViewportBorder.ReleaseMouseCapture();

                ProcessMouseOutOfModel();
            };

            // Subscribe to MouseMove to allow user to specify the beam target
            ViewportBorder.MouseMove += delegate(object sender, MouseEventArgs e)
            {
                if (_isUserBeamControl)
                {
                    ProcessMouseHit(e.GetPosition(ViewportBorder));
                }
                else
                {
                    ProcessMouseOutOfModel();
                }
            };


            // Start animating the beam position
            CompositionTarget.Rendering += CompositionTargetOnRendering;


            // We add test models after the DXScene is initialized (this is required because specifal effects require DirectX device)
            MainDXViewportView.DXSceneInitialized += delegate(object sender, EventArgs e)
            {
                if (MainDXViewportView.DXScene == null)
                {
                    return; // Probably WPF 3D rendering
                }
                // Get _vertexColorEffect that will be used to render model with vertex colors (note that this field must be disposed when it is not used any more - here in Unloaded event handler)

                AddTestModels();
            };

            // Cleanup
            this.Unloaded += delegate(object sender, RoutedEventArgs args)
            {
                CompositionTarget.Rendering -= CompositionTargetOnRendering;

                if (_vertexColorMaterial != null)
                {
                    _vertexColorMaterial.Dispose();
                    _vertexColorMaterial = null;
                }

                if (_lineMaterial != null)
                {
                    _lineMaterial.Dispose();
                    _lineMaterial = null;
                }

                MainDXViewportView.Dispose();
            };
        }
        private void CreateLandscape(int gridSize, float noise, int randomSeed = 0) // is randomSeed is 0 or less, then random seed is used
        {
            _lastUsedGridSize = gridSize;

            // Generate height data with using DiamondSquare algorithm
            float[,] floatHeightData = DiamondSquareGrid(gridSize, seed: randomSeed, rMin: 0, rMax: 1, noise: noise);

            // To show height map we will use HeightMapMesh3D from Ab3d.PowerToys library
            // This class requires data in array of doubles.
            // NOTE: In the future version of DXEngine there will be an optimized version of HeightMesh that will take floats

            _heightData = new double[gridSize, gridSize];

            for (int rowIndex = 0; rowIndex < gridSize; rowIndex++)
            {
                for (int columnIndex = 0; columnIndex < gridSize; columnIndex++)
                {
                    _heightData[rowIndex, columnIndex] = (double)floatHeightData[rowIndex, columnIndex];
                }
            }


            // We can use HeightMapMesh3D object from Ab3d.PowerToys library to create a MeshGeometry3D object from 2D array
            // We create Mesh with size 1 x 1 x 1
            // This will allow us to scale it later to any size with ScaleTransform3D
            _heightMapMesh3D = new Meshes.HeightMapMesh3D(new Point3D(0, 0, 0), new Size3D(1, 1, 1), _heightData).Geometry;


            var vertexColorDiffuseMaterial = new DiffuseMaterial();

            int positionsCount = _heightMapMesh3D.Positions.Count;


            // Create vertexColorsArray
            var vertexColorsArray = new Color4[positionsCount];

            // Fill the vertexColorsArray with color values based on the data from _heightData
            CalculateVertexColors(_heightData, vertexColorsArray);

            // To show per-vertex color, we need to use a special VertexColorMaterial
            // Reuse VertexColorMaterial if possible.

            // Dispose old VertexColorMaterial and create a new one
            if (_vertexColorMaterial != null)
            {
                _vertexColorMaterial.Dispose();
            }

            _vertexColorMaterial = new VertexColorMaterial()
            {
                PositionColors = vertexColorsArray
            };

            // This material needs to be set to the WPF vertexColorDiffuseMaterial as UsedDXMaterial.
            // This means that when DXEngine will need to show WPF vertexColorDiffuseMaterial, it will use the vertexColorMaterial.
            vertexColorDiffuseMaterial.SetUsedDXMaterial(_vertexColorMaterial);


            // Now create GeometryModel3D and ModelVisual3D
            var vertexColorGeometryModel3D = new GeometryModel3D(_heightMapMesh3D, vertexColorDiffuseMaterial);

            vertexColorGeometryModel3D.Transform = new ScaleTransform3D(200, 200, 200);

            // To make the landscape colors visible from front and also back side, uncomment the line below (and comment the GeometryModel3D generation a few lines below):
            //vertexColorGeometryModel3D.BackMaterial = vertexColorDiffuseMaterial;

            var vertexColorModelVisual3D = new ModelVisual3D()
            {
                Content = vertexColorGeometryModel3D
            };

            MainViewport.Children.Add(vertexColorModelVisual3D);


            // Add a new GeometryModel3D with the same _heightMapMesh3D
            // But this time render only back faces with gray material
            var backGeometryModel3D = new GeometryModel3D
            {
                Geometry     = vertexColorGeometryModel3D.Geometry,  // Same geometry as vertexColorGeometryModel3D
                Material     = null,                                 // Do not render front-faced triangles
                BackMaterial = new DiffuseMaterial(Brushes.DimGray), // Render only back faces
                Transform    = vertexColorGeometryModel3D.Transform  // Same scale transform as vertexColorGeometryModel3D
            };

            var backModelVisual3D = new ModelVisual3D()
            {
                Content = backGeometryModel3D
            };

            MainViewport.Children.Add(backModelVisual3D);


            // Refresh the camera in case we have removed the camera's light with MainViewport.Children.Clear();
            Camera1.Refresh();
        }
        private void AddTestModels()
        {
            // Load teapot model from obj file
            var readerObj       = new ReaderObj();
            var geometryModel3D = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Models\teapot.obj")) as GeometryModel3D;

            if (geometryModel3D == null)
            {
                return;
            }

            _objectGeometry3D = (MeshGeometry3D)geometryModel3D.Geometry;



            int positionsCount = _objectGeometry3D.Positions.Count;

            // Create and fill the _positionColorsArray with the last color (light blue)
            _positionColorsArray = new Color4[positionsCount];

            var lastColor = _gradientColor4Array[_gradientColor4Array.Length - 1];

            FillPositionColorsArray(lastColor);

            // Now create the VertexColorMaterial that will be used instead of standard material
            // and will make the model render with special effect where each vertex can have its own color.
            _vertexColorMaterial = new VertexColorMaterial()
            {
                PositionColors      = _positionColorsArray, // The PositionColors property is used to specify colors for each vertex
                CreateDynamicBuffer = true,                 // Because we will update the _positionColorsArray on each frame, it is better to create a dynamic DirectX buffer

                // To show specular effect set the specular data here:
                //SpecularPower = 16,
                //SpecularColor = Color3.White,
                //HasSpecularColor = true
            };

            // Create standard WPF material and set the _vertexColorMaterial to be used when the model is rendered in DXEngine.
            var vertexColorDiffuseMaterial = new DiffuseMaterial();

            vertexColorDiffuseMaterial.SetUsedDXMaterial(_vertexColorMaterial);


            // Create a GeometryModel3D that will be rendered with _vertexColorMaterial
            _vertexColorGeometryModel3D = new GeometryModel3D(_objectGeometry3D, vertexColorDiffuseMaterial);

            var vertexColorModelVisual3D = new ModelVisual3D()
            {
                Content = _vertexColorGeometryModel3D
            };

            MainViewport.Children.Add(vertexColorModelVisual3D);



            // Show the same MeshGeometry3D but this time with wireframe material
            var wireframeWpfMaterial = new DiffuseMaterial();

            _lineMaterial = new LineMaterial()
            {
                LineThickness = 1,
                LineColor     = Color4.Black,
                DepthBias     = 0.1f,
            };

            wireframeWpfMaterial.SetUsedDXMaterial(_lineMaterial);


            var wireframeGeometryModel3D = new GeometryModel3D(_objectGeometry3D, wireframeWpfMaterial);

            var wireframeModelVisual3D = new ModelVisual3D()
            {
                Content = wireframeGeometryModel3D
            };

            MainViewport.Children.Add(wireframeModelVisual3D);
        }