Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
fe3105350This file is pinned to the selected release. Download the original to open it in your design tool.
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Text;
namespace SharpGLTF.Transforms
{
/// <summary>
/// Utility class to calculate camera matrices
/// </summary>
/// <see href="https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#projection-matrices"/>
public static class Projection
{
/// <summary>
/// Calculates an orthographic projection matrix.
/// </summary>
/// <param name="xmag">Magnification in the X axis.</param>
/// <param name="ymag">Magnification in the Y axis.</param>
/// <param name="znear">Distance to the near pane in the Z axis.</param>
/// <param name="zfar">Distance to the far plane in the Z axis.</param>
/// <returns>A projection matrix</returns>
public static Matrix4x4 CreateOrthographicMatrix(float xmag, float ymag, float znear, float zfar)
{
Guard.MustBeGreaterThanOrEqualTo(znear, 0, nameof(znear));
Guard.MustBeGreaterThanOrEqualTo(zfar, 0, nameof(zfar));
Guard.MustBeGreaterThan(zfar, znear, nameof(zfar));
Guard.MustBeLessThan(zfar, float.PositiveInfinity, nameof(zfar));
var d = znear - zfar;
var x = 1 / xmag;
var y = 1 / ymag;
var z = 2 / d;
var w = (zfar + znear) / d;
return new Matrix4x4
(
x, 0, 0, 0,
0, y, 0, 0,
0, 0, z, w,
0, 0, 0, 1
);
}
/// <summary>
/// Calculates a perspective projection matrix.
/// </summary>
/// <param name="aspectRatio">The aspect ratio between horizontal and vertical. (optional)</param>
/// <param name="yfov">The vertical field of view, in radians.</param>
/// <param name="znear">Distance to the near pane in the Z axis.</param>
/// <param name="zfar">Distance to the far plane in the Z axis. Optionally, this value can be positive infinity</param>
/// <returns>A projection matrix</returns>
public static Matrix4x4 CreatePerspectiveMatrix(float aspectRatio, float yfov, float znear, float zfar = float.PositiveInfinity)
{
Guard.MustBeGreaterThan(aspectRatio, 0, nameof(aspectRatio));
Guard.MustBeGreaterThan(yfov, 0, nameof(yfov));
Guard.MustBeLessThan(yfov, (float)Math.PI, nameof(yfov));
Guard.MustBeGreaterThanOrEqualTo(znear, 0, nameof(znear));
Guard.MustBeGreaterThanOrEqualTo(zfar, 0, nameof(zfar));
Guard.MustBeGreaterThan(zfar, znear, nameof(zfar));
var v = (float)Math.Tan(0.5 * yfov);
var h = aspectRatio * v;
var x = 1 / h;
var y = 1 / v;
var z = -1f;
var w = -2 * znear;
if (!float.IsPositiveInfinity(zfar))
{
var d = znear - zfar;
z = (zfar + znear) / d;
w = (2f * zfar * znear) / d;
}
return new Matrix4x4
(
x, 0, 0, 0,
0, y, 0, 0,
0, 0, z, w,
0, 0, -1, 0
);
}
}
}