#region License /* FNA - XNA4 Reimplementation for Desktop Platforms * Copyright 2009-2022 Ethan Lee and the MonoGame Team * * Released under the Microsoft Public License. * See LICENSE for details. */ #endregion #region Using Statements using System; #endregion namespace Microsoft.Xna.Framework.Graphics { /// /// Describes the view bounds for render-target surface. /// [Serializable] public struct Viewport { #region Public Properties /// /// The height of the bounds in pixels. /// public int Height { get { return viewport.h; } set { viewport.h = value; } } /// /// The upper limit of depth of this viewport. /// public float MaxDepth { get { return viewport.maxDepth; } set { viewport.maxDepth = value; } } /// /// The lower limit of depth of this viewport. /// public float MinDepth { get { return viewport.minDepth; } set { viewport.minDepth = value; } } /// /// The width of the bounds in pixels. /// public int Width { get { return viewport.w; } set { viewport.w = value; } } /// /// The y coordinate of the beginning of this viewport. /// public int Y { get { return viewport.y; } set { viewport.y = value; } } /// /// The x coordinate of the beginning of this viewport. /// public int X { get { return viewport.x; } set { viewport.x = value; } } /// /// Gets the aspect ratio of this , which is width / height. /// public float AspectRatio { get { if ((viewport.h != 0) && (viewport.w != 0)) { return (((float) viewport.w) / ((float) viewport.h)); } return 0.0f; } } /// /// Gets or sets a boundary of this . /// public Rectangle Bounds { get { return new Rectangle( viewport.x, viewport.y, viewport.w, viewport.h ); } set { viewport.x = value.X; viewport.y = value.Y; viewport.w = value.Width; viewport.h = value.Height; } } /// /// Returns the subset of the viewport that is guaranteed to be visible on a lower quality display. /// public Rectangle TitleSafeArea { get { return Bounds; } } #endregion #region Internal FNA3D Variables internal FNA3D.FNA3D_Viewport viewport; #endregion #region Public Constructors /// /// Constructs a viewport from the given values. The will be 0.0 and will be 1.0. /// /// The x coordinate of the upper-left corner of the view bounds in pixels. /// The y coordinate of the upper-left corner of the view bounds in pixels. /// The width of the view bounds in pixels. /// The height of the view bounds in pixels. public Viewport(int x, int y, int width, int height) { viewport.x = x; viewport.y = y; viewport.w = width; viewport.h = height; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; } /// /// Constructs a viewport from the given values. /// /// A that defines the location and size of the in a render target. public Viewport(Rectangle bounds) { viewport.x = bounds.X; viewport.y = bounds.Y; viewport.w = bounds.Width; viewport.h = bounds.Height; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; } #endregion #region Public Methods /// /// Projects a from world space into screen space. /// /// The to project. /// The projection . /// The view . /// The world . /// public Vector3 Project( Vector3 source, Matrix projection, Matrix view, Matrix world ) { Matrix matrix = Matrix.Multiply( Matrix.Multiply(world, view), projection ); Vector3 vector = Vector3.Transform(source, matrix); float a = (((source.X * matrix.M14) + (source.Y * matrix.M24)) + (source.Z * matrix.M34)) + matrix.M44; if (!MathHelper.WithinEpsilon(a, 1.0f)) { vector.X = vector.X / a; vector.Y = vector.Y / a; vector.Z = vector.Z / a; } vector.X = (((vector.X + 1f) * 0.5f) * Width) + X; vector.Y = (((-vector.Y + 1f) * 0.5f) * Height) + Y; vector.Z = (vector.Z * (MaxDepth - MinDepth)) + MinDepth; return vector; } /// /// Unprojects a from screen space into world space. /// /// The to unproject. /// The projection . /// The view . /// The world . /// public Vector3 Unproject(Vector3 source, Matrix projection, Matrix view, Matrix world) { Matrix matrix = Matrix.Invert( Matrix.Multiply( Matrix.Multiply(world, view), projection ) ); source.X = (((source.X - X) / ((float) Width)) * 2f) - 1f; source.Y = -((((source.Y - Y) / ((float) Height)) * 2f) - 1f); source.Z = (source.Z - MinDepth) / (MaxDepth - MinDepth); Vector3 vector = Vector3.Transform(source, matrix); float a = ( ((source.X * matrix.M14) + (source.Y * matrix.M24)) + (source.Z * matrix.M34) ) + matrix.M44; if (!MathHelper.WithinEpsilon(a, 1.0f)) { vector.X = vector.X / a; vector.Y = vector.Y / a; vector.Z = vector.Z / a; } return vector; } /// /// Returns a representation of this in the format: /// {X:[] Y:[] Width:[] Height:[] MinDepth:[] MaxDepth:[]} /// /// A representation of this . public override string ToString() { return ( "{" + "X:" + viewport.x.ToString() + " Y:" + viewport.y.ToString() + " Width:" + viewport.w.ToString() + " Height:" + viewport.h.ToString() + " MinDepth:" + viewport.minDepth.ToString() + " MaxDepth:" + viewport.maxDepth.ToString() + "}" ); } #endregion } }