Esempio n. 1
0
        private void CreateScene(bool useDXEngineHitTesting)
        {
            ObjectsPlaceholder.Children.Clear();

            if (_dxEventManager3D != null)
            {
                _dxEventManager3D.ResetEventSources3D();
                _dxEventManager3D = null;
            }

            if (_wpfEventManager != null)
            {
                _wpfEventManager.ResetEventSources3D();
                _wpfEventManager = null;
            }

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


            _stopwatch = new Stopwatch();
            _stopwatch.Start();

            Mouse.OverrideCursor = Cursors.Wait;


            // Create InstancedGeometryVisual3D
            _instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(_instanceMeshGeometry3D);

            _instancedMeshGeometryVisual3D.InstancesData = _instancedData;


            // Setup hit testing
            if (useDXEngineHitTesting)
            {
                // Use DXEventManager3D from Ab3d.DXEngine - it has optimized hit testing for instanced objects
                _dxEventManager3D = new Ab3d.DirectX.Utilities.DXEventManager3D(MainDXViewportView);

                var visualEventSource3D = new Ab3d.DirectX.Utilities.VisualEventSource3D(_instancedMeshGeometryVisual3D);
                visualEventSource3D.MouseEnter += delegate(object sender, DirectX.Common.EventManager3D.Mouse3DEventArgs e)
                {
                    var dxRayInstancedHitTestResult = e.RayHitResult as DXRayInstancedHitTestResult;
                    if (dxRayInstancedHitTestResult != null)
                    {
                        ProcessMouseEnter(dxRayInstancedHitTestResult.HitInstanceIndex);
                    }
                };

                visualEventSource3D.MouseMove += delegate(object sender, DirectX.Common.EventManager3D.Mouse3DEventArgs e)
                {
                    var dxRayInstancedHitTestResult = e.RayHitResult as DXRayInstancedHitTestResult;
                    if (dxRayInstancedHitTestResult != null)
                    {
                        ProcessMouseMove(dxRayInstancedHitTestResult.HitInstanceIndex);
                    }
                };

                visualEventSource3D.MouseLeave += delegate(object sender, DirectX.Common.EventManager3D.Mouse3DEventArgs e)
                {
                    ProcessMouseLeave();
                };

                _dxEventManager3D.RegisterEventSource3D(visualEventSource3D);
            }
            else
            {
                //
                // IMPORTANT:
                //
                // To make WPF hit testing work (also used by EventManager3D), you need to set the IsWpfHitTestVisible to true.
                // This increases initialization time because WPF objects needs to be created for each instance, but this makes the WPF hit testing work.
                _instancedMeshGeometryVisual3D.IsWpfHitTestVisible = true;


                _wpfEventManager = new Ab3d.Utilities.EventManager3D(MainViewport);

                // Because Viewport3D is actually not shown, we need to specify different WPF's object for the source of mouse events - this could be MainDXViewportView or even better a parent Border
                _wpfEventManager.CustomEventsSourceElement = MainDXViewportView;

                var visualEventSource3D = new Ab3d.Utilities.VisualEventSource3D(_instancedMeshGeometryVisual3D);
                visualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs e)
                {
                    if (e.RayHitResult == null || e.RayHitResult.ModelHit == null)
                    {
                        return; // This should not happen, but it is safer to have this check anyway
                    }
                    // Get instance index of the hit object
                    int hitInstanceIndex = GetHitInstanceIndex(e.RayHitResult);

                    ProcessMouseEnter(hitInstanceIndex);
                };

                visualEventSource3D.MouseMove += delegate(object sender, Mouse3DEventArgs e)
                {
                    if (e.RayHitResult == null || e.RayHitResult.ModelHit == null)
                    {
                        return; // This should not happen, but it is safer to have this check anyway
                    }
                    // Get instance index of the hit object
                    int hitInstanceIndex = GetHitInstanceIndex(e.RayHitResult);

                    ProcessMouseMove(hitInstanceIndex);
                };

                visualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs e)
                {
                    ProcessMouseLeave();
                };

                _wpfEventManager.RegisterEventSource3D(visualEventSource3D);
            }



            ObjectsPlaceholder.Children.Add(_instancedMeshGeometryVisual3D);

            Mouse.OverrideCursor = null;

            // If we would only change the InstancedData we would need to call Update method (but here this is not needed because we have set the data for the first time)
            //_instancedGeometryVisual3D.Update();
        }
