private void CreateScene(Viewport3D parentViewport3D, double sphereRadius, double depthBias, TargetPositionCamera targetPositionCamera, bool showSphere)
        {
            parentViewport3D.Children.Clear();

            if (showSphere)
            {
                var sphereVisual3D = new Ab3d.Visuals.SphereVisual3D()
                {
                    CenterPosition          = new Point3D(0, 0, 0),
                    Radius                  = sphereRadius,
                    Segments                = 10,
                    Material                = new DiffuseMaterial(Brushes.SkyBlue),
                    UseCachedMeshGeometry3D = false // This will create a new MeshGeometry3D and will not use the shared MeshGeometry3D with radius = 1
                };

                parentViewport3D.Children.Add(sphereVisual3D);


                var sphereMesh = ((GeometryModel3D)sphereVisual3D.Content).Geometry as MeshGeometry3D;

                var sphereLinePositions = CollectWireframeLinePositions(sphereMesh);

                var multiLineVisual3D = new Ab3d.Visuals.MultiLineVisual3D()
                {
                    Positions     = sphereLinePositions,
                    LineThickness = 0.5,
                    LineColor     = Colors.Black
                };

                // To specify line depth bias to the Ab3d.PowerToys line Visual3D objects,
                // we use SetDXAttribute extension method and use LineDepthBias as DXAttributeType
                // NOTE: This can be used only before the Visual3D is created by DXEngine.
                // If you want to change the line bias after the object has been rendered, use the SetDepthBias method (defined below)
                multiLineVisual3D.SetDXAttribute(DXAttributeType.LineDepthBias, depthBias);

                // It would be also possible to set the depth with changing the DepthBias on the WpfWireframeVisual3DNode.
                // This is done with using the SetDepthBias method
                //SetDepthBias(dxViewportView, wireframeVisual3D, depthBias);


                parentViewport3D.Children.Add(multiLineVisual3D);

                _shownLineVisual3D = multiLineVisual3D;
            }
            else
            {
                if (_sampleModel == null)
                {
                    var readerObj = new Ab3d.ReaderObj();
                    _sampleModel = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Models\Teapot.obj"), null, new DiffuseMaterial(Brushes.SkyBlue));

                    _sampleModel.Freeze();
                }

                double readObjectRadius = Math.Sqrt(_sampleModel.Bounds.SizeX * _sampleModel.Bounds.SizeX + _sampleModel.Bounds.SizeZ + _sampleModel.Bounds.SizeZ) / 2;
                double scaleFactor      = sphereRadius / readObjectRadius;

                var finalModel = new Model3DGroup();
                finalModel.Children.Add(_sampleModel);
                finalModel.Transform = new ScaleTransform3D(scaleFactor, scaleFactor, scaleFactor);
                finalModel.Freeze();

                var wireframeVisual3D = new WireframeVisual3D()
                {
                    OriginalModel = finalModel,
                    WireframeType = WireframeVisual3D.WireframeTypes.WireframeWithOriginalSolidModel,
                    UseModelColor = false,
                    LineColor     = Colors.Black,
                    LineThickness = 0.5
                };

                // To specify line depth bias to the WireframeVisual3D,
                // we use SetDXAttribute extension method and use LineDepthBias as DXAttributeType
                wireframeVisual3D.SetDXAttribute(DXAttributeType.LineDepthBias, depthBias);

                // It would be also possible to set the depth with changing the DepthBias on the WpfWireframeVisual3DNode.
                // This is done with using the SetDepthBias method
                //SetDepthBias(dxViewportView, wireframeVisual3D, depthBias);


                parentViewport3D.Children.Add(wireframeVisual3D);

                _shownLineVisual3D = wireframeVisual3D;
            }

            _previousCameraDistance       = sphereRadius * 4;
            targetPositionCamera.Distance = _previousCameraDistance;
            targetPositionCamera.Offset   = new Vector3D(0, sphereRadius * 0.4, 0);
        }
        private void CreateRootModel()
        {
            bool show3DLine = false;

            switch (ObjectComboBox.SelectedIndex)
            {
            case 0:
                Ab3d.Meshes.SphereMesh3D sphere = new Ab3d.Meshes.SphereMesh3D(new Point3D(0, 0, 0), 80, 10);
                _rootMesh = sphere.Geometry;
                break;

            case 1:
                Ab3d.Meshes.SphereMesh3D sphere2 = new Ab3d.Meshes.SphereMesh3D(new Point3D(0, 0, 0), 80, 5);
                _rootMesh = sphere2.Geometry;
                break;

            case 2:
                // NOTE: Here we create an optimized version of sphere but it does not have texture coordinates
                // If we do not need texture coordinates (do not need to show texture), than we can slightly simplify the sphere model.
                // When we also need to create texture coordinates, the top most position that represent the same point in space is defined multiple times
                // - each time with slightly different texture coordinate (so that the whole top line on the texture is shown around the top sphere position).
                // Also there are x + 1 position around the sphere (in one row) - one additional position is added that the first and last position in the "row" are in the same space position,
                // but the first position has x texture coordinate 0, the last position has x texture coordinate 1 - this shows the whole texture nicely around the sphere.
                // If texture coordinates are not needed, than we do not need to define more than one upper and bottom positions,
                // and also do not need to add another position to the row.
                // Optimized sphere can be created only with SphereMesh3D object (not with SphereVisual3D)
                Ab3d.Meshes.SphereMesh3D sphere3 = new Ab3d.Meshes.SphereMesh3D(new Point3D(0, 0, 0), 80, 12, false);     // false: generateTextureCoordinates
                _rootMesh = sphere3.Geometry;
                break;

            case 3:
                Ab3d.Meshes.BoxMesh3D box = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(130, 60, 100), 1, 1, 1);
                _rootMesh = box.Geometry;
                break;

            case 4:
                Ab3d.Meshes.BoxMesh3D box2 = new Ab3d.Meshes.BoxMesh3D(new Point3D(0, 0, 0), new Size3D(130, 60, 100), 4, 4, 4);
                _rootMesh = box2.Geometry;
                break;

            case 5:
                Ab3d.Meshes.CylinderMesh3D cylinder = new Ab3d.Meshes.CylinderMesh3D(new Point3D(0, -50, 0), 60, 100, 12, true);
                _rootMesh = cylinder.Geometry;
                break;

            case 6:
                Ab3d.Meshes.ConeMesh3D cone = new Ab3d.Meshes.ConeMesh3D(new Point3D(0, -50, 0), 30, 60, 100, 12, true);
                _rootMesh = cone.Geometry;
                break;

            case 7:
                Ab3d.Meshes.ConeMesh3D cone2 = new Ab3d.Meshes.ConeMesh3D(new Point3D(0, -50, 0), 30, 60, 100, 6, false);
                _rootMesh = cone2.Geometry;
                break;

            case 8:
                var readerObj   = new Ab3d.ReaderObj();
                var teapotModel = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\ObjFiles\Teapot.obj")) as GeometryModel3D;

                if (teapotModel == null)
                {
                    return;
                }

                // Get the teapot MeshGeometry3D
                _rootMesh = (MeshGeometry3D)teapotModel.Geometry;

                break;

            case 9:
                var line = new Ab3d.Visuals.LineVisual3D()
                {
                    StartPosition = new Point3D(0, 0, 0),
                    EndPosition   = new Point3D(100, 0, 0),
                    LineColor     = Colors.Silver,
                    LineThickness = 20
                };

                Show3DLines(line);
                show3DLine = true;
                break;

            case 10:
                var polyLineVisual3D = new Ab3d.Visuals.PolyLineVisual3D()
                {
                    Positions     = new Point3DCollection(new Point3D[] { new Point3D(-75, 50, 0), new Point3D(-25, 0, 0), new Point3D(25, 50, 0), new Point3D(75, 0, 0) }),
                    LineThickness = 20
                };

                Show3DLines(polyLineVisual3D);
                show3DLine = true;
                break;

            case 11:
                // This is the same line as in the previous sample (PolyLineVisual3D), but this time
                // it is created as diconnected list of lines - note that this requires that the positions are duplicated.
                var multiLineVisual3D = new Ab3d.Visuals.MultiLineVisual3D()
                {
                    Positions = new Point3DCollection(new Point3D[] { new Point3D(-75, 50, 0), new Point3D(-25, 0, 0),
                                                                      new Point3D(-25, 0, 0), new Point3D(25, 50, 0),
                                                                      new Point3D(25, 50, 0), new Point3D(75, 0, 0) }),
                    LineThickness = 20
                };

                Show3DLines(multiLineVisual3D);
                show3DLine = true;
                break;

            default:
                _rootMesh = null;
                break;
            }

            // If we were looking at 3D lines before and now we are looking an standard 3D models,
            // we adjust the camera back to the side view (from direct front view)
            if (_isShowing3DLines && !show3DLine)
            {
                Camera1.Heading  = 30;
                Camera1.Attitude = -20;
                Camera1.Distance = 300;
            }

            _isShowing3DLines = show3DLine;


            _rootModel          = new GeometryModel3D();
            _rootModel.Geometry = _rootMesh;
            _rootModel.Material = new DiffuseMaterial(Brushes.DarkBlue);

            ObjectModelVisual.Content = _rootModel;

            Ab3d.Utilities.ModelEventSource3D modelEventSource = new Ab3d.Utilities.ModelEventSource3D();
            modelEventSource.TargetModel3D = _rootModel;
            modelEventSource.MouseClick   += new Ab3d.Common.EventManager3D.MouseButton3DEventHandler(modelEventSource_MouseClick);

            _eventsManager.ResetEventSources3D();
            _eventsManager.RegisterEventSource3D(modelEventSource);

            MainViewport.Cursor = Cursors.Hand;
        }