/// <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) { var topLeftRay = viewport.UnProjectToRay(zoomRectangle.TopLeft); var topRightRay = viewport.UnProjectToRay(zoomRectangle.TopRight); var centerRay = viewport.UnProjectToRay( 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 = 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(); var newTarget = centerRay.PlaneIntersection(oldTarget, w); if (newTarget != null) { LookAt(orthographicCamera, newTarget.Value.ToPoint3D(), 200); } } }
/// <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) { var pcam = camera as ProjectionCamera; if (pcam == null) { return; } var topLeftRay = viewport.UnProjectToRay(zoomRectangle.TopLeft); var topRightRay = viewport.UnProjectToRay(zoomRectangle.TopRight); var centerRay = viewport.UnProjectToRay( 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 = pcam.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(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); } var orthographicCamera = camera as OrthographicCamera; if (orthographicCamera != null) { orthographicCamera.Width *= zoomRectangle.Width / viewport.ActualWidth; var oldTarget = pcam.Position + pcam.LookDirection; var distance = pcam.LookDirection.Length; var newTarget = centerRay.PlaneIntersection(oldTarget, w); if (newTarget != null) { orthographicCamera.LookDirection = w * distance; orthographicCamera.Position = newTarget.Value - orthographicCamera.LookDirection; } } }
/// <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) { var pcam = camera as ProjectionCamera; if (pcam == null) { return; } var topLeftRay = viewport.UnProjectToRay(zoomRectangle.TopLeft); var topRightRay = viewport.UnProjectToRay(zoomRectangle.TopRight); var centerRay = viewport.UnProjectToRay( 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 = pcam.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(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); } var orthographicCamera = camera as OrthographicCamera; if (orthographicCamera != null) { orthographicCamera.Width *= zoomRectangle.Width / viewport.ActualWidth; var oldTarget = pcam.Position + pcam.LookDirection; var distance = pcam.LookDirection.Length; var newTarget = centerRay.PlaneIntersection(oldTarget, w); if (newTarget != null) { orthographicCamera.LookDirection = w * distance; orthographicCamera.Position = newTarget.Value - orthographicCamera.LookDirection; } } }