/// <summary> /// Gets the transform to viewport space. /// </summary> /// <param name="visual"> /// The visual. /// </param> /// <returns> /// A transformation matrix. /// </returns> public static Matrix3D?GetViewportTransform(Visual3D visual) { var totalTransform = Matrix3D.Identity; DependencyObject obj = visual; while (obj != null) { var viewport3DVisual = obj as Viewport3DVisual; if (viewport3DVisual != null) { var matxViewport = Viewport3DHelper.GetTotalTransform(viewport3DVisual); totalTransform.Append(matxViewport); return(totalTransform); } var mv = obj as ModelVisual3D; if (mv != null) { if (mv.Transform != null) { totalTransform.Append(mv.Transform.Value); } } obj = VisualTreeHelper.GetParent(obj); } return(null); //throw new InvalidOperationException("The visual is not added to a Viewport3D."); // At this point, we know obj is Viewport3DVisual }
/// <summary> /// Zooms the camera to the specified rectangle. /// </summary> /// <param name="camera"> /// The camera. /// </param> /// <param name="viewport"> /// The viewport. /// </param> /// <param name="zoomRectangle"> /// The zoom rectangle. /// </param> public static void ZoomToRectangle(this ProjectionCamera camera, Viewport3D viewport, Rect zoomRectangle) { var topLeftRay = Viewport3DHelper.Point2DtoRay3D(viewport, zoomRectangle.TopLeft); var topRightRay = Viewport3DHelper.Point2DtoRay3D(viewport, zoomRectangle.TopRight); var centerRay = Viewport3DHelper.Point2DtoRay3D( viewport, new Point( (zoomRectangle.Left + zoomRectangle.Right) * 0.5, (zoomRectangle.Top + zoomRectangle.Bottom) * 0.5)); if (topLeftRay == null || topRightRay == null || centerRay == null) { // could not invert camera matrix return; } var u = topLeftRay.Direction; var v = topRightRay.Direction; var w = centerRay.Direction; u.Normalize(); v.Normalize(); w.Normalize(); var perspectiveCamera = camera as PerspectiveCamera; if (perspectiveCamera != null) { var distance = camera.LookDirection.Length; // option 1: change distance var newDistance = distance * zoomRectangle.Width / viewport.ActualWidth; var newLookDirection = newDistance * w; var newPosition = perspectiveCamera.Position + ((distance - newDistance) * w); var newTarget = newPosition + newLookDirection; LookAt(camera, newTarget, newLookDirection, 200); // option 2: change fov // double newFieldOfView = Math.Acos(Vector3D.DotProduct(u, v)); // var newTarget = camera.Position + distance * w; // pcamera.FieldOfView = newFieldOfView * 180 / Math.PI; // LookAt(camera, newTarget, distance * w, 0); } var orthographicCamera = camera as OrthographicCamera; if (orthographicCamera != null) { orthographicCamera.Width *= zoomRectangle.Width / viewport.ActualWidth; var oldTarget = camera.Position + camera.LookDirection; var distance = camera.LookDirection.Length; Point3D newTarget; if (centerRay.PlaneIntersection(oldTarget, w, out newTarget)) { orthographicCamera.LookDirection = w * distance; orthographicCamera.Position = newTarget - orthographicCamera.LookDirection; } } }
/// <summary> /// Get the ray into the view volume given by the position in 2D (screen coordinates) /// </summary> /// <param name="position"> /// A 2D point. /// </param> /// <returns> /// A ray /// </returns> protected Ray3D GetRay(Point position) { Point3D point1, point2; bool ok = Viewport3DHelper.Point2DtoPoint3D(this.Viewport, position, out point1, out point2); if (!ok) { return null; } return new Ray3D { Origin = point1, Direction = point2 - point1 }; }
/// <summary> /// The set mouse down point. /// </summary> /// <param name="position"> /// The position. /// </param> private void SetMouseDownPoint(Point position) { this.MouseDownPoint = position; Point3D nearestPoint; Vector3D normal; DependencyObject visual; if (Viewport3DHelper.FindNearest( this.Controller.Viewport, this.MouseDownPoint, out nearestPoint, out normal, out visual)) { this.MouseDownNearestPoint3D = nearestPoint; } else { this.MouseDownNearestPoint3D = null; } this.MouseDownPoint3D = this.UnProject(this.MouseDownPoint); }
/// <summary> /// Exports the specified viewport. /// </summary> /// <param name="viewport"> /// The viewport. /// </param> public void Export(Viewport3D viewport) { int m = this.OversamplingMultiplier; var background = this.Background; if (background == null) { background = Brushes.Transparent; } var bmp = Viewport3DHelper.RenderBitmap(viewport, background, m); BitmapEncoder encoder; string ext = Path.GetExtension(this.FileName); switch (ext.ToLower()) { case ".jpg": var jpg = new JpegBitmapEncoder(); jpg.Frames.Add(BitmapFrame.Create(bmp)); encoder = jpg; break; case ".png": var png = new PngBitmapEncoder(); png.Frames.Add(BitmapFrame.Create(bmp)); encoder = png; break; default: throw new InvalidOperationException("Not supported file format."); } using (Stream stm = File.Create(this.FileName)) { encoder.Save(stm); } }
/// <summary> /// Projects the point on the hit plane. /// </summary> /// <param name="p"> /// The p. /// </param> /// <param name="hitPlaneOrigin"> /// The hit Plane Origin. /// </param> /// <param name="hitPlaneNormal"> /// The hit plane normal (world coordinate system). /// </param> /// <returns> /// The point in world coordinates. /// </returns> protected virtual Point3D?GetHitPlanePoint(Point p, Point3D hitPlaneOrigin, Vector3D hitPlaneNormal) { return(Viewport3DHelper.UnProject(this.ParentViewport, p, hitPlaneOrigin, hitPlaneNormal)); }
/// <summary> /// Calculate the screen position of a 3D point. /// </summary> /// <param name="p"> /// The 3D point. /// </param> /// <returns> /// The 2D point. /// </returns> protected Point Project(Point3D p) { return(Viewport3DHelper.Point3DtoPoint2D(this.Viewport, p)); }