diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
index 371729ebec6..8b1b73fcc32 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs
@@ -3,6 +3,14 @@ using System.Runtime.InteropServices;
namespace Godot
{
+ ///
+ /// A 4x4 matrix used for 3D projective transformations. It can represent transformations such as
+ /// translation, rotation, scaling, shearing, and perspective division. It consists of four
+ /// columns.
+ /// For purely linear transformations (translation, rotation, and scale), it is recommended to use
+ /// , as it is more performant and has a lower memory footprint.
+ /// Used internally as 's projection matrix.
+ ///
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Projection : IEquatable
@@ -59,48 +67,107 @@ namespace Godot
public Vector4 w;
///
- /// Constructs a projection from 4 vectors (matrix columns).
+ /// Access whole columns in the form of .
///
- /// The X column, or column index 0.
- /// The Y column, or column index 1.
- /// The Z column, or column index 2.
- /// The W column, or column index 3.
- public Projection(Vector4 x, Vector4 y, Vector4 z, Vector4 w)
+ /// Which column vector.
+ ///
+ /// is not 0, 1, 2 or 3.
+ ///
+ public Vector4 this[int column]
{
- this.x = x;
- this.y = y;
- this.z = z;
- this.w = w;
+ readonly get
+ {
+ switch (column)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ case 3:
+ return w;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(column));
+ }
+ }
+ set
+ {
+ switch (column)
+ {
+ case 0:
+ x = value;
+ return;
+ case 1:
+ y = value;
+ return;
+ case 2:
+ z = value;
+ return;
+ case 3:
+ w = value;
+ return;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(column));
+ }
+ }
}
///
- /// Constructs a new from a .
+ /// Access single values.
///
- /// The .
- public Projection(Transform3D transform)
+ /// Which column vector.
+ /// Which row of the column.
+ ///
+ /// or are not 0, 1, 2 or 3.
+ ///
+ public real_t this[int column, int row]
{
- x = new Vector4(transform.basis.Row0.x, transform.basis.Row1.x, transform.basis.Row2.x, 0);
- y = new Vector4(transform.basis.Row0.y, transform.basis.Row1.y, transform.basis.Row2.y, 0);
- z = new Vector4(transform.basis.Row0.z, transform.basis.Row1.z, transform.basis.Row2.z, 0);
- w = new Vector4(transform.origin.x, transform.origin.y, transform.origin.z, 1);
+ readonly get
+ {
+ switch (column)
+ {
+ case 0:
+ return x[row];
+ case 1:
+ return y[row];
+ case 2:
+ return z[row];
+ case 3:
+ return w[row];
+ default:
+ throw new ArgumentOutOfRangeException(nameof(column));
+ }
+ }
+ set
+ {
+ switch (column)
+ {
+ case 0:
+ x[row] = value;
+ return;
+ case 1:
+ y[row] = value;
+ return;
+ case 2:
+ z[row] = value;
+ return;
+ case 3:
+ w[row] = value;
+ return;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(column));
+ }
+ }
}
///
- /// Constructs a new from the .
+ /// Creates a new that projects positions from a depth range of
+ /// -1 to 1 to one that ranges from 0 to 1, and flips the projected
+ /// positions vertically, according to .
///
- /// The .
- public static explicit operator Transform3D(Projection proj)
- {
- return new Transform3D(
- new Basis(
- new Vector3(proj.x.x, proj.x.y, proj.x.z),
- new Vector3(proj.y.x, proj.y.y, proj.y.z),
- new Vector3(proj.z.x, proj.z.y, proj.z.z)
- ),
- new Vector3(proj.w.x, proj.w.y, proj.w.z)
- );
- }
-
+ /// If the projection should be flipped vertically.
+ /// The created projection.
public static Projection CreateDepthCorrection(bool flipY)
{
return new Projection(
@@ -111,6 +178,12 @@ namespace Godot
);
}
+ ///
+ /// Creates a new that scales a given projection to fit around
+ /// a given in projection space.
+ ///
+ /// The AABB to fit the projection around.
+ /// The created projection.
public static Projection CreateFitAabb(AABB aabb)
{
Vector3 min = aabb.Position;
@@ -124,6 +197,25 @@ namespace Godot
);
}
+ ///
+ /// Creates a new for projecting positions onto a head-mounted display with
+ /// the given X:Y aspect ratio, distance between eyes, display width, distance to lens, oversampling factor,
+ /// and depth clipping planes.
+ /// creates the projection for the left eye when set to 1,
+ /// or the right eye when set to 2.
+ ///
+ ///
+ /// The eye to create the projection for.
+ /// The left eye when set to 1, the right eye when set to 2.
+ ///
+ /// The aspect ratio.
+ /// The distance between the eyes.
+ /// The display width.
+ /// The distance to the lens.
+ /// The oversampling factor.
+ /// The near clipping distance.
+ /// The far clipping distance.
+ /// The created projection.
public static Projection CreateForHmd(int eye, real_t aspect, real_t intraocularDist, real_t displayWidth, real_t displayToLens, real_t oversample, real_t zNear, real_t zFar)
{
real_t f1 = (intraocularDist * (real_t)0.5) / displayToLens;
@@ -148,6 +240,17 @@ namespace Godot
}
}
+ ///
+ /// Creates a new that projects positions in a frustum with
+ /// the given clipping planes.
+ ///
+ /// The left clipping distance.
+ /// The right clipping distance.
+ /// The bottom clipping distance.
+ /// The top clipping distance.
+ /// The near clipping distance.
+ /// The far clipping distance.
+ /// The created projection.
public static Projection CreateFrustum(real_t left, real_t right, real_t bottom, real_t top, real_t near, real_t far)
{
if (right <= left)
@@ -179,6 +282,18 @@ namespace Godot
);
}
+ ///
+ /// Creates a new that projects positions in a frustum with
+ /// the given size, X:Y aspect ratio, offset, and clipping planes.
+ /// determines whether the projection's field of view is flipped over its diagonal.
+ ///
+ /// The frustum size.
+ /// The aspect ratio.
+ /// The offset to apply.
+ /// The near clipping distance.
+ /// The far clipping distance.
+ /// If the field of view is flipped over the projection's diagonal.
+ /// The created projection.
public static Projection CreateFrustumAspect(real_t size, real_t aspect, Vector2 offset, real_t near, real_t far, bool flipFov)
{
if (!flipFov)
@@ -188,6 +303,11 @@ namespace Godot
return CreateFrustum(-size / 2 + offset.x, +size / 2 + offset.x, -size / aspect / 2 + offset.y, +size / aspect / 2 + offset.y, near, far);
}
+ ///
+ /// Creates a new that projects positions into the given .
+ ///
+ /// The Rect2 to project positions into.
+ /// The created projection.
public static Projection CreateLightAtlasRect(Rect2 rect)
{
return new Projection(
@@ -198,6 +318,17 @@ namespace Godot
);
}
+ ///
+ /// Creates a new that projects positions using an orthogonal projection with
+ /// the given clipping planes.
+ ///
+ /// The left clipping distance.
+ /// The right clipping distance.
+ /// The bottom clipping distance.
+ /// The top clipping distance.
+ /// The near clipping distance.
+ /// The far clipping distance.
+ /// The created projection.
public static Projection CreateOrthogonal(real_t left, real_t right, real_t bottom, real_t top, real_t zNear, real_t zFar)
{
Projection proj = Projection.Identity;
@@ -211,6 +342,17 @@ namespace Godot
return proj;
}
+ ///
+ /// Creates a new that projects positions using an orthogonal projection with
+ /// the given size, X:Y aspect ratio, and clipping planes.
+ /// determines whether the projection's field of view is flipped over its diagonal.
+ ///
+ /// The frustum size.
+ /// The aspect ratio.
+ /// The near clipping distance.
+ /// The far clipping distance.
+ /// If the field of view is flipped over the projection's diagonal.
+ /// The created projection.
public static Projection CreateOrthogonalAspect(real_t size, real_t aspect, real_t zNear, real_t zFar, bool flipFov)
{
if (!flipFov)
@@ -220,6 +362,17 @@ namespace Godot
return CreateOrthogonal(-size / 2, +size / 2, -size / aspect / 2, +size / aspect / 2, zNear, zFar);
}
+ ///
+ /// Creates a new that projects positions using a perspective projection with
+ /// the given Y-axis field of view (in degrees), X:Y aspect ratio, and clipping planes.
+ /// determines whether the projection's field of view is flipped over its diagonal.
+ ///
+ /// The vertical field of view (in degrees).
+ /// The aspect ratio.
+ /// The near clipping distance.
+ /// The far clipping distance.
+ /// If the field of view is flipped over the projection's diagonal.
+ /// The created projection.
public static Projection CreatePerspective(real_t fovyDegrees, real_t aspect, real_t zNear, real_t zFar, bool flipFov)
{
if (flipFov)
@@ -249,6 +402,27 @@ namespace Godot
return proj;
}
+ ///
+ /// Creates a new that projects positions using a perspective projection with
+ /// the given Y-axis field of view (in degrees), X:Y aspect ratio, and clipping distances.
+ /// The projection is adjusted for a head-mounted display with the given distance between eyes and distance
+ /// to a point that can be focused on.
+ /// creates the projection for the left eye when set to 1,
+ /// or the right eye when set to 2.
+ /// determines whether the projection's field of view is flipped over its diagonal.
+ ///
+ /// The vertical field of view (in degrees).
+ /// The aspect ratio.
+ /// The near clipping distance.
+ /// The far clipping distance.
+ /// If the field of view is flipped over the projection's diagonal.
+ ///
+ /// The eye to create the projection for.
+ /// The left eye when set to 1, the right eye when set to 2.
+ ///
+ /// The distance between the eyes.
+ /// The distance to a point of convergence that can be focused on.
+ /// The created projection.
public static Projection CreatePerspectiveHmd(real_t fovyDegrees, real_t aspect, real_t zNear, real_t zFar, bool flipFov, int eye, real_t intraocularDist, real_t convergenceDist)
{
if (flipFov)
@@ -286,6 +460,13 @@ namespace Godot
return proj * cm;
}
+ ///
+ /// Returns a scalar value that is the signed factor by which areas are scaled by this matrix.
+ /// If the sign is negative, the matrix flips the orientation of the area.
+ /// The determinant can be used to calculate the invertibility of a matrix or solve linear systems
+ /// of equations involving the matrix, among other applications.
+ ///
+ /// The determinant calculated from this projection.
public readonly real_t Determinant()
{
return x.w * y.z * z.y * w.x - x.z * y.w * z.y * w.x -
@@ -302,12 +483,20 @@ namespace Godot
x.y * y.x * z.z * w.w + x.x * y.y * z.z * w.w;
}
+ ///
+ /// Returns the X:Y aspect ratio of this 's viewport.
+ ///
+ /// The aspect ratio from this projection's viewport.
public readonly real_t GetAspect()
{
Vector2 vpHe = GetViewportHalfExtents();
return vpHe.x / vpHe.y;
}
+ ///
+ /// Returns the horizontal field of view of the projection (in degrees).
+ ///
+ /// The horizontal field of view of this projection.
public readonly real_t GetFov()
{
Plane rightPlane = new Plane(x.w - x.x, y.w - y.x, z.w - z.x, -w.w + w.x).Normalized();
@@ -322,11 +511,22 @@ namespace Godot
}
}
+ ///
+ /// Returns the vertical field of view of the projection (in degrees) associated with
+ /// the given horizontal field of view (in degrees) and aspect ratio.
+ ///
+ /// The horizontal field of view (in degrees).
+ /// The aspect ratio.
+ /// The vertical field of view of this projection.
public static real_t GetFovy(real_t fovx, real_t aspect)
{
return Mathf.RadToDeg(Mathf.Atan(aspect * Mathf.Tan(Mathf.DegToRad(fovx) * (real_t)0.5)) * (real_t)2.0);
}
+ ///
+ /// Returns the factor by which the visible level of detail is scaled by this .
+ ///
+ /// The level of detail factor for this projection.
public readonly real_t GetLodMultiplier()
{
if (IsOrthogonal())
@@ -341,6 +541,12 @@ namespace Godot
}
}
+ ///
+ /// Returns the number of pixels with the given pixel width displayed per meter, after
+ /// this is applied.
+ ///
+ /// The width for each pixel (in meters).
+ /// The number of pixels per meter.
public readonly int GetPixelsPerMeter(int forPixelWidth)
{
Vector3 result = this * new Vector3(1, 0, -1);
@@ -348,6 +554,15 @@ namespace Godot
return (int)((result.x * (real_t)0.5 + (real_t)0.5) * forPixelWidth);
}
+ ///
+ /// Returns the clipping plane of this whose index is given
+ /// by .
+ /// should be equal to one of ,
+ /// , , ,
+ /// , or .
+ ///
+ /// The kind of clipping plane to get from the projection.
+ /// The clipping plane of this projection.
public readonly Plane GetProjectionPlane(Planes plane)
{
Plane newPlane = plane switch
@@ -364,28 +579,49 @@ namespace Godot
return newPlane.Normalized();
}
+ ///
+ /// Returns the dimensions of the far clipping plane of the projection, divided by two.
+ ///
+ /// The half extents for this projection's far plane.
public readonly Vector2 GetFarPlaneHalfExtents()
{
var res = GetProjectionPlane(Planes.Far).Intersect3(GetProjectionPlane(Planes.Right), GetProjectionPlane(Planes.Top));
return new Vector2(res.Value.x, res.Value.y);
}
+ ///
+ /// Returns the dimensions of the viewport plane that this
+ /// projects positions onto, divided by two.
+ ///
+ /// The half extents for this projection's viewport plane.
public readonly Vector2 GetViewportHalfExtents()
{
var res = GetProjectionPlane(Planes.Near).Intersect3(GetProjectionPlane(Planes.Right), GetProjectionPlane(Planes.Top));
return new Vector2(res.Value.x, res.Value.y);
}
+ ///
+ /// Returns the distance for this beyond which positions are clipped.
+ ///
+ /// The distance beyond which positions are clipped.
public readonly real_t GetZFar()
{
return GetProjectionPlane(Planes.Far).D;
}
+ ///
+ /// Returns the distance for this before which positions are clipped.
+ ///
+ /// The distance before which positions are clipped.
public readonly real_t GetZNear()
{
return -GetProjectionPlane(Planes.Near).D;
}
+ ///
+ /// Returns a copy of this with the signs of the values of the Y column flipped.
+ ///
+ /// The flipped projection.
public readonly Projection FlippedY()
{
Projection proj = this;
@@ -393,6 +629,13 @@ namespace Godot
return proj;
}
+ ///
+ /// Returns a with the near clipping distance adjusted to be
+ /// .
+ /// Note: The original must be a perspective projection.
+ ///
+ /// The near clipping distance to adjust the projection to.
+ /// The adjusted projection.
public readonly Projection PerspectiveZNearAdjusted(real_t newZNear)
{
Projection proj = this;
@@ -404,6 +647,12 @@ namespace Godot
return proj;
}
+ ///
+ /// Returns a with the X and Y values from the given
+ /// added to the first and second values of the final column respectively.
+ ///
+ /// The offset to apply to the projection.
+ /// The offseted projection.
public readonly Projection JitterOffseted(Vector2 offset)
{
Projection proj = this;
@@ -412,6 +661,11 @@ namespace Godot
return proj;
}
+ ///
+ /// Returns a that performs the inverse of this 's
+ /// projective transformation.
+ ///
+ /// The inverted projection.
public readonly Projection Inverse()
{
Projection proj = this;
@@ -535,11 +789,70 @@ namespace Godot
return proj;
}
+ ///
+ /// Returns if this performs an orthogonal projection.
+ ///
+ /// If the projection performs an orthogonal projection.
public readonly bool IsOrthogonal()
{
return w.w == (real_t)1.0;
}
+ // Constants
+ private static readonly Projection _zero = new Projection(
+ new Vector4(0, 0, 0, 0),
+ new Vector4(0, 0, 0, 0),
+ new Vector4(0, 0, 0, 0),
+ new Vector4(0, 0, 0, 0)
+ );
+ private static readonly Projection _identity = new Projection(
+ new Vector4(1, 0, 0, 0),
+ new Vector4(0, 1, 0, 0),
+ new Vector4(0, 0, 1, 0),
+ new Vector4(0, 0, 0, 1)
+ );
+
+ ///
+ /// Zero projection, a projection with all components set to 0.
+ ///
+ /// Equivalent to new Projection(Vector4.Zero, Vector4.Zero, Vector4.Zero, Vector4.Zero).
+ public static Projection Zero { get { return _zero; } }
+
+ ///
+ /// The identity projection, with no distortion applied.
+ /// This is used as a replacement for Projection() in GDScript.
+ /// Do not use new Projection() with no arguments in C#, because it sets all values to zero.
+ ///
+ /// Equivalent to new Projection(new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1)).
+ public static Projection Identity { get { return _identity; } }
+
+ ///
+ /// Constructs a projection from 4 vectors (matrix columns).
+ ///
+ /// The X column, or column index 0.
+ /// The Y column, or column index 1.
+ /// The Z column, or column index 2.
+ /// The W column, or column index 3.
+ public Projection(Vector4 x, Vector4 y, Vector4 z, Vector4 w)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+
+ ///
+ /// Constructs a new from a .
+ ///
+ /// The .
+ public Projection(Transform3D transform)
+ {
+ x = new Vector4(transform.basis.Row0.x, transform.basis.Row1.x, transform.basis.Row2.x, 0);
+ y = new Vector4(transform.basis.Row0.y, transform.basis.Row1.y, transform.basis.Row2.y, 0);
+ z = new Vector4(transform.basis.Row0.z, transform.basis.Row1.z, transform.basis.Row2.z, 0);
+ w = new Vector4(transform.origin.x, transform.origin.y, transform.origin.z, 1);
+ }
+
///
/// Composes these two projections by multiplying them
/// together. This has the effect of applying the right
@@ -646,127 +959,41 @@ namespace Godot
}
///
- /// Access whole columns in the form of .
+ /// Constructs a new from the .
///
- /// Which column vector.
- ///
- /// is not 0, 1, 2 or 3.
- ///
- public Vector4 this[int column]
+ /// The .
+ public static explicit operator Transform3D(Projection proj)
{
- readonly get
- {
- switch (column)
- {
- case 0:
- return x;
- case 1:
- return y;
- case 2:
- return z;
- case 3:
- return w;
- default:
- throw new ArgumentOutOfRangeException(nameof(column));
- }
- }
- set
- {
- switch (column)
- {
- case 0:
- x = value;
- return;
- case 1:
- y = value;
- return;
- case 2:
- z = value;
- return;
- case 3:
- w = value;
- return;
- default:
- throw new ArgumentOutOfRangeException(nameof(column));
- }
- }
+ return new Transform3D(
+ new Basis(
+ new Vector3(proj.x.x, proj.x.y, proj.x.z),
+ new Vector3(proj.y.x, proj.y.y, proj.y.z),
+ new Vector3(proj.z.x, proj.z.y, proj.z.z)
+ ),
+ new Vector3(proj.w.x, proj.w.y, proj.w.z)
+ );
}
///
- /// Access single values.
+ /// Returns if the projection is exactly equal
+ /// to the given object ().
///
- /// Which column vector.
- /// Which row of the column.
- ///
- /// or are not 0, 1, 2 or 3.
- ///
- public real_t this[int column, int row]
+ /// The object to compare with.
+ /// Whether or not the vector and the object are equal.
+ public override readonly bool Equals(object obj)
{
- readonly get
- {
- switch (column)
- {
- case 0:
- return x[row];
- case 1:
- return y[row];
- case 2:
- return z[row];
- case 3:
- return w[row];
- default:
- throw new ArgumentOutOfRangeException(nameof(column));
- }
- }
- set
- {
- switch (column)
- {
- case 0:
- x[row] = value;
- return;
- case 1:
- y[row] = value;
- return;
- case 2:
- z[row] = value;
- return;
- case 3:
- w[row] = value;
- return;
- default:
- throw new ArgumentOutOfRangeException(nameof(column));
- }
- }
+ return obj is Projection other && Equals(other);
}
- // Constants
- private static readonly Projection _zero = new Projection(
- new Vector4(0, 0, 0, 0),
- new Vector4(0, 0, 0, 0),
- new Vector4(0, 0, 0, 0),
- new Vector4(0, 0, 0, 0)
- );
- private static readonly Projection _identity = new Projection(
- new Vector4(1, 0, 0, 0),
- new Vector4(0, 1, 0, 0),
- new Vector4(0, 0, 1, 0),
- new Vector4(0, 0, 0, 1)
- );
-
///
- /// Zero projection, a projection with all components set to 0.
+ /// Returns if the projections are exactly equal.
///
- /// Equivalent to new Projection(Vector4.Zero, Vector4.Zero, Vector4.Zero, Vector4.Zero).
- public static Projection Zero { get { return _zero; } }
-
- ///
- /// The identity projection, with no distortion applied.
- /// This is used as a replacement for Projection() in GDScript.
- /// Do not use new Projection() with no arguments in C#, because it sets all values to zero.
- ///
- /// Equivalent to new Projection(new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1)).
- public static Projection Identity { get { return _identity; } }
+ /// The other projection.
+ /// Whether or not the projections are exactly equal.
+ public readonly bool Equals(Projection other)
+ {
+ return x == other.x && y == other.y && z == other.z && w == other.w;
+ }
///
/// Serves as the hash function for .
@@ -797,26 +1024,5 @@ namespace Godot
$"{z.x.ToString(format)}, {z.y.ToString(format)}, {z.z.ToString(format)}, {z.w.ToString(format)}\n" +
$"{w.x.ToString(format)}, {w.y.ToString(format)}, {w.z.ToString(format)}, {w.w.ToString(format)}\n";
}
-
- ///
- /// Returns if the projection is exactly equal
- /// to the given object ().
- ///
- /// The object to compare with.
- /// Whether or not the vector and the object are equal.
- public override readonly bool Equals(object obj)
- {
- return obj is Projection other && Equals(other);
- }
-
- ///
- /// Returns if the projections are exactly equal.
- ///
- /// The other projection.
- /// Whether or not the projections are exactly equal.
- public readonly bool Equals(Projection other)
- {
- return x == other.x && y == other.y && z == other.z && w == other.w;
- }
}
}