Merge pull request #220 from Frassle/project

[Math] Vector3 Project and Unproject
This commit is contained in:
thefiddler 2015-05-11 12:07:24 +02:00
commit 788b039e32

View file

@ -1224,6 +1224,120 @@ namespace OpenTK
#endregion
#region Project
/// <summary>
/// Projects a vector from object space into screen space.
/// </summary>
/// <param name="vector">The vector to project.</param>
/// <param name="x">The X coordinate of the viewport.</param>
/// <param name="y">The Y coordinate of the viewport.</param>
/// <param name="width">The width of the viewport.</param>
/// <param name="height">The height of the viewport.</param>
/// <param name="minZ">The minimum depth of the viewport.</param>
/// <param name="maxZ">The maximum depth of the viewport.</param>
/// <param name="worldViewProjection">The world-view-projection matrix.</param>
/// <returns>The vector in screen space.</returns>
/// <remarks>
/// To project to normalized device coordinates (NDC) use the following parameters:
/// Project(vector, -1, -1, 2, 2, -1, 1, worldViewProjection).
/// </remarks>
public static Vector3 Project(Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, Matrix4 worldViewProjection)
{
Vector4 result;
result.X =
vector.X * worldViewProjection.M11 +
vector.Y * worldViewProjection.M21 +
vector.Z * worldViewProjection.M31 +
worldViewProjection.M41;
result.Y =
vector.X * worldViewProjection.M12 +
vector.Y * worldViewProjection.M22 +
vector.Z * worldViewProjection.M32 +
worldViewProjection.M42;
result.Z =
vector.X * worldViewProjection.M13 +
vector.Y * worldViewProjection.M23 +
vector.Z * worldViewProjection.M33 +
worldViewProjection.M43;
result.W =
vector.X * worldViewProjection.M14 +
vector.Y * worldViewProjection.M24 +
vector.Z * worldViewProjection.M34 +
worldViewProjection.M44;
result /= result.W;
result.X = x + (width * ((result.X + 1.0f) / 2.0f));
result.Y = y + (height * ((result.Y + 1.0f) / 2.0f));
result.Z = minZ + ((maxZ - minZ) * ((result.Z + 1.0f) / 2.0f));
return new Vector3(result.X, result.Y, result.Z);
}
#endregion
#region Unproject
/// <summary>
/// Projects a vector from screen space into object space.
/// </summary>
/// <param name="vector">The vector to project.</param>
/// <param name="x">The X coordinate of the viewport.</param>
/// <param name="y">The Y coordinate of the viewport.</param>
/// <param name="width">The width of the viewport.</param>
/// <param name="height">The height of the viewport.</param>
/// <param name="minZ">The minimum depth of the viewport.</param>
/// <param name="maxZ">The maximum depth of the viewport.</param>
/// <param name="worldViewProjection">The inverse of the world-view-projection matrix.</param>
/// <returns>The vector in object space.</returns>
/// <remarks>
/// To project from normalized device coordinates (NDC) use the following parameters:
/// Project(vector, -1, -1, 2, 2, -1, 1, inverseWorldViewProjection).
/// </remarks>
public static Vector3 Unproject(Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, Matrix4 inverseWorldViewProjection)
{
Vector4 result;
result.X = ((((vector.X - x) / width) * 2.0f) - 1.0f);
result.Y = ((((vector.Y - y) / height) * 2.0f) - 1.0f);
result.Z = (((vector.Z / (maxZ - minZ)) * 2.0f) - 1.0f);
result.X =
result.X * inverseWorldViewProjection.M11 +
result.Y * inverseWorldViewProjection.M21 +
result.Z * inverseWorldViewProjection.M31 +
inverseWorldViewProjection.M41;
result.Y =
result.X * inverseWorldViewProjection.M12 +
result.Y * inverseWorldViewProjection.M22 +
result.Z * inverseWorldViewProjection.M32 +
inverseWorldViewProjection.M42;
result.Z =
result.X * inverseWorldViewProjection.M13 +
result.Y * inverseWorldViewProjection.M23 +
result.Z * inverseWorldViewProjection.M33 +
inverseWorldViewProjection.M43;
result.W =
result.X * inverseWorldViewProjection.M14 +
result.Y * inverseWorldViewProjection.M24 +
result.Z * inverseWorldViewProjection.M34 +
inverseWorldViewProjection.M44;
result /= result.W;
return new Vector3(result.X, result.Y, result.Z);
}
#endregion
#endregion
#region Swizzle