Ejemplo n.º 1
0
        private GeometryModel3D AddMeshNormalMaterialModel(MeshGeometry3D mesh, Point3D position, Color3 colorMask)
        {
            var diffuseMaterial = new DiffuseMaterial(Brushes.Red);

            var meshNormalMaterial = new MeshNormalMaterial()
            {
                ColorMask = colorMask
            };

            diffuseMaterial.SetUsedDXMaterial(meshNormalMaterial);

            _disposeList.Add(meshNormalMaterial);


            var model3D = new GeometryModel3D(mesh, diffuseMaterial);

            model3D.Transform = new TranslateTransform3D(position.X, position.Y, position.Z);

            var modelVisual3D = new ModelVisual3D()
            {
                Content = model3D
            };

            MainViewport.Children.Add(modelVisual3D);

            return(model3D);
        }
        private void ShowOnlyHiddenLines()
        {
            var allTestLines = TestObjectsModelVisual3D.Children.OfType <BaseLineVisual3D>().ToList();

            foreach (var lineVisual3D in allTestLines)
            {
                // Use _hiddenLineMaterial and put line into OverlayRenderingQueue (see comments in ShowVisibleAndHiddenLines for more info)
                ChangeLineMaterial(lineVisual3D, _hiddenLineMaterial, MainDXViewportView.DXScene.OverlayRenderingQueue);

                // We could also call SetDXAttribute and set the CustomRenderingQueue to OverlayRenderingQueue.
                //lineVisual3D.SetDXAttribute(DXAttributeType.CustomRenderingQueue, MainDXViewportView.DXScene.OverlayRenderingQueue);
            }


            if (_wireframeGeometryModel3D != null)
            {
                var newWpfWireframeMaterial = new DiffuseMaterial(Brushes.Red);
                newWpfWireframeMaterial.SetUsedDXMaterial(_hiddenLineMaterial);

                _wireframeGeometryModel3D.Material = newWpfWireframeMaterial;
                _wireframeGeometryModel3D.SetDXAttribute(DXAttributeType.CustomRenderingQueue, MainDXViewportView.DXScene.OverlayRenderingQueue);
            }


            // Change LineMaterial to _hiddenLineMaterial and move it to the OverlayRenderingQueue
            _screenSpaceLineNode.LineMaterial         = _hiddenLineMaterial;
            _screenSpaceLineNode.CustomRenderingQueue = MainDXViewportView.DXScene.OverlayRenderingQueue;

            _screenSpaceLineNode.NotifySceneNodeChange(SceneNode.SceneNodeDirtyFlags.MaterialChanged | SceneNode.SceneNodeDirtyFlags.RenderingQueueChanged);
        }
        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);
        }
        private void ShowVisibleAndHiddenLines()
        {
            // To show both visible and hidden lines we need to render each line twice:
            // once with standard settings to shew visible part of the one,
            // once with using HiddenLineMaterial to show the hidden part of the line.

            // Now we will clone the existing 3D lines
            var existingLineVisuals = TestObjectsModelVisual3D.Children.OfType <BaseLineVisual3D>().ToList();

            var newLineVisuals = new List <BaseLineVisual3D>();

            foreach (var lineVisual3D in existingLineVisuals)
            {
                var clonedLineVisual = CloneLineVisuals(lineVisual3D);

                TestObjectsModelVisual3D.Children.Add(clonedLineVisual);
                newLineVisuals.Add(clonedLineVisual);
            }

            // After adding new WPF objects to the scene, we need to manually call Update to create DXEngine's SceneNode objects that will be needed later
            MainDXViewportView.Update();


            // We need to update the _sceneNodesDictionary because we have changed the scene
            CreateSceneNodesDictionary();



            // Now change the materials of the clones lines to hiddenLineMaterial
            foreach (var newLineVisual3D in newLineVisuals)
            {
                ChangeLineMaterial(newLineVisual3D, _hiddenLineMaterial);
            }


            if (_wireframeGeometryModel3D != null)
            {
                // Clone the GeometryModel3D that shows teapot wireframe and use hiddenLineMaterial to render it
                var newWpfWireframeMaterial = new DiffuseMaterial(Brushes.Red);
                newWpfWireframeMaterial.SetUsedDXMaterial(_hiddenLineMaterial);

                var geometryModel3D = new GeometryModel3D(_wireframeGeometryModel3D.Geometry, newWpfWireframeMaterial);
                geometryModel3D.Transform = _wireframeGeometryModel3D.Transform;
                var modelVisual3D = new ModelVisual3D()
                {
                    Content = geometryModel3D
                };

                TestObjectsModelVisual3D.Children.Add(modelVisual3D);
            }
        }
        private DiffuseMaterial CreateDiffuseMaterial(string textureFileName)
        {
            DiffuseMaterial material;

            if (textureFileName.EndsWith(".dds", StringComparison.OrdinalIgnoreCase))
            {
                var dxScene = MainDXViewportView.DXScene;
                if (dxScene == null) // In case of WPF 3D rendering
                {
                    return(null);
                }


                // The easiest way to load image file and in the same time create a material with the loaded texture is to use the CreateStandardTextureMaterial method.
                var standardMaterial = Ab3d.DirectX.TextureLoader.CreateStandardTextureMaterial(MainDXViewportView.DXScene.DXDevice, textureFileName);

                // We need to manually dispose the created StandardMaterial and ShaderResourceView
                _disposables.Add(standardMaterial);
                _disposables.Add(standardMaterial.DiffuseTextures[0]);


                bool isAlphaToCoverageEnabled = AlphaToCoverageRadioButton.IsChecked ?? false;
                bool isAlphaClippingEnabled   = AlphaClippingRadioButton.IsChecked ?? false;

                standardMaterial.AlphaClipThreshold = isAlphaClippingEnabled
                                                        ? GetAlphaClippingThreshold()
                                                        : 0; // 0 disables alpha clipping

                // When AlphaToCoverage is enabled, then we need to set the TextureBlendState to AlphaToCoverage.
                // If this is not done (if TextureBlendState is null), then the bend state is set to Opaque or PremultipliedAlphaBlend (when the texture has transparency)
                if (isAlphaToCoverageEnabled)
                {
                    standardMaterial.TextureBlendState = dxScene.DXDevice.CommonStates.AlphaToCoverage;
                }

                material = new DiffuseMaterial();
                material.SetUsedDXMaterial(standardMaterial);
            }
            else
            {
                var bitmapImage = new BitmapImage(new Uri(textureFileName, UriKind.Absolute));
                material = new DiffuseMaterial(new ImageBrush(bitmapImage));

                // When using WPF material, we need to set special DXEngine attributes with using SetDXAttribute (this is done in the following method):
                SetMaterialsDXAttributes(material);
            }

            return(material);
        }
        private void ShowOnlyHiddenLines()
        {
            foreach (var lineVisual3D in TestObjectsModelVisual3D.Children.OfType <BaseLineVisual3D>())
            {
                ChangeLineMaterial(lineVisual3D, _hiddenLineMaterial);
            }


            if (_wireframeGeometryModel3D != null)
            {
                var newWpfWireframeMaterial = new DiffuseMaterial(Brushes.Red);
                newWpfWireframeMaterial.SetUsedDXMaterial(_hiddenLineMaterial);

                _wireframeGeometryModel3D.Material = newWpfWireframeMaterial;
            }
        }