Esempio n. 2
0
        public ModelRotatorSample()
        {
            InitializeComponent();

            _normalMaterial   = new DiffuseMaterial(Brushes.Silver);
            _selectedMaterial = new DiffuseMaterial(new SolidColorBrush(Color.FromArgb(150, 192, 192, 192))); // semi-transparent Silver

            _eventManager = new Ab3d.Utilities.EventManager3D(MainViewport);


            // Setup events on ModelRotatorVisual3D
            SelectedModelRotator.ModelRotateStarted += delegate(object sender, ModelRotatedEventArgs args)
            {
                if (_selectedBoxModel == null)
                {
                    return;
                }

                // When a new rotation is started, we create a new AxisAngleRotation3D with the used Axis or rotation
                // During the rotation we will adjust the angle (inside ModelRotated event handler)
                _axisAngleRotation3D = new AxisAngleRotation3D(args.RotationAxis, 0);

                // Insert the new rotate transform before the last translate transform that positions the box
                var rotateTransform3D = new RotateTransform3D(_axisAngleRotation3D);

                AddTransform(_selectedBoxModel, rotateTransform3D);
            };

            SelectedModelRotator.ModelRotated += delegate(object sender, ModelRotatedEventArgs args)
            {
                if (_selectedBoxModel == null)
                {
                    return;
                }

                _axisAngleRotation3D.Angle = args.RotationAngle;
            };

            SelectedModelRotator.ModelRotateEnded += delegate(object sender, ModelRotatedEventArgs args)
            {
                // Nothing to do here in this sample
                // The event handler is here only for description purposes
            };

            // To create custom circle 3D model, use the CreateCustomCircleModelCallback.
            // The following commented code shows how the default circle 3D model is created
            //SelectedModelRotator.CreateCustomCircleModelCallback = delegate (Vector3D normalVector3D, double innerRadius, double outerRadius, Brush circleBrush)
            //{
            //    int segmentsCount = 30;
            //    double circleHeight = outerRadius * 0.05; // Height is 20 times smaller than outer radius

            //    var tubeMesh3D = new Ab3d.Meshes.TubeMesh3D(new Point3D(0, 0, 0), normalVector3D, outerRadius, innerRadius, circleHeight, segmentsCount);

            //    var geometryModel3D = new GeometryModel3D(tubeMesh3D.Geometry, new DiffuseMaterial(circleBrush));

            //    return geometryModel3D;
            //};


            CreateRandomScene();
        }
