// This method can be used to change the depth bias value after the Visual3D (line visual or WireframeVisual3D) has already been rendered by DXEngine (or at least the DXEngine has already initialized the 3D SceneNodes).
        // To set initial line depth bias value, it is much easier to use the the following (see also the CreateScene method above):
        // _multiLineVisual3D.SetDXAttribute(DXAttributeType.LineDepthBias, depthBias);
        public static void SetDepthBias(DXViewportView parentDXViewportView, BaseVisual3D lineVisual3D, double depthBiasValue)
        {
            var lineSceneNode = parentDXViewportView.GetSceneNodeForWpfObject(lineVisual3D);

            if (lineSceneNode == null)
            {
                return;
            }


            // First check if we got WpfWireframeVisual3DNode that is created from WireframeVisual3D
            // This is handled differently then LineVisual3D objects because WpfWireframeVisual3DNode defines the DepthBias property
            var wpfWireframeVisual3DNode = lineSceneNode as WpfWireframeVisual3DNode;

            if (wpfWireframeVisual3DNode != null)
            {
                wpfWireframeVisual3DNode.DepthBias = (float)depthBiasValue;
                return;
            }


            // Handle other 3D lines Visual3D objects:

            // To change the DepthBias we need to get to the used LineMaterial
            // LineMaterial is used on the ScreenSpaceLineNode (in the DXEngine's scene nodes hierarchy).
            // Currently the MultiLineVisual3D is converted into WpfModelVisual3DNode with one ScreenSpaceLineNode set as child.
            // But this might be optimized in the future so that WpfModelVisual3DNode would be converted directly into ScreenSpaceLineNode.
            // Thefore here we check both options:

            var screenSpaceLineNode = lineSceneNode as ScreenSpaceLineNode;

            if (screenSpaceLineNode == null && lineSceneNode.ChildNodesCount == 1)
            {
                screenSpaceLineNode = lineSceneNode.ChildNodes[0] as ScreenSpaceLineNode;
            }


            if (screenSpaceLineNode != null)
            {
                // Get line material
                // The LineMaterial is of type ILineMaterial that does not provide setters for properties
                // Therefore we need to cast that into the actual LineMaterial object
                var lineMaterial = screenSpaceLineNode.LineMaterial as LineMaterial;

                if (lineMaterial != null)
                {
                    lineMaterial.DepthBias = (float)depthBiasValue; // Finally we can set DepthBias

                    // When we change properties on the DXEngine objects, we need to manually notify the DXEngine about the changes
                    // We do that with NotifySceneNodeChange method
                    screenSpaceLineNode.NotifySceneNodeChange(SceneNode.SceneNodeDirtyFlags.MaterialChanged);
                }
            }
        }
        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);
        }