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 AddModel(Model3D originalModel3D, Point3D position, PositionTypes positionType, Size3D size, bool preserveAspectRatio = true) { // Create a new Model3DGroup that will hold the originalModel3D. // This allows us to have different transformation for each originalModel3D (transformation is on Model3DGroup) var model3DGroup = new Model3DGroup(); model3DGroup.Children.Add(originalModel3D); Ab3d.Utilities.ModelUtils.PositionAndScaleModel3D(model3DGroup, position, positionType, size, preserveAspectRatio); // Add the model var modelVisual3D = new ModelVisual3D() { Content = model3DGroup }; SolidObjectsVisual3D.Children.Add(modelVisual3D); // Now add red WireCrossVisual3D at the specified position var wireCrossVisual3D = new Ab3d.Visuals.WireCrossVisual3D() { Position = position, LinesLength = 30, LineColor = Colors.Red }; SolidObjectsVisual3D.Children.Add(wireCrossVisual3D); // Now show a WireBoxVisual3D (box from 3D lines) that would represent the position, positionType and size. // To get the correct CenterPosition of the WireBoxVisual3D, // we start with creating a bounding box (Rect3D) that would be used when CenterPosition would be set to (0, 0, 0): var wireboxInitialBounds = new Point3D(-size.X * 0.5, -size.Y * 0.5, -size.Z * 0.5); // Then we use that bounding box and call GetModelTranslationVector3D method // that will tell us how much we need to move the bounding box so that it will be positioned at position and for positionType: var wireboxCenterOffset = Ab3d.Utilities.ModelUtils.GetModelTranslationVector3D(new Rect3D(wireboxInitialBounds, size), position, positionType); // Now we can use the result wireboxCenterOffset as a CenterPosition or a WireBoxVisual3D var wireBoxVisual3D = new WireBoxVisual3D() { CenterPosition = new Point3D(wireboxCenterOffset.X, wireboxCenterOffset.Y, wireboxCenterOffset.Z), Size = size, LineColor = Colors.Green, LineThickness = 1 }; SolidObjectsVisual3D.Children.Add(wireBoxVisual3D); // Finally we add TextBlockVisual3D to show position and size information for this model // Note that the TextBlockVisual3D is added to the TransparentObjectsVisual3D. // The reason for this is that TextBlockVisual3D uses semi-transparent background. // To correctly show other object through semi-transparent, the semi-transparent must be added to the scene after solid objects. var infoText = string.Format("Position: {0:0}\r\nPositionType: {1}\r\nSize: {2:0}", position, positionType, size); if (!preserveAspectRatio) { infoText += "\r\npreserveAspectRatio: false"; } var textBlockVisual3D = new TextBlockVisual3D() { Position = new Point3D(model3DGroup.Bounds.GetCenterPosition().X, -15, 55), // Show so that X center position is the same as model center position PositionType = PositionTypes.Center, TextDirection = new Vector3D(1, 0, 0), UpDirection = new Vector3D(0, 1, -1), // angled at 45 degrees Size = new Size(80, 0), // y size will be calculated automatically based on x size (80) and size of the text Text = infoText, BorderBrush = Brushes.DimGray, BorderThickness = new Thickness(1, 1, 1, 1), Background = new SolidColorBrush(Color.FromArgb(180, 200, 200, 200)), TextPadding = new Thickness(5, 2, 5, 2) }; TransparentObjectsVisual3D.Children.Add(textBlockVisual3D); }
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); }