Esempio n. 3
0
        private void CreateSceneObjects()
        {
            for (int y = 0; y < 5; y++)
            {
                for (int x = 0; x < 6; x++)
                {
                    var boxVisual3D = new Ab3d.Visuals.BoxVisual3D()
                    {
                        CenterPosition = new Point3D(40 * x - 100, 6, y * 40 - 80),
                        Size           = new Size3D(10, 10, 10),
                        Material       = _standardMaterial
                    };

                    SelectionRootModelVisual3D.Children.Add(boxVisual3D);
                }
            }

            // Use EventManager3D to handle clicking on selected boxes
            var eventManager3D = new Ab3d.Utilities.EventManager3D(MainViewport);

            var multiVisualEventSource3D = new MultiVisualEventSource3D(SelectionRootModelVisual3D.Children);

            multiVisualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs e)
            {
                Mouse.OverrideCursor = Cursors.Hand;

                var hitBoxVisual3D = e.HitObject as Ab3d.Visuals.BoxVisual3D;
                if (hitBoxVisual3D != null)
                {
                    _wireBoxVisual3D.CenterPosition = hitBoxVisual3D.CenterPosition;
                    _wireBoxVisual3D.Size           = hitBoxVisual3D.Size;

                    MainViewport.Children.Add(_wireBoxVisual3D);
                }
            };

            multiVisualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs e)
            {
                Mouse.OverrideCursor = null;

                if (_wireBoxVisual3D != null)
                {
                    MainViewport.Children.Remove(_wireBoxVisual3D);
                }
            };

            multiVisualEventSource3D.MouseClick += delegate(object sender, MouseButton3DEventArgs e)
            {
                if (_selectedBoxVisual3D != null)
                {
                    _selectedBoxVisual3D.Material = _standardMaterial;
                }

                var hitBoxVisual3D = e.HitObject as Ab3d.Visuals.BoxVisual3D;
                if (hitBoxVisual3D != null)
                {
                    hitBoxVisual3D.Material = _selectedMaterial;
                    _selectedBoxVisual3D    = hitBoxVisual3D;

                    if (_wireBoxVisual3D != null)
                    {
                        MainViewport.Children.Remove(_wireBoxVisual3D);
                    }

                    MoveCameraTo(hitBoxVisual3D);
                }
                else
                {
                    _selectedBoxVisual3D = null;
                }
            };

            eventManager3D.RegisterEventSource3D(multiVisualEventSource3D);

            // Exclude _wireBoxVisual3D from receiving mouse events
            eventManager3D.RegisterExcludedVisual3D(_wireBoxVisual3D);
        }
        public void ShowData(List <SphereData> originalData, Rect3D displayedDataBounds, Rect xyDataRange)
        {
            // Now use original data to create our data view objects

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

            _allSpheresData = new List <SphereDataView>(originalData.Count);

            foreach (var originalSphereData in originalData)
            {
                // Set color of the sphere based on its y position
                // We choose the color from the gradient defined in EnsureGradientColorsArray
                double relativeY = (originalSphereData.Location.Y - xyDataRange.Y) / xyDataRange.Height;

                int   colorArrayIndex = (int)(relativeY * (_gradientColorsArray.Length - 1));
                Color color           = _gradientColorsArray[colorArrayIndex];


                var sphereDataView = SphereDataView.Create(originalSphereData, displayedDataBounds, originalData.Count, xyDataRange, color);

                sphereDataView.IsSelectedChanged += delegate(object sender, EventArgs args)
                {
                    var changedPositionDataView = (SphereDataView)sender;
                    if (changedPositionDataView.IsSelected)
                    {
                        DataListBox.SelectedItems.Add(changedPositionDataView);
                    }
                    else
                    {
                        DataListBox.SelectedItems.Remove(changedPositionDataView);
                    }

                    UpdateSelectedSpheresData();
                };

                _allSpheresData.Add(sphereDataView);
            }

            // Bind positions data to ListBox
            DataListBox.ItemsSource = _allSpheresData;


            // Create curve through all positions
            // This is done by first creating all points that define the curve (10 points between each position that define the curve)
            List <Point3D> allPositions = new List <Point3D>();

            foreach (var positionData in _allSpheresData)
            {
                allPositions.Add(positionData.Position);
            }

            BezierCurve       bezierCurve = Ab3d.Utilities.BezierCurve.CreateFromCurvePositions(allPositions);
            Point3DCollection curvePoints = bezierCurve.CreateBezierCurve(positionsPerSegment: 10); // How many points between each defined position in the curve

            // Create 3D Polyline from curvePoints
            Model3D curveModel = Ab3d.Models.Line3DFactory.CreatePolyLine3D(curvePoints, thickness: 2, color: Colors.Blue, isClosed: false, startLineCap: LineCap.Flat, endLineCap: LineCap.Flat, parentViewport3D: MainViewport);

            CurveModelVisual.Content = curveModel;


            // Now create 3D sphere objects for each position
            SpheresModelVisual.Children.Clear();

            // Each sphere will also need MouseEnter, MouseLeave and MouseClick event handlers
            // We use EventManager3D for that
            var eventManager3D = new Ab3d.Utilities.EventManager3D(MainViewport);


            // Add 3D sphere for each position
            foreach (var positionData in _allSpheresData)
            {
                SpheresModelVisual.Children.Add(positionData.ModelVisual3D); // Sphere Visual3D is created in SphereDataView object

                // Add event handlers (sphere Visual3D will be the source of the events)
                var visualEventSource3D = new VisualEventSource3D(positionData.ModelVisual3D);

                visualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs e)
                {
                    if (_isSelecting)
                    {
                        return;
                    }

                    // Use hand cursor
                    Mouse.OverrideCursor = Cursors.Hand;

                    // Find selected position data
                    var selectedPositionData = _allSpheresData.FirstOrDefault(p => p.ModelVisual3D == e.HitObject);

                    SelectData(selectedPositionData, e.CurrentMousePosition);
                };

                visualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs e)
                {
                    if (_isSelecting)
                    {
                        return;
                    }

                    Mouse.OverrideCursor = null;

                    DataToolTipBorder.Visibility  = Visibility.Collapsed;
                    DataToolTipBorder.DataContext = null;

                    SelectedSphereLinesVisual.Children.Clear();
                };

                visualEventSource3D.MouseClick += delegate(object sender, MouseButton3DEventArgs e)
                {
                    // Select / deselect on mouse click
                    var clickedPositionData = _allSpheresData.FirstOrDefault(p => p.ModelVisual3D == e.HitObject);

                    if (clickedPositionData != null)
                    {
                        positionData.IsSelected = !clickedPositionData.IsSelected;
                    }
                };

                // Register the event source
                eventManager3D.RegisterEventSource3D(visualEventSource3D);
            }
        }
        public ModelMoverOverlaySample()
        {
            InitializeComponent();

            // We need to synchronize the Camera and Lights in OverlayViewport with the camera in the MainViewport
            Camera1.CameraChanged += delegate(object s, CameraChangedRoutedEventArgs args)
            {
                OverlayViewport.Camera         = MainViewport.Camera;
                OverlayViewportLight.Direction = ((DirectionalLight)Camera1.CameraLight).Direction;
            };


            // NOTE:
            // To define custom axes directions for ModelMoverVisual3D, define it in code and specify the axes direction it the constructor - for example:
            // ModelMover = new ModelMoverVisual3D(new Vector3D(-1, 0, 0), new Vector3D(0, -1, 0), new Vector3D(0, 0, -1));
            //
            // You can even define angles that are not aligned with coordinate axes:
            // ModelMover = new ModelMoverVisual3D(new Vector3D(-1, -1, 0), new Vector3D(-1, 1, 0), new Vector3D(0, 0, -1));


            // Setup event handlers on ModelMoverVisual3D
            ModelMover.ModelMoveStarted += delegate(object o, EventArgs eventArgs)
            {
                if (_selectedBoxModel == null)
                {
                    return;
                }

                _startMovePosition = _selectedBoxModel.CenterPosition;
            };

            ModelMover.ModelMoved += delegate(object o, Ab3d.Common.ModelMovedEventArgs e)
            {
                if (_selectedBoxModel == null)
                {
                    return;
                }

                var newCenterPosition = _startMovePosition + e.MoveVector3D;

                if (Math.Abs(newCenterPosition.X) > 2000 ||
                    Math.Abs(newCenterPosition.Y) > 2000 ||
                    Math.Abs(newCenterPosition.Z) > 2000)
                {
                    InfoTextBlock.Text = "Move out of range";
                    return;
                }

                _selectedBoxModel.CenterPosition = newCenterPosition;
                ModelMover.Position = GetSelectedModelWorldPosition(); // GetSelectedModelPosition gets the _selectedBoxModel.CenterPosition and transforms it with the transformations of parent ModelVisual3D objects

                InfoTextBlock.Text = string.Format("MoveVector3D: {0:0}", e.MoveVector3D);
            };

            ModelMover.ModelMoveEnded += delegate(object sender, EventArgs args)
            {
                InfoTextBlock.Text = "";
            };


            _normalMaterial = new DiffuseMaterial(Brushes.Silver);
            _eventManager   = new Ab3d.Utilities.EventManager3D(MainViewport);

            CreateRandomScene();
        }
