public Graph3D()
        {
            InitializeComponent();

            CameraControllerInfo.AddCustomInfoLine(0, Ab3d.Controls.MouseCameraController.MouseAndKeyboardConditions.LeftMouseButtonPressed, "Click to select sphere\r\nDrag for rectangular section");

            _sampleData = InitializeData();
            ShowData(_sampleData);

            // Subscribe mouse events that will be used to create selection rectangle
            ViewportBorder.MouseLeftButtonDown += SelectionOverlayCanvasOnMouseLeftButtonDown;
            ViewportBorder.MouseMove           += SelectionOverlayCanvasOnMouseMove;
            ViewportBorder.MouseLeftButtonUp   += SelectionOverlayCanvasOnMouseLeftButtonUp;
        }
        public Graph3D()
        {
            InitializeComponent();

            CameraControllerInfo.AddCustomInfoLine(0, Ab3d.Controls.MouseCameraController.MouseAndKeyboardConditions.LeftMouseButtonPressed, "Click to select sphere\r\nDrag for rectangular section");


            var linearGradientBrush = CreateGradientBrush();

            _gradientColorsArray = HeightMapMesh3D.GetGradientColorsArray(linearGradientBrush, 30);

            LegendRectangle.Fill = linearGradientBrush;


            _xyDataRange = new Rect(-10, -10, 20, 20);
            _sampleData  = GenerateRandomData(_xyDataRange, relativeMargin: 0.2, dataCount: 20);


            // Setup axis limits and shown values
            AxesBox.SetAxisDataRange(AxesBoxVisual3D.AxisTypes.XAxis, minimumValue: 0, maximumValue: _sampleData.Count, majorTicksStep: 2, minorTicksStep: 0, snapMaximumValueToMajorTicks: true);
            AxesBox.SetAxisDataRange(AxesBoxVisual3D.AxisTypes.YAxis, minimumValue: _xyDataRange.Y, maximumValue: _xyDataRange.Y + _xyDataRange.Height, majorTicksStep: 5, minorTicksStep: 2.5, snapMaximumValueToMajorTicks: true);
            AxesBox.SetAxisDataRange(AxesBoxVisual3D.AxisTypes.ZAxis, minimumValue: _xyDataRange.X, maximumValue: _xyDataRange.X + _xyDataRange.Width, majorTicksStep: 5, minorTicksStep: 2.5, snapMaximumValueToMajorTicks: true);


            // All data will be displayed in a 3D box defined below:
            var displayedDataBounds = new Rect3D(AxesBox.CenterPosition.X - AxesBox.Size.X * 0.5,
                                                 AxesBox.CenterPosition.Y - AxesBox.Size.Y * 0.5,
                                                 AxesBox.CenterPosition.Z - AxesBox.Size.Z * 0.5,
                                                 AxesBox.Size.X,
                                                 AxesBox.Size.Y,
                                                 AxesBox.Size.Z);

            ShowData(_sampleData, displayedDataBounds, _xyDataRange);

            UpdateSelectedSpheresData();

            MinValueTextBlock.Text = string.Format("{0:0}", _xyDataRange.Y);
            MaxValueTextBlock.Text = string.Format("{0:0}", _xyDataRange.Y + _xyDataRange.Height);

            // Subscribe mouse events that will be used to create selection rectangle
            ViewportBorder.MouseLeftButtonDown += SelectionOverlayCanvasOnMouseLeftButtonDown;
            ViewportBorder.MouseMove           += SelectionOverlayCanvasOnMouseMove;
            ViewportBorder.MouseLeftButtonUp   += SelectionOverlayCanvasOnMouseLeftButtonUp;
        }
        private void ShowCustomInfoButtonOnClick(object sender, RoutedEventArgs e)
        {
            if (_isCustomInfoShown)
            {
                // ClearCustomInfoLines method removes all custom info
                CameraControllerInfo.ClearCustomInfoLines();

                ShowCustomInfoButton.Content = "Show custom info";
                _isCustomInfoShown           = false;
            }
            else
            {
                // AddCustomInfoLine method adds custom message with keyboard and mouse button icon to the existing mouse controller info.
                // The first parameter (insertRowIndex) specifies the index of the inserted row at the time of insertion
                // In our example we are inserting two texts both time to index = 0
                // This means that the first line will be inserted first and then the second line will be inserted at position 0 (so the first line will become second)
                CameraControllerInfo.AddCustomInfoLine(0, Ab3d.Controls.MouseCameraController.MouseAndKeyboardConditions.MiddleMouseButtonPressed, "Custom info text 2");
                CameraControllerInfo.AddCustomInfoLine(0, Ab3d.Controls.MouseCameraController.MouseAndKeyboardConditions.ShiftKey | Ab3d.Controls.MouseCameraController.MouseAndKeyboardConditions.LeftMouseButtonPressed, "Custom info text 1");

                ShowCustomInfoButton.Content = "Hide custom info";
                _isCustomInfoShown           = true;
            }
        }
        public HeatmapRenderingSample()
        {
            InitializeComponent();

            // 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();
                }
            };


            this.Loaded += delegate(object sender, RoutedEventArgs args)
            {
                LoadTestModel();

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

            // Cleanup
            this.Unloaded += delegate(object sender, RoutedEventArgs args)
            {
                CompositionTarget.Rendering -= CompositionTargetOnRendering;
            };
        }
        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();
            };
        }