コード例 #1
0
        private void LineTypesRadioButtonChanged(object sender, RoutedEventArgs e)
        {
            if (!this.IsLoaded)
            {
                return;
            }

            // First recreate all 3D objects to reset their attributes and settings
            CreateTest3DObjects();
            MainDXViewportView.Update();

            if (StandardLinesRadioButton.IsChecked ?? false)
            {
                // Nothing to do - just show standard lines
            }
            else if (OnlyHiddenLinesRadioButton.IsChecked ?? false)
            {
                ShowOnlyHiddenLines();
            }
            else if (StandardAndHiddenLinesRadioButton.IsChecked ?? false)
            {
                ShowVisibleAndHiddenLines();
            }
            else if (AlwaysVisibleLines1RadioButton.IsChecked ?? false)
            {
                ShowAlwaysVisibleLinesWithDXAttribute();
            }
            else if (AlwaysVisibleLines2RadioButton.IsChecked ?? false)
            {
                ShowAlwaysVisibleLinesAdvanced();
            }
        }
コード例 #2
0
        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);
            }
        }
コード例 #3
0
        private void GetClosestHitObject()
        {
            var dxScene = MainDXViewportView.DXScene;

            if (dxScene == null) // NO DXEngine rendering
            {
                return;
            }


            _hitLinesModelVisual3D.Children.Clear();

            // After the 3D lines are cleared we need to call Update method to update SceneNodes before we call HitTest.
            // If this is not done manually, the SceneNodes would be updated before next rendering but after the HitTest and we could get hit the 3D line.
            MainDXViewportView.Update();


            // DXHitTestOptions.MeshPositionsCountForOctTreeGeneration:
            // Gets or sets an integer value that specifies number of positions in a mesh (DXMeshGeometry3D) at which a OctTree is generated to speed up hit testing
            // (e.g. if mesh has more positions then a value specified with this property, then OctTree will be generated for the mesh).
            // Default value is 512.
            //dxScene.DXHitTestOptions.MeshPositionsCountForOctTreeGeneration = 1;

            //dxScene.DXHitTestOptions.GetOnlyFrontFacingTriangles = false;

            // Hit test center of the MainDXViewportView (we could also use mouse position)
            var positionInViewport3D = new Point(MainDXViewportView.ActualWidth / 2, MainDXViewportView.ActualHeight / 2);
            var pickRay = dxScene.GetRayFromCamera((int)positionInViewport3D.X, (int)positionInViewport3D.Y);

            // It is also possible to specify a hit test filter callback to skip testing some SceneNodes
            //dxScene.DXHitTestOptions.HitTestFilterCallback = delegate(SceneNode sceneNode)
            //{
            //    if (sceneNode == ...)
            //        return DXHitTestOptions.HitTestFilterResult.ContinueSkipSelfAndChildren;

            //    return DXHitTestOptions.HitTestFilterResult.Continue;
            //};

            var dxRayHitTestResult = dxScene.GetClosestHitObject(pickRay);


            if (dxRayHitTestResult == null)
            {
                AddMessage("DXScene hit test result: no object hit");
            }
            else
            {
                string message = string.Format("Ray.Start: {0:0.0}; Ray.Direction: {1:0.00}\r\nDXScene hit test result:\r\n  PointHit: {2:0.0};   (distance: {3:0})\r\n  SceneNode Id: {4}",
                                               pickRay.Position,
                                               pickRay.Direction,
                                               dxRayHitTestResult.HitPosition,
                                               dxRayHitTestResult.DistanceToRayOrigin,
                                               dxRayHitTestResult.HitSceneNode.Id);

                if (!string.IsNullOrEmpty(dxRayHitTestResult.HitSceneNode.Name))
                {
                    message += " ('" + dxRayHitTestResult.HitSceneNode.Name + "')";
                }

                AddMessage(message);

                AddHitLineArrow(pickRay, dxRayHitTestResult, dxRayHitTestResult.HitPosition.ToWpfPoint3D());
            }


            // NOTE:
            // If you want to manually do a hit testing on a mesh data with vertex and index buffer,
            // then you can use the Ab3d.DirectX.HitTester.HitTest method.
            // The method takes a Ray, various types of vertex buffers, index buffer and a few flags and returns a hit test result.
        }