Esempio n. 6
0
        public DucksLakeDemo()
        {
            InitializeComponent();

            MouseCameraControllerInfo1.AddCustomInfoLine(0, MouseCameraController.MouseAndKeyboardConditions.LeftMouseButtonPressed, "Select duck");


            _duckModel3D = LoadDuckModel();

            _eventManager3D = new Ab3d.Utilities.EventManager3D(MainViewport);
            _eventManager3D.CustomEventsSourceElement = ViewportBorder;


            MainDXViewportView.DXSceneInitialized += delegate(object sender, EventArgs args)
            {
                if (MainDXViewportView.DXScene == null)
                {
                    return; // Probably WPF 3D rendering
                }
                // Setup shadow rendering
                _varianceShadowRenderingProvider = new VarianceShadowRenderingProvider();

                // Because we have a big green plane, we need to increase the shadow map size (increase this more to get a more detailed shadow).
                _varianceShadowRenderingProvider.ShadowMapSize = 1024;

                MainDXViewportView.DXScene.InitializeShadowRendering(_varianceShadowRenderingProvider);

                // Specify the light that cases shadow(note that point light is not supported - only DirectionalLight and SpotLight are supported).
                MainSceneLight.SetDXAttribute(DXAttributeType.IsCastingShadow, true);
            };


            this.Focusable       = true; // by default Page is not focusable and therefore does not receive keyDown event
            this.PreviewKeyDown += OnPreviewKeyDown;
            this.Focus();


            // We need to synchronize the Camera in OverlayViewport with the camera in the MainViewport
            Camera1.CameraChanged += delegate(object s, CameraChangedRoutedEventArgs args)
            {
                OverlayViewport.Camera = MainViewport.Camera;
            };

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

                ShowModelMover();
            };

            // IMPORTANT:
            // It is very important to call Dispose method on DXSceneView after the control is not used any more (see help file for more info)
            this.Unloaded += delegate(object sender, RoutedEventArgs args)
            {
                if (_varianceShadowRenderingProvider != null)
                {
                    _varianceShadowRenderingProvider.Dispose();
                }

                MainDXViewportView.Dispose();
            };
        }
