diff options
author | Raul Santos <raulsntos@gmail.com> | 2022-08-01 04:06:35 +0200 |
---|---|---|
committer | Raul Santos <raulsntos@gmail.com> | 2022-08-22 21:11:24 +0200 |
commit | 0b8b733d77ba9acca2f0b864d020732e2a265edc (patch) | |
tree | 4b43888786a0d56f85ed5f97b11b7ec7bfd6d62d /modules | |
parent | 8a1e5980116355024cd7a7ce0c15db7d4ecb200a (diff) |
C#: Replace `Xform` and `XformInv` with `*` operator
- In cases where both `Xform`/`XformInv` and the `*` operator were
implemented the `Xform`/`XformInv` methods were removed in favor of the
`*` operator.
- In cases where the `Xform`/`XformInv` existed but not the `*` operator,
the `Xform`/`XformInv` methods were replaced with the `*` operator.
- In cases where no method existed, a new `*` operator has been
implemented to support the same operations that are supported in GDScript.
- Fixes the `Transform.Xform` and `Transform.XformInv` with `Rect2`
implementation to use a zero `Rect2` size to start expanding from
(which is how it's implemented in C++).
Diffstat (limited to 'modules')
7 files changed, 292 insertions, 181 deletions
diff --git a/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs b/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs index 188bbb775c..069908c426 100644 --- a/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs +++ b/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs @@ -26,7 +26,7 @@ public partial class _CLASS_ : _BASE_ // Get the input direction and handle the movement/deceleration. // As good practice, you should replace UI actions with custom gameplay actions. Vector2 inputDir = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down"); - Vector3 direction = Transform.basis.Xform(new Vector3(inputDir.x, 0, inputDir.y)).Normalized(); + Vector3 direction = (Transform.basis * new Vector3(inputDir.x, 0, inputDir.y)).Normalized(); if (direction != Vector3.Zero) { velocity.x = direction.x * Speed; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs index 646681a9b1..4cb9bf5758 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs @@ -618,41 +618,6 @@ namespace Godot return tr; } - /// <summary> - /// Returns a vector transformed (multiplied) by the basis matrix. - /// </summary> - /// <seealso cref="XformInv(Vector3)"/> - /// <param name="v">A vector to transform.</param> - /// <returns>The transformed vector.</returns> - public Vector3 Xform(Vector3 v) - { - return new Vector3 - ( - Row0.Dot(v), - Row1.Dot(v), - Row2.Dot(v) - ); - } - - /// <summary> - /// Returns a vector transformed (multiplied) by the transposed basis matrix. - /// - /// Note: This results in a multiplication by the inverse of the - /// basis matrix only if it represents a rotation-reflection. - /// </summary> - /// <seealso cref="Xform(Vector3)"/> - /// <param name="v">A vector to inversely transform.</param> - /// <returns>The inversely transformed vector.</returns> - public Vector3 XformInv(Vector3 v) - { - return new Vector3 - ( - Row0[0] * v.x + Row1[0] * v.y + Row2[0] * v.z, - Row0[1] * v.x + Row1[1] * v.y + Row2[1] * v.z, - Row0[2] * v.x + Row1[2] * v.y + Row2[2] * v.z - ); - } - private static readonly Basis[] _orthoBases = { new Basis(1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f), new Basis(0f, -1f, 0f, 1f, 0f, 0f, 0f, 0f, 1f), @@ -857,6 +822,41 @@ namespace Godot } /// <summary> + /// Returns a Vector3 transformed (multiplied) by the basis matrix. + /// </summary> + /// <param name="basis">The basis matrix transformation to apply.</param> + /// <param name="vector">A Vector3 to transform.</param> + /// <returns>The transformed Vector3.</returns> + public static Vector3 operator *(Basis basis, Vector3 vector) + { + return new Vector3 + ( + basis.Row0.Dot(vector), + basis.Row1.Dot(vector), + basis.Row2.Dot(vector) + ); + } + + /// <summary> + /// Returns a Vector3 transformed (multiplied) by the transposed basis matrix. + /// + /// Note: This results in a multiplication by the inverse of the + /// basis matrix only if it represents a rotation-reflection. + /// </summary> + /// <param name="vector">A Vector3 to inversely transform.</param> + /// <param name="basis">The basis matrix transformation to apply.</param> + /// <returns>The inversely transformed vector.</returns> + public static Vector3 operator *(Vector3 vector, Basis basis) + { + return new Vector3 + ( + basis.Row0[0] * vector.x + basis.Row1[0] * vector.y + basis.Row2[0] * vector.z, + basis.Row0[1] * vector.x + basis.Row1[1] * vector.y + basis.Row2[1] * vector.z, + basis.Row0[2] * vector.x + basis.Row1[2] * vector.y + basis.Row2[2] * vector.z + ); + } + + /// <summary> /// Returns <see langword="true"/> if the basis matrices are exactly /// equal. Note: Due to floating-point precision errors, consider using /// <see cref="IsEqualApprox"/> instead, which is more reliable. diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs index df16fe5718..3dcf433c4a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs @@ -355,7 +355,7 @@ namespace Godot public int GetPixelsPerMeter(int forPixelWidth) { - Vector3 result = Xform(new Vector3(1, 0, -1)); + Vector3 result = this * new Vector3(1, 0, -1); return (int)((result.x * (real_t)0.5 + (real_t)0.5) * forPixelWidth); } @@ -588,22 +588,54 @@ namespace Godot } /// <summary> - /// Returns a vector transformed (multiplied) by this projection. + /// Returns a Vector4 transformed (multiplied) by the projection. /// </summary> /// <param name="proj">The projection to apply.</param> - /// <param name="v">A vector to transform.</param> - /// <returns>The transformed vector.</returns> - public static Vector4 operator *(Projection proj, Vector4 v) + /// <param name="vector">A Vector4 to transform.</param> + /// <returns>The transformed Vector4.</returns> + public static Vector4 operator *(Projection proj, Vector4 vector) { return new Vector4( - proj.x.x * v.x + proj.y.x * v.y + proj.z.x * v.z + proj.w.x * v.w, - proj.x.y * v.x + proj.y.y * v.y + proj.z.y * v.z + proj.w.y * v.w, - proj.x.z * v.x + proj.y.z * v.y + proj.z.z * v.z + proj.w.z * v.w, - proj.x.w * v.x + proj.y.w * v.y + proj.z.w * v.z + proj.w.w * v.w + proj.x.x * vector.x + proj.y.x * vector.y + proj.z.x * vector.z + proj.w.x * vector.w, + proj.x.y * vector.x + proj.y.y * vector.y + proj.z.y * vector.z + proj.w.y * vector.w, + proj.x.z * vector.x + proj.y.z * vector.y + proj.z.z * vector.z + proj.w.z * vector.w, + proj.x.w * vector.x + proj.y.w * vector.y + proj.z.w * vector.z + proj.w.w * vector.w ); } /// <summary> + /// Returns a Vector4 transformed (multiplied) by the inverse projection. + /// </summary> + /// <param name="proj">The projection to apply.</param> + /// <param name="vector">A Vector4 to transform.</param> + /// <returns>The inversely transformed Vector4.</returns> + public static Vector4 operator *(Vector4 vector, Projection proj) + { + return new Vector4( + proj.x.x * vector.x + proj.x.y * vector.y + proj.x.z * vector.z + proj.x.w * vector.w, + proj.y.x * vector.x + proj.y.y * vector.y + proj.y.z * vector.z + proj.y.w * vector.w, + proj.z.x * vector.x + proj.z.y * vector.y + proj.z.z * vector.z + proj.z.w * vector.w, + proj.w.x * vector.x + proj.w.y * vector.y + proj.w.z * vector.z + proj.w.w * vector.w + ); + } + + /// <summary> + /// Returns a Vector3 transformed (multiplied) by the projection. + /// </summary> + /// <param name="proj">The projection to apply.</param> + /// <param name="vector">A Vector3 to transform.</param> + /// <returns>The transformed Vector3.</returns> + public static Vector3 operator *(Projection proj, Vector3 vector) + { + Vector3 ret = new Vector3( + proj.x.x * vector.x + proj.y.x * vector.y + proj.z.x * vector.z + proj.w.x, + proj.x.y * vector.x + proj.y.y * vector.y + proj.z.y * vector.z + proj.w.y, + proj.x.z * vector.x + proj.y.z * vector.y + proj.z.z * vector.z + proj.w.z + ); + return ret / (proj.x.w * vector.x + proj.y.w * vector.y + proj.z.w * vector.z + proj.w.w); + } + + /// <summary> /// Returns <see langword="true"/> if the projections are exactly equal. /// </summary> /// <param name="left">The left projection.</param> @@ -714,21 +746,6 @@ namespace Godot } } - /// <summary> - /// Returns a vector transformed (multiplied) by this projection. - /// </summary> - /// <param name="v">A vector to transform.</param> - /// <returns>The transformed vector.</returns> - private Vector3 Xform(Vector3 v) - { - Vector3 ret = new Vector3( - x.x * v.x + y.x * v.y + z.x * v.z + w.x, - x.y * v.x + y.y * v.y + z.y * v.z + w.y, - x.z * v.x + y.z * v.y + z.z * v.z + w.z - ); - return ret / (x.w * v.x + y.w * v.y + z.w * v.z + w.w); - } - // Constants private static readonly Projection _zero = new Projection( new Vector4(0, 0, 0, 0), diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs index 90e4e3b41e..4260ff22e7 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs @@ -313,24 +313,6 @@ namespace Godot ); } - /// <summary> - /// Returns a vector transformed (multiplied) by this quaternion. - /// </summary> - /// <param name="v">A vector to transform.</param> - /// <returns>The transformed vector.</returns> - public Vector3 Xform(Vector3 v) - { -#if DEBUG - if (!IsNormalized()) - { - throw new InvalidOperationException("Quaternion is not normalized"); - } -#endif - var u = new Vector3(x, y, z); - Vector3 uv = u.Cross(v); - return v + (((uv * w) + u.Cross(uv)) * 2); - } - // Constants private static readonly Quaternion _identity = new Quaternion(0, 0, 0, 1); @@ -461,6 +443,36 @@ namespace Godot } /// <summary> + /// Returns a Vector3 rotated (multiplied) by the quaternion. + /// </summary> + /// <param name="quaternion">The quaternion to rotate by.</param> + /// <param name="vector">A Vector3 to transform.</param> + /// <returns>The rotated Vector3.</returns> + public static Vector3 operator *(Quaternion quaternion, Vector3 vector) + { +#if DEBUG + if (!quaternion.IsNormalized()) + { + throw new InvalidOperationException("Quaternion is not normalized"); + } +#endif + var u = new Vector3(quaternion.x, quaternion.y, quaternion.z); + Vector3 uv = u.Cross(vector); + return vector + (((uv * quaternion.w) + u.Cross(uv)) * 2); + } + + /// <summary> + /// Returns a Vector3 rotated (multiplied) by the inverse quaternion. + /// </summary> + /// <param name="vector">A Vector3 to inversely rotate.</param> + /// <param name="quaternion">The quaternion to rotate by.</param> + /// <returns>The inversely rotated Vector3.</returns> + public static Vector3 operator *(Vector3 vector, Quaternion quaternion) + { + return quaternion.Inverse() * vector; + } + + /// <summary> /// Adds each component of the left <see cref="Quaternion"/> /// to the right <see cref="Quaternion"/>. This operation is not /// meaningful on its own, but it can be used as a part of a @@ -503,38 +515,6 @@ namespace Godot } /// <summary> - /// Rotates (multiplies) the <see cref="Vector3"/> - /// by the given <see cref="Quaternion"/>. - /// </summary> - /// <param name="quat">The quaternion to rotate by.</param> - /// <param name="vec">The vector to rotate.</param> - /// <returns>The rotated vector.</returns> - public static Vector3 operator *(Quaternion quat, Vector3 vec) - { -#if DEBUG - if (!quat.IsNormalized()) - { - throw new InvalidOperationException("Quaternion is not normalized."); - } -#endif - var u = new Vector3(quat.x, quat.y, quat.z); - Vector3 uv = u.Cross(vec); - return vec + (((uv * quat.w) + u.Cross(uv)) * 2); - } - - /// <summary> - /// Inversely rotates (multiplies) the <see cref="Vector3"/> - /// by the given <see cref="Quaternion"/>. - /// </summary> - /// <param name="vec">The vector to rotate.</param> - /// <param name="quat">The quaternion to rotate by.</param> - /// <returns>The inversely rotated vector.</returns> - public static Vector3 operator *(Vector3 vec, Quaternion quat) - { - return quat.Inverse() * vec; - } - - /// <summary> /// Multiplies each component of the <see cref="Quaternion"/> /// by the given <see cref="real_t"/>. This operation is not /// meaningful on its own, but it can be used as a part of a diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs index ab2c0cd785..70cf8bbe22 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs @@ -384,31 +384,6 @@ namespace Godot return copy; } - /// <summary> - /// Returns a vector transformed (multiplied) by this transformation matrix. - /// </summary> - /// <seealso cref="XformInv(Vector2)"/> - /// <param name="v">A vector to transform.</param> - /// <returns>The transformed vector.</returns> - [Obsolete("Xform is deprecated. Use the multiplication operator (Transform2D * Vector2) instead.")] - public Vector2 Xform(Vector2 v) - { - return new Vector2(Tdotx(v), Tdoty(v)) + origin; - } - - /// <summary> - /// Returns a vector transformed (multiplied) by the inverse transformation matrix. - /// </summary> - /// <seealso cref="Xform(Vector2)"/> - /// <param name="v">A vector to inversely transform.</param> - /// <returns>The inversely transformed vector.</returns> - [Obsolete("XformInv is deprecated. Use the multiplication operator (Vector2 * Transform2D) instead.")] - public Vector2 XformInv(Vector2 v) - { - Vector2 vInv = v - origin; - return new Vector2(x.Dot(vInv), y.Dot(vInv)); - } - // Constants private static readonly Transform2D _identity = new Transform2D(1, 0, 0, 1, 0, 0); private static readonly Transform2D _flipX = new Transform2D(-1, 0, 0, 1, 0, 0); @@ -502,7 +477,7 @@ namespace Godot } /// <summary> - /// Returns a Vector2 transformed (multiplied) by transformation matrix. + /// Returns a Vector2 transformed (multiplied) by the transformation matrix. /// </summary> /// <param name="transform">The transformation to apply.</param> /// <param name="vector">A Vector2 to transform.</param> @@ -525,7 +500,7 @@ namespace Godot } /// <summary> - /// Returns a Rect2 transformed (multiplied) by transformation matrix. + /// Returns a Rect2 transformed (multiplied) by the transformation matrix. /// </summary> /// <param name="transform">The transformation to apply.</param> /// <param name="rect">A Rect2 to transform.</param> @@ -536,7 +511,7 @@ namespace Godot Vector2 toX = transform.x * rect.Size.x; Vector2 toY = transform.y * rect.Size.y; - return new Rect2(pos, rect.Size).Expand(pos + toX).Expand(pos + toY).Expand(pos + toX + toY); + return new Rect2(pos, new Vector2()).Expand(pos + toX).Expand(pos + toY).Expand(pos + toX + toY); } /// <summary> @@ -552,11 +527,11 @@ namespace Godot Vector2 to2 = new Vector2(rect.Position.x + rect.Size.x, rect.Position.y + rect.Size.y) * transform; Vector2 to3 = new Vector2(rect.Position.x + rect.Size.x, rect.Position.y) * transform; - return new Rect2(pos, rect.Size).Expand(to1).Expand(to2).Expand(to3); + return new Rect2(pos, new Vector2()).Expand(to1).Expand(to2).Expand(to3); } /// <summary> - /// Returns a copy of the given Vector2[] transformed (multiplied) by transformation matrix. + /// Returns a copy of the given Vector2[] transformed (multiplied) by the transformation matrix. /// </summary> /// <param name="transform">The transformation to apply.</param> /// <param name="array">A Vector2[] to transform.</param> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs index 810f55e150..5481225e3f 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs @@ -108,7 +108,7 @@ namespace Godot public Transform3D AffineInverse() { Basis basisInv = basis.Inverse(); - return new Transform3D(basisInv, basisInv.Xform(-origin)); + return new Transform3D(basisInv, basisInv * -origin); } /// <summary> @@ -147,7 +147,7 @@ namespace Godot public Transform3D Inverse() { Basis basisTr = basis.Transposed(); - return new Transform3D(basisTr, basisTr.Xform(-origin)); + return new Transform3D(basisTr, basisTr * -origin); } /// <summary> @@ -286,43 +286,6 @@ namespace Godot )); } - /// <summary> - /// Returns a vector transformed (multiplied) by this transformation matrix. - /// </summary> - /// <seealso cref="XformInv(Vector3)"/> - /// <param name="v">A vector to transform.</param> - /// <returns>The transformed vector.</returns> - public Vector3 Xform(Vector3 v) - { - return new Vector3 - ( - basis.Row0.Dot(v) + origin.x, - basis.Row1.Dot(v) + origin.y, - basis.Row2.Dot(v) + origin.z - ); - } - - /// <summary> - /// Returns a vector transformed (multiplied) by the transposed transformation matrix. - /// - /// Note: This results in a multiplication by the inverse of the - /// transformation matrix only if it represents a rotation-reflection. - /// </summary> - /// <seealso cref="Xform(Vector3)"/> - /// <param name="v">A vector to inversely transform.</param> - /// <returns>The inversely transformed vector.</returns> - public Vector3 XformInv(Vector3 v) - { - Vector3 vInv = v - origin; - - return new Vector3 - ( - (basis.Row0[0] * vInv.x) + (basis.Row1[0] * vInv.y) + (basis.Row2[0] * vInv.z), - (basis.Row0[1] * vInv.x) + (basis.Row1[1] * vInv.y) + (basis.Row2[1] * vInv.z), - (basis.Row0[2] * vInv.x) + (basis.Row1[2] * vInv.y) + (basis.Row2[2] * vInv.z) - ); - } - // Constants private static readonly Transform3D _identity = new Transform3D(Basis.Identity, Vector3.Zero); private static readonly Transform3D _flipX = new Transform3D(new Basis(-1, 0, 0, 0, 1, 0, 0, 0, 1), Vector3.Zero); @@ -399,12 +362,188 @@ namespace Godot /// <returns>The composed transform.</returns> public static Transform3D operator *(Transform3D left, Transform3D right) { - left.origin = left.Xform(right.origin); + left.origin = left * right.origin; left.basis *= right.basis; return left; } /// <summary> + /// Returns a Vector3 transformed (multiplied) by the transformation matrix. + /// </summary> + /// <param name="transform">The transformation to apply.</param> + /// <param name="vector">A Vector3 to transform.</param> + /// <returns>The transformed Vector3.</returns> + public static Vector3 operator *(Transform3D transform, Vector3 vector) + { + return new Vector3 + ( + transform.basis.Row0.Dot(vector) + transform.origin.x, + transform.basis.Row1.Dot(vector) + transform.origin.y, + transform.basis.Row2.Dot(vector) + transform.origin.z + ); + } + + /// <summary> + /// Returns a Vector3 transformed (multiplied) by the transposed transformation matrix. + /// + /// Note: This results in a multiplication by the inverse of the + /// transformation matrix only if it represents a rotation-reflection. + /// </summary> + /// <param name="vector">A Vector3 to inversely transform.</param> + /// <param name="transform">The transformation to apply.</param> + /// <returns>The inversely transformed Vector3.</returns> + public static Vector3 operator *(Vector3 vector, Transform3D transform) + { + Vector3 vInv = vector - transform.origin; + + return new Vector3 + ( + (transform.basis.Row0[0] * vInv.x) + (transform.basis.Row1[0] * vInv.y) + (transform.basis.Row2[0] * vInv.z), + (transform.basis.Row0[1] * vInv.x) + (transform.basis.Row1[1] * vInv.y) + (transform.basis.Row2[1] * vInv.z), + (transform.basis.Row0[2] * vInv.x) + (transform.basis.Row1[2] * vInv.y) + (transform.basis.Row2[2] * vInv.z) + ); + } + + /// <summary> + /// Returns an AABB transformed (multiplied) by the transformation matrix. + /// </summary> + /// <param name="transform">The transformation to apply.</param> + /// <param name="aabb">An AABB to transform.</param> + /// <returns>The transformed AABB.</returns> + public static AABB operator *(Transform3D transform, AABB aabb) + { + Vector3 min = aabb.Position; + Vector3 max = aabb.Position + aabb.Size; + + Vector3 tmin = transform.origin; + Vector3 tmax = transform.origin; + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + { + real_t e = transform.basis[i][j] * min[j]; + real_t f = transform.basis[i][j] * max[j]; + if (e < f) + { + tmin[i] += e; + tmax[i] += f; + } + else + { + tmin[i] += f; + tmax[i] += e; + } + } + } + + return new AABB(tmin, tmax - tmin); + } + + /// <summary> + /// Returns an AABB transformed (multiplied) by the inverse transformation matrix. + /// </summary> + /// <param name="aabb">An AABB to inversely transform.</param> + /// <param name="transform">The transformation to apply.</param> + /// <returns>The inversely transformed AABB.</returns> + public static AABB operator *(AABB aabb, Transform3D transform) + { + Vector3 pos = new Vector3(aabb.Position.x + aabb.Size.x, aabb.Position.y + aabb.Size.y, aabb.Position.z + aabb.Size.z) * transform; + Vector3 to1 = new Vector3(aabb.Position.x + aabb.Size.x, aabb.Position.y + aabb.Size.y, aabb.Position.z) * transform; + Vector3 to2 = new Vector3(aabb.Position.x + aabb.Size.x, aabb.Position.y, aabb.Position.z + aabb.Size.z) * transform; + Vector3 to3 = new Vector3(aabb.Position.x + aabb.Size.x, aabb.Position.y, aabb.Position.z) * transform; + Vector3 to4 = new Vector3(aabb.Position.x, aabb.Position.y + aabb.Size.y, aabb.Position.z + aabb.Size.z) * transform; + Vector3 to5 = new Vector3(aabb.Position.x, aabb.Position.y + aabb.Size.y, aabb.Position.z) * transform; + Vector3 to6 = new Vector3(aabb.Position.x, aabb.Position.y, aabb.Position.z + aabb.Size.z) * transform; + Vector3 to7 = new Vector3(aabb.Position.x, aabb.Position.y, aabb.Position.z) * transform; + + return new AABB(pos, new Vector3()).Expand(to1).Expand(to2).Expand(to3).Expand(to4).Expand(to5).Expand(to6).Expand(to7); + } + + /// <summary> + /// Returns a Plane transformed (multiplied) by the transformation matrix. + /// </summary> + /// <param name="transform">The transformation to apply.</param> + /// <param name="plane">A Plane to transform.</param> + /// <returns>The transformed Plane.</returns> + public static Plane operator *(Transform3D transform, Plane plane) + { + Basis bInvTrans = transform.basis.Inverse().Transposed(); + + // Transform a single point on the plane. + Vector3 point = transform * (plane.Normal * plane.D); + + // Use inverse transpose for correct normals with non-uniform scaling. + Vector3 normal = (bInvTrans * plane.Normal).Normalized(); + + real_t d = normal.Dot(point); + return new Plane(normal, d); + } + + /// <summary> + /// Returns a Plane transformed (multiplied) by the inverse transformation matrix. + /// </summary> + /// <param name="plane">A Plane to inversely transform.</param> + /// <param name="transform">The transformation to apply.</param> + /// <returns>The inversely transformed Plane.</returns> + public static Plane operator *(Plane plane, Transform3D transform) + { + Transform3D tInv = transform.AffineInverse(); + Basis bTrans = transform.basis.Transposed(); + + // Transform a single point on the plane. + Vector3 point = tInv * (plane.Normal * plane.D); + + // Note that instead of precalculating the transpose, an alternative + // would be to use the transpose for the basis transform. + // However that would be less SIMD friendly (requiring a swizzle). + // So the cost is one extra precalced value in the calling code. + // This is probably worth it, as this could be used in bottleneck areas. And + // where it is not a bottleneck, the non-fast method is fine. + + // Use transpose for correct normals with non-uniform scaling. + Vector3 normal = (bTrans * plane.Normal).Normalized(); + + real_t d = normal.Dot(point); + return new Plane(normal, d); + } + + /// <summary> + /// Returns a copy of the given Vector3[] transformed (multiplied) by the transformation matrix. + /// </summary> + /// <param name="transform">The transformation to apply.</param> + /// <param name="array">A Vector3[] to transform.</param> + /// <returns>The transformed copy of the Vector3[].</returns> + public static Vector3[] operator *(Transform3D transform, Vector3[] array) + { + Vector3[] newArray = new Vector3[array.Length]; + + for (int i = 0; i < array.Length; i++) + { + newArray[i] = transform * array[i]; + } + + return newArray; + } + + /// <summary> + /// Returns a copy of the given Vector3[] transformed (multiplied) by the inverse transformation matrix. + /// </summary> + /// <param name="array">A Vector3[] to inversely transform.</param> + /// <param name="transform">The transformation to apply.</param> + /// <returns>The inversely transformed copy of the Vector3[].</returns> + public static Vector3[] operator *(Vector3[] array, Transform3D transform) + { + Vector3[] newArray = new Vector3[array.Length]; + + for (int i = 0; i < array.Length; i++) + { + newArray[i] = array[i] * transform; + } + + return newArray; + } + + /// <summary> /// Returns <see langword="true"/> if the transforms are exactly equal. /// Note: Due to floating-point precision errors, consider using /// <see cref="IsEqualApprox"/> instead, which is more reliable. diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index e796d2f20f..2643f352d7 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -518,7 +518,7 @@ namespace Godot throw new ArgumentException("Argument is not normalized", nameof(axis)); } #endif - return new Basis(axis, angle).Xform(this); + return new Basis(axis, angle) * this; } /// <summary> |