private BaseLineVisual3D GenerateRandomLine(Color lineColor, int lineLength)
        {
            var positions = CreateRandomPositions(lineLength);


            BaseLineVisual3D createdLine;

            if (_rnd.Next(4) == 1) // 25% chance to return a simple Line instead of PolyLine
            {
                createdLine = new Ab3d.Visuals.LineVisual3D()
                {
                    StartPosition = positions[0],
                    EndPosition   = positions[positions.Count - 1],
                    LineColor     = lineColor,
                    LineThickness = _rnd.NextDouble() * 5 + 1,
                };
            }
            else
            {
                createdLine = new Ab3d.Visuals.PolyLineVisual3D()
                {
                    LineColor     = lineColor,
                    LineThickness = _rnd.NextDouble() * 5 + 1,
                    Positions     = positions
                };
            }


            MainViewport.Children.Add(createdLine);

            return(createdLine);
        }
        public void SelectData(SphereDataView selectedPositionData, Point mousePosition)
        {
            // Show tooltip with details
            DataToolTipBorder.DataContext = selectedPositionData;

            Canvas.SetLeft(DataToolTipBorder, mousePosition.X + 10);
            Canvas.SetTop(DataToolTipBorder, mousePosition.Y + 10);

            DataToolTipBorder.Visibility = Visibility.Visible;


            // Add additional 3D lines that will show where the sphere is in the 3D space
            var centerPosition = AxesBox.CenterPosition;
            var size           = AxesBox.Size;

            double wireBoxBottom = centerPosition.Y - size.Y * 0.5;

            var verticalLineVisual3D = new Ab3d.Visuals.LineVisual3D()
            {
                StartPosition = selectedPositionData.Position,
                EndPosition   = new Point3D(selectedPositionData.Position.X, wireBoxBottom, selectedPositionData.Position.Z),
                LineThickness = 2,
                LineColor     = Colors.Gray
            };

            SelectedSphereLinesVisual.Children.Add(verticalLineVisual3D);

            double x1 = centerPosition.X - size.X * 0.5;
            double x2 = centerPosition.X + size.X * 0.5;

            var xLineVisual3D = new Ab3d.Visuals.LineVisual3D()
            {
                StartPosition = new Point3D(x1, wireBoxBottom, selectedPositionData.Position.Z),
                EndPosition   = new Point3D(x2, wireBoxBottom, selectedPositionData.Position.Z),
                LineThickness = 2,
                LineColor     = Colors.Gray
            };

            SelectedSphereLinesVisual.Children.Add(xLineVisual3D);

            double z1 = centerPosition.Z - size.Z * 0.5;
            double z2 = centerPosition.Z + size.Z * 0.5;

            var zLineVisual3D = new Ab3d.Visuals.LineVisual3D()
            {
                StartPosition = new Point3D(selectedPositionData.Position.X, wireBoxBottom, z1),
                EndPosition   = new Point3D(selectedPositionData.Position.X, wireBoxBottom, z2),
                LineThickness = 2,
                LineColor     = Colors.Gray
            };

            SelectedSphereLinesVisual.Children.Add(zLineVisual3D);
        }
        private void AddHitLineArrow(Ray ray, DXRayHitTestResult hitResult, Point3D?referenceHitPosition = null, Point3D?rayEndPosition = null)
        {
            Ab3d.Visuals.LineVisual3D lineVisual3D;
            Point3D endPosition;

            if (hitResult != null)
            {
                endPosition = hitResult.HitPosition.ToWpfPoint3D();
            }
            else
            {
                endPosition = rayEndPosition ?? Camera1.TargetPosition + Camera1.Offset;
            }

            if (hitResult != null)
            {
                lineVisual3D = new Ab3d.Visuals.LineVisual3D()
                {
                    StartPosition = ray.Position.ToWpfPoint3D(),
                    EndPosition   = endPosition,
                    LineColor     = Colors.Green,
                    LineThickness = 1,
                    EndLineCap    = LineCap.ArrowAnchor
                };


                if (referenceHitPosition != null)
                {
                    var wireCrossVisual3D = new Ab3d.Visuals.WireCrossVisual3D()
                    {
                        Position      = referenceHitPosition.Value,
                        LineColor     = Colors.Red,
                        LineThickness = 1,
                        LinesLength   = 5
                    };

                    _hitLinesModelVisual3D.Children.Add(wireCrossVisual3D);
                }
            }
            else
            {
                lineVisual3D = new Ab3d.Visuals.LineVisual3D()
                {
                    StartPosition = ray.Position.ToWpfPoint3D(),
                    EndPosition   = endPosition,
                    LineColor     = Colors.Green,
                    LineThickness = 1
                };
            }

            _hitLinesModelVisual3D.Children.Add(lineVisual3D);
        }
        private void HitTestButton_OnClick(object sender, RoutedEventArgs e)
        {
            var dxScene = MainDXViewportView.DXScene;

            if (dxScene == null)
            {
                return;
            }

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

            var hitTestContext   = new DXHitTestContext(dxScene);
            var octTreeHitResult = _octTree.HitTest(ref pickRay, hitTestContext);


            _hitLinesModelVisual3D.Children.Clear();

            if (octTreeHitResult == null)
            {
                AddMessage("OctTree hit test result: no object hit\r\n");
            }
            else
            {
                AddMessage(string.Format("OctTree hit test result (Ray.Start: {0:0.0}; Ray.Direction: {1:0.00}):\r\n  PointHit: {2:0.0};   (distance: {3:0})\r\n",
                                         pickRay.Position,
                                         pickRay.Direction,
                                         octTreeHitResult.HitPosition,
                                         octTreeHitResult.DistanceToRayOrigin));

                var lineVisual3D = new Ab3d.Visuals.LineVisual3D()
                {
                    StartPosition = pickRay.Position.ToWpfPoint3D(),
                    EndPosition   = octTreeHitResult.HitPosition.ToWpfPoint3D(),
                    LineColor     = Colors.Orange,
                    LineThickness = 1,
                    EndLineCap    = LineCap.ArrowAnchor
                };

                _hitLinesModelVisual3D.Children.Add(lineVisual3D);
            }
        }