Esempio n. 7
0
        private void SubscribeEvents()
        {
            // Create an instance of EventManager3D for out Viewport3D

            // Important:
            // It is highly recommended not to have more than one EventManager3D object per Viewport3D.
            // Having multiple EventManager3D object can greatly reduce the performance because each time the Viewport3D camera is changed,
            // each EventManager3D must perform a full 3D hit testing from the current mouse position.
            // This operation is very CPU intensive and can affect performance when there are many 3D objects in the scene.
            // When multiple EventManager3D object are defined, then the 3D hit testing is performed multiple times.
            // Therefore it is recommended to have only one EventManager3D object per Viewport3D.
            //
            // It is also recommended to remove registered event sources after they are not used any more.
            // This can be done with RemoveEventSource3D method.

            _eventManager = new Ab3d.Utilities.EventManager3D(MainViewport);

            // Create a NamedObjects dictionary and set it to eventManager.
            // This way we can use names on EventSource objects to identify Model3D or Visual3D.
            // This is very usefull if we read the 3d objects with Reader3ds or ReaderObj and already have the NamedObjects dictionry.
            // When names are used in EventSource objects, we get the HitModelName or HitVisualName property set so we can know which object was hit.
            var namedObjects = new Dictionary <string, object>();

            namedObjects.Add("Landscape", _landscapeModel);
            namedObjects.Add("Base", _windGenarator.BaseModel);
            namedObjects.Add("Blades", _windGenarator.BladesModel);
            namedObjects.Add("Turbine", _windGenarator.TurbineModel);

            _eventManager.NamedObjects = namedObjects;



            // subscribe the Landscape as the drag surface
            var modelEventSource = new Ab3d.Utilities.ModelEventSource3D();

            // Instead of using TargetModelName and NamedObjects, we could also specify the model with TargetModel3D
            //modelEventSource.TargetModel3D = _landscapeModel;

            modelEventSource.TargetModelName = "Landscape";
            modelEventSource.IsDragSurface   = true;

            _eventManager.RegisterEventSource3D(modelEventSource);


            // subscribe other objects
            var multiModelEventSource = new Ab3d.Utilities.MultiModelEventSource3D();

            // Instead of using TargetModelNames and NamedObjects, we could specify the models with model instances
            //multiModelEventSource.TargetModels3D = new Model3D[] { _windGenarator.BaseModel,
            //                                                       _windGenarator.BladesModel,
            //                                                       _windGenarator.TurbineModel };

            // Because we have set the NamedObjects dictionary to _eventManager we can simply specify the models by their names:
            multiModelEventSource.TargetModelNames = "Base, Blades, Turbine";
            multiModelEventSource.IsDragSurface    = false;

            // Subscribe to all events
            multiModelEventSource.MouseEnter       += eventSource_MouseEnter;
            multiModelEventSource.MouseLeave       += eventSource_MouseLeave;
            multiModelEventSource.MouseMove        += eventSource_MouseMove;
            multiModelEventSource.MouseUp          += eventSource_MouseUp;
            multiModelEventSource.MouseDown        += eventSource_MouseDown;
            multiModelEventSource.MouseClick       += eventSource_MouseClick;
            multiModelEventSource.MouseWheel       += multiModelEventSource_MouseWheel;
            multiModelEventSource.MouseDoubleClick += eventSource_MouseDoubleClick;
            multiModelEventSource.BeginMouseDrag   += eventSource_BeginMouseDrag;
            multiModelEventSource.MouseDrag        += eventSource_MouseDrag;
            multiModelEventSource.EndMouseDrag     += eventSource_EndMouseDrag;

            multiModelEventSource.TouchEnter += eventSource_TouchEnter;
            multiModelEventSource.TouchDown  += eventSource_TouchDown;
            multiModelEventSource.TouchMove  += eventSource_TouchMove;
            multiModelEventSource.TouchUp    += eventSource_TouchUp;
            multiModelEventSource.TouchLeave += eventSource_TouchLeave;

            // NOTE:
            // It is also possible to subscribe to touch manipulations events (pinch scale and rotate)
            // But this requires to set IsManipulationEnabled to true and that disables some other events
            // See the TouchManipulationsSample for more information

            _eventManager.RegisterEventSource3D(multiModelEventSource);
        }