コード例 #4
0
        private void GetAllHitTestObjects()
        {
            var dxScene = MainDXViewportView.DXScene;

            if (dxScene == null) // NO DXEngine rendering
            {
                return;
            }



            _hitLinesModelVisual3D.Children.Clear();

            // After the 3D lines are cleared we need to call Update method to update SceneNodes before we call HitTest.
            // If this is not done manually, the SceneNodes would be updated before next rendering but after the HitTest and we could get hit the 3D line.
            MainDXViewportView.Update();


            // DXHitTestOptions.MeshPositionsCountForOctTreeGeneration:
            // Gets or sets an integer value that specifies number of positions in a mesh (DXMeshGeometry3D) at which a OctTree is generated to speed up hit testing
            // (e.g. if mesh has more positions then a value specified with this property, then OctTree will be generated for the mesh).
            // Default value is 512.
            //dxScene.DXHitTestOptions.MeshPositionsCountForOctTreeGeneration = 1;

            // When GetOnlyFrontFacingTriangles is true, then only triangles that are facing the camera will be hit
            dxScene.DXHitTestOptions.GetOnlyFrontFacingTriangles = OnlyFrontTrianglesCheckBox.IsChecked ?? false;

            // By default multiple hit results can be returned per one SceneNode.
            // This can be changed by setting GetOnlyOneHitPerSceneNode to true.
            //dxScene.DXHitTestOptions.GetOnlyOneHitPerSceneNode = false;

            // It is also possible to specify a hit test filter callback to skip testing some SceneNodes
            //dxScene.DXHitTestOptions.HitTestFilterCallback = delegate(SceneNode sceneNode)
            //{
            //    if (sceneNode == ...)
            //        return DXHitTestOptions.HitTestFilterResult.ContinueSkipSelfAndChildren;

            //    return DXHitTestOptions.HitTestFilterResult.Continue;
            //};

            // Hit test center of the MainDXViewportView (we could also use mouse position)
            var positionInViewport3D = new Point(MainDXViewportView.ActualWidth / 2, MainDXViewportView.ActualHeight / 2);
            var pickRay = dxScene.GetRayFromCamera((int)positionInViewport3D.X, (int)positionInViewport3D.Y);


            List <DXRayHitTestResult> allHitTests = dxScene.GetAllHitObjects(pickRay);

            if (allHitTests.Count == 0)
            {
                AddMessage("No object hit\r\n");
            }
            else
            {
                var sb = new StringBuilder();
                sb.AppendFormat("Ray.Start: {0:0.0}; Ray.Direction: {1:0.00}\r\n{2} hit results:\r\n",
                                pickRay.Position, pickRay.Direction, allHitTests.Count);

                for (var i = 0; i < allHitTests.Count; i++)
                {
                    var hitTest = allHitTests[i];
                    sb.AppendFormat("{0}. PointHit: {1:0.0};  Dist: {2:0};   SceneNode Id: {3}",
                                    i + 1,
                                    hitTest.HitPosition,
                                    hitTest.DistanceToRayOrigin,
                                    hitTest.HitSceneNode.Id);

                    if (!string.IsNullOrEmpty(hitTest.HitSceneNode.Name))
                    {
                        sb.AppendFormat(" ('{0}')", hitTest.HitSceneNode.Name);
                    }

                    var dxRayHitTestWpfModel3DResult = hitTest as DXRayHitTestWpfModel3DResult;
                    if (dxRayHitTestWpfModel3DResult != null && dxRayHitTestWpfModel3DResult.HitGeometryModel3D != null)
                    {
                        var name = dxRayHitTestWpfModel3DResult.HitGeometryModel3D.GetName();

                        if (!string.IsNullOrEmpty(name))
                        {
                            sb.Append("  GeometryModel3D.Name: ").Append(name);
                        }
                    }


                    sb.AppendLine();

                    //if (_showHitArrows)
                    //{
                    var wireCrossVisual3D = new Ab3d.Visuals.WireCrossVisual3D()
                    {
                        Position      = hitTest.HitPosition.ToWpfPoint3D(),
                        LineColor     = Colors.Red,
                        LineThickness = 1,
                        LinesLength   = 5
                    };

                    _hitLinesModelVisual3D.Children.Add(wireCrossVisual3D);
                    //}
                }

                sb.AppendLine();

                AddMessage(sb.ToString());
            }

            var lineVisual3D = new Ab3d.Visuals.LineVisual3D()
            {
                StartPosition = pickRay.Position.ToWpfPoint3D(),
                EndPosition   = pickRay.Position.ToWpfPoint3D() + pickRay.Direction.ToWpfVector3D() * dxScene.Camera.FarPlaneDistance,
                LineColor     = Colors.Green,
                LineThickness = 1,
                EndLineCap    = LineCap.ArrowAnchor
            };

            _hitLinesModelVisual3D.Children.Add(lineVisual3D);
        }
コード例 #5
0
        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);
        }