Example #5
0
        private void UpdateHorizontalMouseLines()
        {
            if (_currentEditorMode == EditorModes.Create)
            {
                if (_horizontalMouseLine == null)
                {
                    _horizontalMouseLine = new Visuals.LineVisual3D
                    {
                        LineColor     = Colors.Green,
                        LineThickness = 2,
                        IsVisible     = false
                    };

                    LinesVisual.Children.Add(_horizontalMouseLine);
                }

                if (_verticalMouseLine == null)
                {
                    _verticalMouseLine = new Visuals.LineVisual3D
                    {
                        LineColor     = Colors.Green,
                        LineThickness = 2,
                        IsVisible     = false
                    };

                    LinesVisual.Children.Add(_verticalMouseLine);
                }
            }
            else
            {
                if (_horizontalMouseLine != null)
                {
                    LinesVisual.Children.Remove(_horizontalMouseLine);
                    _horizontalMouseLine = null;
                }

                if (_verticalMouseLine != null)
                {
                    LinesVisual.Children.Remove(_verticalMouseLine);
                    _verticalMouseLine = null;
                }
            }
        }
        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;
        }
        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);
        }
        private void CreateShapesSample()
        {
            //
            // First create a few lines
            //
            for (int i = 0; i < 5; i++)
            {
                // 2D coordinates of the line
                double x1 = -300;
                double y1 = -50 + i * 20;

                double x2 = -250;
                double y2 = i * 20;

                var lineVisual3D = new LineVisual3D()
                {
                    // Because we use 3D engine to show 2D lines, we need to convert 2D coordinates to 3D coordinates.
                    // This is done with setting Z to 0 (but we could use that to move some lines or shapes in front of the other lines).
                    StartPosition = new Point3D(x1, y1, 0),
                    EndPosition   = new Point3D(x2, y2, 0),
                    LineColor     = Colors.Black,
                    LineThickness = i + 1
                };

                RootLinesVisual3D.Children.Add(lineVisual3D);
            }


            //
            // Create a polyline
            //
            var polygonPositions = new Point3DCollection(new Point3D[]
            {
                new Point3D(-70, -50, 0),
                new Point3D(-170, -50, 0),
                new Point3D(-170, 50, 0),
                new Point3D(-70, 50, 0),
            });

            var polyLineVisual3D = new PolyLineVisual3D()
            {
                Positions     = polygonPositions,
                LineColor     = Colors.Black,
                LineThickness = 1,
                IsClosed      = true
            };

            RootLinesVisual3D.Children.Add(polyLineVisual3D);


            //
            // Create 2 lines with pattern (see LinesWithPatternSample for more info)
            //
            var lineWithPattern1 = new Ab3d.Visuals.LineVisual3D()
            {
                StartPosition = new Point3D(-300, -100, 0),
                EndPosition   = new Point3D(300, -100, 0),
                LineThickness = 2,
                LineColor     = Colors.Orange
            };

            lineWithPattern1.SetDXAttribute(DXAttributeType.LinePattern, 0x3333); // 0x3333 is 0011001100110011
            //lineWithPattern1.SetDXAttribute(DXAttributeType.LinePatternScale,  1); // We do not need to set default scale and offset values
            //lineWithPattern1.SetDXAttribute(DXAttributeType.LinePatternOffset, 0);

            RootLinesVisual3D.Children.Add(lineWithPattern1);


            var lineWithPattern2 = new Ab3d.Visuals.LineVisual3D()
            {
                StartPosition = new Point3D(-300, -110, 0),
                EndPosition   = new Point3D(300, -110, 0),
                LineThickness = 2,
                LineColor     = Colors.Orange
            };

            lineWithPattern2.SetDXAttribute(DXAttributeType.LinePattern, 0x5555); // 0x3333 is 0101010101010101

            RootLinesVisual3D.Children.Add(lineWithPattern2);


            //
            // Create curve with BezierCurve class from Ab3d.PowerToys library (see Lines3D/CurvesSample in Ab3d.PowerToys samples project for more)
            //
            // NOTE:
            // Ab3d.DXEngine cannot show real curves but only straight lines.
            // But you can convert a curve to many lines to simulate a curve (but this may be seen when zooming in).
            //
            var curveControlPoints = new Point3D[]
            {
                new Point3D(0, 0, 0),
                new Point3D(30, 0, 0),
                new Point3D(60, 50, 0),
                new Point3D(90, 0, 0),
                new Point3D(120, 0, 0)
            };

            var bezierCurve    = Ab3d.Utilities.BezierCurve.CreateFromCurvePositions(curveControlPoints);
            var curvePositions = bezierCurve.CreateBezierCurve(positionsPerSegment: 20); // create 20 positions between each control point

            var curveLineVisual3D = new PolyLineVisual3D()
            {
                Positions     = curvePositions,
                LineColor     = Colors.Green,
                LineThickness = 2,
                Transform     = new TranslateTransform3D(0, -50, 0)
            };

            RootLinesVisual3D.Children.Add(curveLineVisual3D);


            //
            // Create lines from a WPF ellipse or any other WPF's shape
            //
            var ellipseGeometry = new EllipseGeometry(new Rect(0, 0, 120, 50));
            var flattenGeometry = ellipseGeometry.GetFlattenedPathGeometry(tolerance: 0.1, type: ToleranceType.Absolute);

            var geometryPoints = new List <Point>();

            geometryPoints.Add(flattenGeometry.Figures[0].StartPoint);

            // We need only the first Figure
            foreach (var oneSegment in flattenGeometry.Figures[0].Segments)
            {
                if (oneSegment is PolyLineSegment)
                {
                    geometryPoints.AddRange(((PolyLineSegment)oneSegment).Points);
                }
                else if (oneSegment is LineSegment)
                {
                    geometryPoints.Add(((LineSegment)oneSegment).Point);
                }
            }

            var ellipsePoints = ConvertToPoint3DCollection(geometryPoints);

            var ellipseLineVisual3D = new PolyLineVisual3D()
            {
                Positions     = ellipsePoints,
                LineColor     = Colors.Green,
                LineThickness = 2,
                Transform     = new TranslateTransform3D(0, 20, 0)
            };

            RootLinesVisual3D.Children.Add(ellipseLineVisual3D);


            //
            // Show 2D shapes with using triangulator from Ab3d.PowerToys to convert shape to a set of triangles.
            //
            // NOTE:
            // The current version (Ab3d.PowerToys v9.4) does not support triangulating shapes with holes.
            //
            var shapePoints = new Point[]
            {
                new Point(0, 0),
                new Point(50, 0),
                new Point(100, 50),
                new Point(100, 100),
                new Point(50, 80),
                new Point(50, 40),
                new Point(0, 40),
                new Point(0, 0),
            };

            var triangulator    = new Ab3d.Utilities.Triangulator(shapePoints);
            var triangleIndices = triangulator.CreateTriangleIndices();

            var shapePoints3D = ConvertToPoint3DCollection(shapePoints);

            var meshGeometry3D = new MeshGeometry3D()
            {
                Positions       = shapePoints3D,
                TriangleIndices = new Int32Collection(triangleIndices)
            };

            var shapeGeometryModel3D = new GeometryModel3D(meshGeometry3D, new DiffuseMaterial(Brushes.LightBlue));

            // NOTE:
            // We set Z of the shape to -0.5 !!!
            // This will move the solid shape slightly behind the 3D line so the line will be always on top of the shape
            shapeGeometryModel3D.Transform = new TranslateTransform3D(200, -50, -0.5);

            RootLinesVisual3D.Children.Add(shapeGeometryModel3D.CreateModelVisual3D());


            // Also add an outline to the shape
            var shapeOutlineVisual3D = new PolyLineVisual3D()
            {
                Positions     = shapePoints3D,
                LineColor     = Colors.Black,
                LineThickness = 1,
                Transform     = shapeGeometryModel3D.Transform
            };

            RootLinesVisual3D.Children.Add(shapeOutlineVisual3D);
        }