Esempio n. 8
0
        public ModelMoverOverlaySample()
        {
            InitializeComponent();

            // We need to synchronize the Camera and Lights in OverlayViewport with the camera in the MainViewport
            Camera1.CameraChanged += delegate(object s, CameraChangedRoutedEventArgs args)
            {
                OverlayViewport.Camera         = MainViewport.Camera;
                OverlayViewportLight.Direction = ((DirectionalLight)Camera1.CameraLight).Direction;
            };


            // NOTE:
            // To define custom axes directions for ModelMoverVisual3D, define it in code and specify the axes direction it the constructor - for example:
            // ModelMover = new ModelMoverVisual3D(new Vector3D(-1, 0, 0), new Vector3D(0, -1, 0), new Vector3D(0, 0, -1));
            //
            // You can even define angles that are not aligned with coordinate axes:
            // ModelMover = new ModelMoverVisual3D(new Vector3D(-1, -1, 0), new Vector3D(-1, 1, 0), new Vector3D(0, 0, -1));


            // Setup event handlers on ModelMoverVisual3D
            ModelMover.ModelMoveStarted += delegate(object o, EventArgs eventArgs)
            {
                if (_selectedBoxModel == null)
                {
                    return;
                }

                _startMovePosition = _selectedBoxModel.CenterPosition;
            };

            ModelMover.ModelMoved += delegate(object o, Ab3d.Common.ModelMovedEventArgs e)
            {
                if (_selectedBoxModel == null)
                {
                    return;
                }

                var newCenterPosition = _startMovePosition + e.MoveVector3D;

                if (Math.Abs(newCenterPosition.X) > 2000 ||
                    Math.Abs(newCenterPosition.Y) > 2000 ||
                    Math.Abs(newCenterPosition.Z) > 2000)
                {
                    InfoTextBlock.Text = "Move out of range";
                    return;
                }

                _selectedBoxModel.CenterPosition = newCenterPosition;
                ModelMover.Position = _selectedBoxModel.CenterPosition;

                InfoTextBlock.Text = string.Format("MoveVector3D: {0:0}", e.MoveVector3D);
            };

            ModelMover.ModelMoveEnded += delegate(object sender, EventArgs args)
            {
                InfoTextBlock.Text = "";
            };


            _normalMaterial = new DiffuseMaterial(Brushes.Silver);
            _eventManager   = new Ab3d.Utilities.EventManager3D(MainViewport);

            CreateRandomScene();

            // IMPORTANT:
            // It is very important to call Dispose method on DXSceneView after the control is not used any more (see help file for more info)
            this.Unloaded += (sender, args) => MainDXViewportView.Dispose();
        }
        public void ShowData(List <SphereData> originalData)
        {
            // Now use original data to create our data view objects

            // All data will be displayed in a 3D box defined below:
            var displayedDataBounds = new Rect3D(-40, -20, -40, 80, 40, 80);

            _allPositionsData = new List <SphereDataView>(originalData.Count);

            foreach (var originalSphereData in originalData)
            {
                var sphereDataView = SphereDataView.Create(originalSphereData, displayedDataBounds, originalData.Count, _locationSize, _maxSize);

                sphereDataView.IsSelectedChanged += delegate(object sender, EventArgs args)
                {
                    var changedPositionDataView = (SphereDataView)sender;
                    if (changedPositionDataView.IsSelected)
                    {
                        DataListBox.SelectedItems.Add(changedPositionDataView);
                    }
                    else
                    {
                        DataListBox.SelectedItems.Remove(changedPositionDataView);
                    }

                    UpdateSelectedSpheresData();
                };

                _allPositionsData.Add(sphereDataView);
            }


            // Setup axis limits and shown values
            AxisWireBox.MinYValue = 0;
            AxisWireBox.MaxYValue = 10;

            AxisWireBox.YAxisValues = new double[] { 0, 2, 4, 6, 8, 10 };


            // Bind positions data to ListBox
            DataListBox.ItemsSource = _allPositionsData;


            // Create curve through all positions
            // This is done by first creating all points that define the curve (10 points between each position that define the curve)
            List <Point3D> allPositions = new List <Point3D>();

            foreach (var positionData in _allPositionsData)
            {
                allPositions.Add(positionData.Position);
            }

            BezierCurve       bezierCurve = Ab3d.Utilities.BezierCurve.CreateFromCurvePositions(allPositions);
            Point3DCollection curvePoints = bezierCurve.CreateBezierCurve(positionsPerSegment: 10); // How many points between each defined position in the curve

            // Create 3D Polyline from curvePoints
            Model3D curveModel = Ab3d.Models.Line3DFactory.CreatePolyLine3D(curvePoints, thickness: 2, color: Colors.Blue, isClosed: false, startLineCap: LineCap.Flat, endLineCap: LineCap.Flat, parentViewport3D: MainViewport);

            CurveModelVisual.Content = curveModel;


            // Now create 3D sphere objects for each position
            SpheresModelVisual.Children.Clear();

            // Each sphere will also need MouseEnter, MouseLeave and MouseClick event handlers
            // We use EventManager3D for that
            var eventManager3D = new Ab3d.Utilities.EventManager3D(MainViewport);


            // Add 3D sphere for each position
            foreach (var positionData in _allPositionsData)
            {
                SpheresModelVisual.Children.Add(positionData.ModelVisual3D); // Sphere Visual3D is created in SphereDataView object

                // Add event handlers (sphere Visual3D will be the source of the events)
                var visualEventSource3D = new VisualEventSource3D(positionData.ModelVisual3D);

                visualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs e)
                {
                    if (_isSelecting)
                    {
                        return;
                    }

                    // Use hand cursor
                    Mouse.OverrideCursor = Cursors.Hand;

                    // Find selected position data
                    var selectedPositionData = _allPositionsData.FirstOrDefault(p => p.ModelVisual3D == e.HitObject);

                    SelectData(selectedPositionData, e.CurrentMousePosition);
                };

                visualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs e)
                {
                    if (_isSelecting)
                    {
                        return;
                    }

                    Mouse.OverrideCursor = null;

                    DataToolTipBorder.Visibility  = Visibility.Collapsed;
                    DataToolTipBorder.DataContext = null;

                    SelectedSphereLinesVisual.Children.Clear();
                };

                visualEventSource3D.MouseClick += delegate(object sender, MouseButton3DEventArgs e)
                {
                    // Select / deselect on mouse click
                    var clickedPositionData = _allPositionsData.FirstOrDefault(p => p.ModelVisual3D == e.HitObject);

                    if (clickedPositionData != null)
                    {
                        positionData.IsSelected = !clickedPositionData.IsSelected;
                    }
                };

                // Register the event source
                eventManager3D.RegisterEventSource3D(visualEventSource3D);
            }
        }