private static Matrix3D GetProjectionMatrix(PerspectiveCamera camera, double aspectRatio) { Debug.Assert(camera != null, "Caller needs to ensure camera is non-null."); // This math is identical to what you find documented for // D3DXMatrixPerspectiveFovRH with the exception that in // WPF the camera's horizontal rather the vertical // field-of-view is specified. double hFoV = MUtils.DegreesToRadians(camera.FieldOfView); double zn = camera.NearPlaneDistance; double zf = camera.FarPlaneDistance; double xScale = 1 / Math.Tan(hFoV / 2); double yScale = aspectRatio * xScale; double m33 = (zf == double.PositiveInfinity) ? -1 : (zf / (zn - zf)); double m43 = zn * m33; return(new Matrix3D( xScale, 0, 0, 0, 0, yScale, 0, 0, 0, 0, m33, -1, 0, 0, m43, 0)); }
/// <summary> /// Computes the transform from the inner space of the given /// Visual3D to the camera coordinate space /// /// The result will contain the transform of the given visual. /// /// This method can fail if Camera.Transform is non-invertable /// in which case the camera clip planes will be coincident and /// nothing will render. In this case success will be false. /// </summary> /// <param name="visual"></param> /// <param name="success"></param> /// <returns></returns> public static Matrix3D TryTransformToCameraSpace(DependencyObject visual, out Viewport3DVisual viewport, out bool success) { Matrix3D toViewSpace = GetWorldTransformationMatrix(visual, out viewport); toViewSpace.Append(MUtils.TryWorldToCameraTransform(viewport, out success)); if (!success) { return(ZeroMatrix); } return(toViewSpace); }
/// <summary> /// Computes the transform from the inner space of the given /// Visual3D to the 2D space of the Viewport3DVisual which /// contains it. /// /// The result will contain the transform of the given visual. /// /// This method can fail if Camera.Transform is non-invertable /// in which case the camera clip planes will be coincident and /// nothing will render. In this case success will be false. /// </summary> /// <param name="visual"></param> /// <param name="success"></param> /// <returns></returns> public static Matrix3D TryTransformTo2DAncestor(DependencyObject visual, out Viewport3DVisual viewport, out bool success) { Matrix3D to2D = GetWorldTransformationMatrix(visual, out viewport); to2D.Append(MUtils.TryWorldToViewportTransform(viewport, out success)); if (!success) { return(ZeroMatrix); } return(to2D); }
/// <summary> /// Computes the transform from world space to the Viewport3DVisual's /// inner 2D space. /// /// This method can fail if Camera.Transform is non-invertable /// in which case the camera clip planes will be coincident and /// nothing will render. In this case success will be false. /// </summary> public static Matrix3D TryWorldToViewportTransform(Viewport3DVisual visual, out bool success) { success = false; Matrix3D result = TryWorldToCameraTransform(visual, out success); if (success) { result.Append(GetProjectionMatrix(visual.Camera, MUtils.GetAspectRatio(visual.Viewport.Size))); result.Append(GetHomogeneousToViewportTransform(visual.Viewport)); success = true; } return(result); }
public Point?Point3DToScreen2D(Point3D point3D, Viewport3D viewPort) { // We need a Viewport3DVisual but we only have a Viewport3D. if (viewPort.Children.Count == 0) { return(null); } Viewport3DVisual vpv = VisualTreeHelper.GetParent(viewPort.Children[0]) as Viewport3DVisual; // Get the world to viewport transform matrix Matrix3D m = MUtils.TryWorldToViewportTransform(vpv, out var bOk); if (!bOk) { return(null); } // Transform the 3D point to 2D var transformedPoint = m.Transform(point3D); var screen2DPoint = new Point(transformedPoint.X, transformedPoint.Y); return(screen2DPoint); }