Ejemplo n.º 7
0
        private void CreateSampleScene()
        {
            _physicallyBasedMaterial = new PhysicallyBasedMaterial();

            // We need to dispose the PhysicallyBasedMaterial when this sample is uloaded
            _disposables.Add(_physicallyBasedMaterial);


            UpdateBaseColor();
            UpdateMetalness();
            UpdateRoughness();

            var normalMapShaderResourceView = GetNormalMapShaderResourceView();

            if (normalMapShaderResourceView != null)
            {
                _physicallyBasedMaterial.SetTextureMap(TextureMapTypes.NormalMap, normalMapShaderResourceView, "bricks_normal.png");
            }

            var ambientOcclusionShaderResourceView = AmbientOcclusionShaderResourceView();

            if (ambientOcclusionShaderResourceView != null)
            {
                _physicallyBasedMaterial.SetTextureMap(TextureMapTypes.AmbientOcclusion, ambientOcclusionShaderResourceView, "bricks_ao.png");
            }



            var wpfMaterial = new DiffuseMaterial(Brushes.Red);

            wpfMaterial.SetUsedDXMaterial(_physicallyBasedMaterial);

            ModelPlaceholder.Content = null;
            ModelPlaceholder.Children.Clear();


            var sphereVisual3D = new Ab3d.Visuals.SphereVisual3D()
            {
                CenterPosition          = new Point3D(40, 12, 0),
                Radius                  = 12,
                Segments                = 50,
                Material                = wpfMaterial,
                FreezeMeshGeometry3D    = false,
                UseCachedMeshGeometry3D = false
            };

            ModelPlaceholder.Children.Add(sphereVisual3D);


            var boxVisual3D = new Ab3d.Visuals.BoxVisual3D()
            {
                CenterPosition          = new Point3D(-40, 10, 0),
                Size                    = new Size3D(20, 20, 20),
                Material                = wpfMaterial,
                FreezeMeshGeometry3D    = false,
                UseCachedMeshGeometry3D = false
            };

            ModelPlaceholder.Children.Add(boxVisual3D);


            var readerObj = new Ab3d.ReaderObj();

            var readModel3D = (GeometryModel3D)readerObj.ReadModel3D(_modelsFolder + "teapot-hires.obj");

            Ab3d.Utilities.ModelUtils.CenterAndScaleModel3D(readModel3D, new Point3D(0, 10, 0), new Size3D(40, 40, 40), true);

            //// This code is called for each GeometryModel3D inside Plane1
            //var tangentVectors = Ab3d.DirectX.Utilities.MeshUtils.CalculateTangentVectors((MeshGeometry3D)readModel3D.Geometry);

            ////// Assign tangent array to the MeshGeometry3D
            //readModel3D.Geometry.SetDXAttribute(DXAttributeType.MeshTangentArray, tangentVectors);



            readModel3D.Material = wpfMaterial;

            //ModelPlaceholder.Content = null;
            ModelPlaceholder.Children.Add(readModel3D.CreateModelVisual3D());



            // Rendering normal (bump) maps require tangent vectors.
            // The following code will generate tangent vectors and assign them to the MeshGeometry3D that form our 3D model.
            // If tangent vectors are not provided, they will be calculated on-demand in the pixel shader (slightly reducing performance).

            Ab3d.Utilities.ModelIterator.IterateGeometryModel3DObjects(ModelPlaceholder, delegate(GeometryModel3D geometryModel3D, Transform3D transform3D)
            {
                // This code is called for each GeometryModel3D inside Plane1
                var tangentVectors = Ab3d.DirectX.Utilities.MeshUtils.CalculateTangentVectors((MeshGeometry3D)geometryModel3D.Geometry);

                // Assign tangent array to the MeshGeometry3D
                geometryModel3D.Geometry.SetDXAttribute(DXAttributeType.MeshTangentArray, tangentVectors);
            });


            Camera1.Distance = 150;

            UpdateLights();
        }
        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);
        }
        private void CreateTeapotWireframeModel(Point3D centerPosition, Size3D size, DiffuseMaterial material)
        {
            // The most common way to show wireframe models in DXEngine is to use WireframeVisual3D from Ab3d.PowerToys - see commented code below:
            //var wireframeVisual3D = new WireframeVisual3D()
            //{
            //    WireframeType = WireframeVisual3D.WireframeTypes.WireframeWithOriginalSolidModel,
            //    UseModelColor = false,
            //    LineThickness = 1,
            //    LineColor = Colors.Yellow,
            //    Transform = new TranslateTransform3D(0, 0, -50)
            //};
            //
            //wireframeVisual3D.OriginalModel = teapotModel;
            //// Set LineDepthBias to prevent rendering wireframe at the same depth as the 3D objects.
            //// This creates much nicer 3D lines. See the LineDepthBiasSample for more information.
            //wireframeVisual3D.SetDXAttribute(DXAttributeType.LineDepthBias, 0.1);

            // But in this sample we show special line rendering.
            // Therefore we will create standard WPF GeometryModel3D and then apply LineMaterial to it so the model will be rendered with wireframe lines

            // First read teapot model from Teapot.obj file
            var readerObj   = new Ab3d.ReaderObj();
            var teapotModel = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Models\Teapot.obj")) as GeometryModel3D;

            if (teapotModel == null)
            {
                return;
            }

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


            // Get transformation to scale and position the model to the centerPosition and size
            var bounds = meshGeometry3D.Bounds;

            double scaleX = size.X / bounds.SizeX;
            double scaleY = size.Y / bounds.SizeY;
            double scaleZ = size.Z / bounds.SizeZ;

            double minScale = Math.Min(scaleX, Math.Min(scaleY, scaleZ));

            scaleX = scaleY = scaleZ = minScale;

            var scaleTransform3D = new ScaleTransform3D(scaleX, scaleY, scaleZ);

            bounds = scaleTransform3D.TransformBounds(bounds);


            double cx = bounds.X + bounds.SizeX * 0.5;
            double cy = bounds.Y + bounds.SizeY * 0.5;
            double cz = bounds.Z + bounds.SizeZ * 0.5;

            var translateTransform3D = new TranslateTransform3D(centerPosition.X - cx, centerPosition.Y - cy, centerPosition.Z - cz);

            var transform3DGroup = new Transform3DGroup();

            transform3DGroup.Children.Add(scaleTransform3D);
            transform3DGroup.Children.Add(translateTransform3D);



            // First create the standard solid model with the specified material
            var geometryModel3D = new GeometryModel3D(meshGeometry3D, material);

            geometryModel3D.Transform = transform3DGroup;

            var modelVisual3D = new ModelVisual3D()
            {
                Content = geometryModel3D
            };

            TestObjectsModelVisual3D.Children.Add(modelVisual3D);


            // To render wireframe object, we first create a DXEngine material that is used to rendered lines or wireframe
            if (_dxLineMaterial == null)
            {
                _dxLineMaterial = new LineMaterial()
                {
                    LineThickness = 1,
                    LineColor     = Colors.Yellow.ToColor4(),
                    DepthBias     = 0.1f
                                    // Set DepthBias to prevent rendering wireframe at the same depth as the 3D objects. This creates much nicer 3D lines because lines are rendered on top of 3D object and not in the same position as 3D object.
                };
            }
            else
            {
                _dxLineMaterial.ReadZBuffer = true;
            }

            // Now create standard WPF material and assign DXEngine's LineMaterial to it.
            // This will use the dxLineMaterial when the wpfLineMaterial will be rendered in DXEngine
            var wpfWireframeMaterial = new DiffuseMaterial(Brushes.Red);

            wpfWireframeMaterial.SetUsedDXMaterial(_dxLineMaterial);


            // Finally, create another GeometryModel3D, but this time we will use DXEngine's LineMaterial to render it
            _wireframeGeometryModel3D           = new GeometryModel3D(meshGeometry3D, wpfWireframeMaterial);
            _wireframeGeometryModel3D.Transform = transform3DGroup;

            modelVisual3D = new ModelVisual3D()
            {
                Content = _wireframeGeometryModel3D
            };

            TestObjectsModelVisual3D.Children.Add(modelVisual3D);
        }
        private void ShowVisibleAndHiddenLines()
        {
            // To show both visible and hidden lines we need to render each line twice:
            // once with standard settings to shew visible part of the one,
            // once with using HiddenLineMaterial to show the hidden part of the line.


            // Now we will clone the existing 3D lines
            var existingLineVisuals = TestObjectsModelVisual3D.Children.OfType <BaseLineVisual3D>().ToList();

            var newLineVisuals = new List <BaseLineVisual3D>();

            foreach (var lineVisual3D in existingLineVisuals)
            {
                var clonedLineVisual = CloneLineVisuals(lineVisual3D);

                // To correctly show hidden lines, then need to be rendered after the objects in front of the lines
                // (they are rendered only in case when there are already some objects in front of them - line's depth is bigger then current depth value).
                // In case you want to show the hidden lines behind semi-transparent objects, you need to make sure that
                // the lines are put into the OverlayRenderingQueue.
                // This is needed because TransparentRenderingQueue is defined after LineGeometryRenderingQueue
                // and therefore all transparent objects are rendered after all 3D lines (this is needed so the lines are visible through transparent objects).
                // This can be done with using the SetDXAttribute method and setting the CustomRenderingQueue value.
                // Note that this value need to be set before the line is initialized by the DXEngine - so before the MainDXViewportView.Update call a few lines below.
                // (in case of using ScreenSpaceLineNode, you can set its CustomRenderingQueue).
                //clonedLineVisual.SetDXAttribute(DXAttributeType.CustomRenderingQueue, MainDXViewportView.DXScene.OverlayRenderingQueue);

                TestObjectsModelVisual3D.Children.Add(clonedLineVisual);
                newLineVisuals.Add(clonedLineVisual);
            }

            // After adding new WPF objects to the scene, we need to manually call Update to create DXEngine's SceneNode objects that will be needed later
            MainDXViewportView.Update();

            // We need to update the _sceneNodesDictionary because we have changed the scene
            CreateSceneNodesDictionary();

            // Now change the materials of the clones lines to hiddenLineMaterial
            foreach (var newLineVisual3D in newLineVisuals)
            {
                // Now we can change the material to _hiddenLineMaterial.
                //
                // We also need to put the hidden line to the OverlayRenderingQueue.
                // This is needed because to correctly show hidden lines, they need to be rendered after the objects in front of the lines
                // (they are rendered only in case when there are already some objects in front of them - line's depth is bigger then current depth value).
                // In case you want to show the hidden lines behind semi-transparent objects, you need to make sure that
                // the lines are put into the OverlayRenderingQueue.
                // This is needed because TransparentRenderingQueue is defined after LineGeometryRenderingQueue
                // and therefore all transparent objects are rendered after all 3D lines (this is needed so the lines are visible through transparent objects).
                //
                // Here this is done with setting the CustomRenderingQueue on the ScreenSpaceLineNode (see ChangeLineMaterial method).

                ChangeLineMaterial(newLineVisual3D, _hiddenLineMaterial, MainDXViewportView.DXScene.OverlayRenderingQueue);

                // We could also call SetDXAttribute and set the CustomRenderingQueue to OverlayRenderingQueue.
                // This can be done with uncommenting the following line
                // (but this is less efficient than setting the CustomRenderingQueue on the ScreenSpaceLineNode as done in the ChangeLineMaterial):
                //newLineVisual3D.SetDXAttribute(DXAttributeType.CustomRenderingQueue, MainDXViewportView.DXScene.OverlayRenderingQueue);
            }


            if (_wireframeGeometryModel3D != null)
            {
                // Clone the GeometryModel3D that shows teapot wireframe and use hiddenLineMaterial to render it
                var newWpfWireframeMaterial = new DiffuseMaterial(Brushes.Red);
                newWpfWireframeMaterial.SetUsedDXMaterial(_hiddenLineMaterial);

                var geometryModel3D = new GeometryModel3D(_wireframeGeometryModel3D.Geometry, newWpfWireframeMaterial);
                geometryModel3D.Transform = _wireframeGeometryModel3D.Transform;
                var modelVisual3D = new ModelVisual3D()
                {
                    Content = geometryModel3D
                };

                TestObjectsModelVisual3D.Children.Add(modelVisual3D);
            }


            // Create a new ScreenSpaceLineNode from the data for _screenSpaceLineNode
            // Set its material to _hiddenLineMaterial and move it to the OverlayRenderingQueue:
            var hiddenScreenSpaceLineNode = new ScreenSpaceLineNode(_screenSpaceLineNode.Positions, _screenSpaceLineNode.IsLineStrip, _screenSpaceLineNode.IsLineClosed, _hiddenLineMaterial);

            hiddenScreenSpaceLineNode.CustomRenderingQueue = MainDXViewportView.DXScene.OverlayRenderingQueue;

            var sceneNodeVisual3D = new SceneNodeVisual3D(hiddenScreenSpaceLineNode);

            TestObjectsModelVisual3D.Children.Add(sceneNodeVisual3D);
        }