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