///// <summary> ///// Animates the camera position and directions. ///// </summary> ///// <param name="camera"> ///// The camera to animate. ///// </param> ///// <param name="newPosition"> ///// The position to animate to. ///// </param> ///// <param name="newDirection"> ///// The direction to animate to. ///// </param> ///// <param name="newUpDirection"> ///// The up direction to animate to. ///// </param> ///// <param name="animationTime"> ///// Animation time in milliseconds. ///// </param> //public static void AnimateTo( // this Camera camera, // Vector3 newPosition, // Vector3 newDirection, // Vector3 newUpDirection, // double animationTime) //{ // var projectionCamera = camera as ProjectionCamera; // if (projectionCamera == null) // { // return; // } // projectionCamera.Position = newPosition; // projectionCamera.LookDirection = newDirection; // projectionCamera.UpDirection = newUpDirection; // //if (animationTime > 0) // //{ // // var a1 = new Point3DAnimation( // // fromPosition, newPosition, new Duration(TimeSpan.FromMilliseconds(animationTime))) // // { // // AccelerationRatio = 0.3, // // DecelerationRatio = 0.5, // // FillBehavior = FillBehavior.Stop // // }; // // a1.Completed += (s, a) => { camera.BeginAnimation(ProjectionCamera.PositionProperty, null); }; // // camera.BeginAnimation(ProjectionCamera.PositionProperty, a1); // // var a2 = new Vector3DAnimation( // // fromDirection, newDirection, new Duration(TimeSpan.FromMilliseconds(animationTime))) // // { // // AccelerationRatio = 0.3, // // DecelerationRatio = 0.5, // // FillBehavior = FillBehavior.Stop // // }; // // a2.Completed += (s, a) => { camera.BeginAnimation(ProjectionCamera.LookDirectionProperty, null); }; // // camera.BeginAnimation(ProjectionCamera.LookDirectionProperty, a2); // // var a3 = new Vector3DAnimation( // // fromUpDirection, newUpDirection, new Duration(TimeSpan.FromMilliseconds(animationTime))) // // { // // AccelerationRatio = 0.3, // // DecelerationRatio = 0.5, // // FillBehavior = FillBehavior.Stop // // }; // // a3.Completed += (s, a) => { camera.BeginAnimation(ProjectionCamera.UpDirectionProperty, null); }; // // camera.BeginAnimation(ProjectionCamera.UpDirectionProperty, a3); // //} //} /// <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 Camera camera, Viewport3DX viewport, Rect zoomRectangle) { if (!(camera is ProjectionCamera pcam)) { return; } if (viewport.UnProject(new Vector2((float)zoomRectangle.Top, (float)zoomRectangle.Left), out var topLeftRay) && viewport.UnProject(new Vector2((float)zoomRectangle.Top, (float)zoomRectangle.Right), out var topRightRay) && viewport.UnProject( new Vector2( ((float)zoomRectangle.Left + (float)zoomRectangle.Right) * 0.5f, ((float)zoomRectangle.Top + (float)zoomRectangle.Bottom) * 0.5f), out var centerRay)) { var u = topLeftRay.Direction; var v = topRightRay.Direction; var w = centerRay.Direction; u.Normalize(); v.Normalize(); w.Normalize(); if (camera is PerspectiveCamera perspectiveCamera) { var distance = pcam.LookDirection.Length(); // option 1: change distance var newDistance = distance * zoomRectangle.Width / viewport.ActualWidth; var newLookDirection = (float)newDistance * w; var newPosition = perspectiveCamera.Position + ((distance - (float)newDistance) * w); var newTarget = newPosition + newLookDirection; LookAt(pcam, 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); } else if (camera is OrthographicCamera orthographicCamera) { orthographicCamera.Width *= zoomRectangle.Width / viewport.ActualWidth; var oldTarget = pcam.Position + pcam.LookDirection; var distance = pcam.LookDirection.Length(); if (centerRay.PlaneIntersection(oldTarget, w, out var newTarget)) { orthographicCamera.LookDirection = w * distance; orthographicCamera.Position = newTarget - orthographicCamera.LookDirection; } } } }
/// <summary> /// /// </summary> /// <param name="viewport"></param> /// <param name="p"></param> /// <param name="plane"></param> /// <returns></returns> public static Vector3?UnProjectOnPlane(this Viewport3DX viewport, Vector2 p, Plane plane) { if (viewport.UnProject(p, out var ray)) { if (plane.Intersects(ref ray, out Vector3 point)) { return(point); } } return(null); }
/// <summary> /// Un-projects a 2D screen point. /// </summary> /// <param name="viewport">The viewport.</param> /// <param name="point2d">The input point.</param> /// <returns>The ray.</returns> public static Ray UnProject(this Viewport3DX viewport, Vector2 point2d) { if (viewport.UnProject(point2d, out var ray)) { return(ray); } else { return(new Ray()); } }
/// <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 Camera camera, Viewport3DX viewport, Rect zoomRectangle) { if (viewport.UnProject(zoomRectangle.TopLeft.ToVector2(), out var topLeftRay) && viewport.UnProject(zoomRectangle.TopRight.ToVector2(), out var topRightRay) && viewport.UnProject(new global::SharpDX.Vector2( (float)(zoomRectangle.Left + zoomRectangle.Right) * 0.5f, (float)(zoomRectangle.Top + zoomRectangle.Bottom) * 0.5f), out var centerRay)) { var u = Vector3.Normalize(topLeftRay.Direction); var v = Vector3.Normalize(topRightRay.Direction); var w = Vector3.Normalize(centerRay.Direction); if (camera is IPerspectiveCameraModel perspectiveCamera) { var distance = camera.LookDirection.Length; // option 1: change distance var newDistance = distance * zoomRectangle.Width / viewport.ActualWidth; var newLookDirection = (float)newDistance * w; var newPosition = camera.CameraInternal.Position + ((float)(distance - newDistance) * w); var newTarget = newPosition + newLookDirection; LookAt(camera, newTarget.ToPoint3D(), newLookDirection.ToVector3D(), 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); } else if (camera is IOrthographicCameraModel orthographicCamera) { orthographicCamera.Width *= zoomRectangle.Width / viewport.ActualWidth; var oldTarget = camera.CameraInternal.Position + camera.CameraInternal.LookDirection; var distance = camera.CameraInternal.LookDirection.Length(); if (centerRay.PlaneIntersection(oldTarget, w, out var newTarget)) { LookAt(orthographicCamera, newTarget.ToPoint3D(), 200); } } } }
/// <summary> /// /// </summary> /// <param name="viewport"></param> /// <param name="point2d"></param> /// <returns></returns> public static Ray UnProjectToRay(this Viewport3DX viewport, Vector2 point2d) { var r = viewport.UnProject(point2d); return(new Ray(r.Position, r.Direction)); }
/// <summary> /// Un-projects the specified 2D screen point to a ray. /// </summary> /// <param name="viewport">The viewport.</param> /// <param name="point2d">The point.</param> /// <returns>The ray.</returns> public static Ray3D UnProjectToRay(this Viewport3DX viewport, Point point2d) { var r = viewport.UnProject(point2d.ToVector2()); return(new Ray3D(r.Position.ToPoint3D(), r.Direction.ToVector3D())); }
/// <summary> /// Un-projects a 2D screen point. /// </summary> /// <param name="viewport">The viewport.</param> /// <param name="point2d">The input point.</param> /// <returns>The ray.</returns> public static Ray UnProject(this Viewport3DX viewport, Point point2d) { return(viewport.UnProject(point2d.ToVector2())); }
/// <summary> /// Un-projects a 2D screen point. /// </summary> /// <param name="viewport">The viewport.</param> /// <param name="point2d">The input point.</param> /// <returns>The ray.</returns> public static Ray UnProject(this Viewport3DX viewport, Vector2 point2d) { viewport.UnProject(point2d, out var ray); return(ray); }