#region License
/* FNA - XNA4 Reimplementation for Desktop Platforms
* Copyright 2009-2016 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 height;
}
set
{
height = value;
}
}
///
/// The upper limit of depth of this viewport.
///
public float MaxDepth
{
get
{
return maxDepth;
}
set
{
maxDepth = value;
}
}
///
/// The lower limit of depth of this viewport.
///
public float MinDepth
{
get
{
return minDepth;
}
set
{
minDepth = value;
}
}
///
/// The width of the bounds in pixels.
///
public int Width
{
get
{
return width;
}
set
{
width = value;
}
}
///
/// The y coordinate of the beginning of this viewport.
///
public int Y
{
get
{
return y;
}
set
{
y = value;
}
}
///
/// The x coordinate of the beginning of this viewport.
///
public int X
{
get
{
return x;
}
set
{
x = value;
}
}
///
/// Gets the aspect ratio of this , which is width / height.
///
public float AspectRatio
{
get
{
if ((height != 0) && (width != 0))
{
return (((float) width) / ((float) height));
}
return 0.0f;
}
}
///
/// Gets or sets a boundary of this .
///
public Rectangle Bounds
{
get
{
return new Rectangle(
x,
y,
width,
height
);
}
set
{
x = value.X;
y = value.Y;
width = value.Width;
height = 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 Private Variables
private int x;
private int y;
private int width;
private int height;
private float minDepth;
private float maxDepth;
#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)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
minDepth = 0.0f;
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)
{
x = bounds.X;
y = bounds.Y;
width = bounds.Width;
height = bounds.Height;
minDepth = 0.0f;
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:" + x.ToString() +
" Y:" + y.ToString() +
" Width:" + width.ToString() +
" Height:" + height.ToString() +
" MinDepth:" + minDepth.ToString() +
" MaxDepth:" + maxDepth.ToString() +
"}"
);
}
#endregion
}
}