Browse Source

C#: Add Projection documentation

- Add documentation to Projection type
- Reorder Projection members to be consistent with other C# types
Raul Santos 2 years ago
parent
commit
ca5c51f47e
1 changed files with 368 additions and 162 deletions
  1. 368 162
      modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs

+ 368 - 162
modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs

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