diff options
Diffstat (limited to 'modules/mono/glue')
-rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs | 43 | ||||
-rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs | 88 | ||||
-rw-r--r-- | modules/mono/glue/GodotSharp/GodotSharp/Variant.cs | 56 |
3 files changed, 123 insertions, 64 deletions
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs index 9c3bc51c44..bb1d6e1661 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs @@ -4,21 +4,6 @@ using System.Runtime.InteropServices; namespace Godot { /// <summary> - /// Specifies which order Euler angle rotations should be in. - /// When composing, the order is the same as the letters. When decomposing, - /// the order is reversed (ex: YXZ decomposes Z first, then X, and Y last). - /// </summary> - public enum EulerOrder - { - XYZ, - XZY, - YXZ, - YZX, - ZXY, - ZYX - }; - - /// <summary> /// 3×3 matrix used for 3D rotation and scale. /// Almost always used as an orthogonal basis for a Transform. /// @@ -270,11 +255,11 @@ namespace Godot /// </summary> /// <param name="order">The Euler order to use. By default, use YXZ order (most common).</param> /// <returns>A <see cref="Vector3"/> representing the basis rotation in Euler angles.</returns> - public Vector3 GetEuler(EulerOrder order = EulerOrder.YXZ) + public Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz) { switch (order) { - case EulerOrder.XYZ: + case EulerOrder.Xyz: { // Euler angles in XYZ convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix @@ -318,7 +303,7 @@ namespace Godot } return euler; } - case EulerOrder.XZY: + case EulerOrder.Xzy: { // Euler angles in XZY convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix @@ -353,7 +338,7 @@ namespace Godot } return euler; } - case EulerOrder.YXZ: + case EulerOrder.Yxz: { // Euler angles in YXZ convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix @@ -398,7 +383,7 @@ namespace Godot return euler; } - case EulerOrder.YZX: + case EulerOrder.Yzx: { // Euler angles in YZX convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix @@ -433,7 +418,7 @@ namespace Godot } return euler; } - case EulerOrder.ZXY: + case EulerOrder.Zxy: { // Euler angles in ZXY convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix @@ -468,7 +453,7 @@ namespace Godot } return euler; } - case EulerOrder.ZYX: + case EulerOrder.Zyx: { // Euler angles in ZYX convention. // See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix @@ -998,7 +983,7 @@ namespace Godot /// </summary> /// <param name="euler">The Euler angles to use.</param> /// <param name="order">The order to compose the Euler angles.</param> - public static Basis FromEuler(Vector3 euler, EulerOrder order = EulerOrder.YXZ) + public static Basis FromEuler(Vector3 euler, EulerOrder order = EulerOrder.Yxz) { real_t c, s; @@ -1016,17 +1001,17 @@ namespace Godot switch (order) { - case EulerOrder.XYZ: + case EulerOrder.Xyz: return xmat * ymat * zmat; - case EulerOrder.XZY: + case EulerOrder.Xzy: return xmat * zmat * ymat; - case EulerOrder.YXZ: + case EulerOrder.Yxz: return ymat * xmat * zmat; - case EulerOrder.YZX: + case EulerOrder.Yzx: return ymat * zmat * xmat; - case EulerOrder.ZXY: + case EulerOrder.Zxy: return zmat * xmat * ymat; - case EulerOrder.ZYX: + case EulerOrder.Zyx: return zmat * ymat * xmat; default: throw new ArgumentOutOfRangeException(nameof(order)); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs index d459fe8c96..f01f0be985 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs @@ -312,7 +312,7 @@ namespace Godot /// the rotation angles in the format (X angle, Y angle, Z angle). /// </summary> /// <returns>The Euler angle representation of this quaternion.</returns> - public Vector3 GetEuler() + public Vector3 GetEuler(EulerOrder order = EulerOrder.Yxz) { #if DEBUG if (!IsNormalized()) @@ -321,7 +321,7 @@ namespace Godot } #endif var basis = new Basis(this); - return basis.GetEuler(); + return basis.GetEuler(order); } /// <summary> @@ -507,35 +507,6 @@ namespace Godot } /// <summary> - /// Constructs a <see cref="Quaternion"/> that will perform a rotation specified by - /// Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last), - /// given in the vector format as (X angle, Y angle, Z angle). - /// </summary> - /// <param name="eulerYXZ">Euler angles that the quaternion will be rotated by.</param> - public Quaternion(Vector3 eulerYXZ) - { - real_t halfA1 = eulerYXZ.y * 0.5f; - real_t halfA2 = eulerYXZ.x * 0.5f; - real_t halfA3 = eulerYXZ.z * 0.5f; - - // R = Y(a1).X(a2).Z(a3) convention for Euler angles. - // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6) - // a3 is the angle of the first rotation, following the notation in this reference. - - real_t cosA1 = Mathf.Cos(halfA1); - real_t sinA1 = Mathf.Sin(halfA1); - real_t cosA2 = Mathf.Cos(halfA2); - real_t sinA2 = Mathf.Sin(halfA2); - real_t cosA3 = Mathf.Cos(halfA3); - real_t sinA3 = Mathf.Sin(halfA3); - - x = (sinA1 * cosA2 * sinA3) + (cosA1 * sinA2 * cosA3); - y = (sinA1 * cosA2 * cosA3) - (cosA1 * sinA2 * sinA3); - z = (cosA1 * cosA2 * sinA3) - (sinA1 * sinA2 * cosA3); - w = (sinA1 * sinA2 * sinA3) + (cosA1 * cosA2 * cosA3); - } - - /// <summary> /// Constructs a <see cref="Quaternion"/> that will rotate around the given axis /// by the specified angle. The axis must be a normalized vector. /// </summary> @@ -572,6 +543,61 @@ namespace Godot } } + public Quaternion(Vector3 arcFrom, Vector3 arcTo) + { + Vector3 c = arcFrom.Cross(arcTo); + real_t d = arcFrom.Dot(arcTo); + + if (d < -1.0f + Mathf.Epsilon) + { + x = 0f; + y = 1f; + z = 0f; + w = 0f; + } + else + { + real_t s = Mathf.Sqrt((1.0f + d) * 2.0f); + real_t rs = 1.0f / s; + + x = c.x * rs; + y = c.y * rs; + z = c.z * rs; + w = s * 0.5f; + } + } + + /// <summary> + /// Constructs a <see cref="Quaternion"/> that will perform a rotation specified by + /// Euler angles (in the YXZ convention: when decomposing, first Z, then X, and Y last), + /// given in the vector format as (X angle, Y angle, Z angle). + /// </summary> + /// <param name="eulerYXZ">Euler angles that the quaternion will be rotated by.</param> + public static Quaternion FromEuler(Vector3 eulerYXZ) + { + real_t halfA1 = eulerYXZ.y * 0.5f; + real_t halfA2 = eulerYXZ.x * 0.5f; + real_t halfA3 = eulerYXZ.z * 0.5f; + + // R = Y(a1).X(a2).Z(a3) convention for Euler angles. + // Conversion to quaternion as listed in https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770024290.pdf (page A-6) + // a3 is the angle of the first rotation, following the notation in this reference. + + real_t cosA1 = Mathf.Cos(halfA1); + real_t sinA1 = Mathf.Sin(halfA1); + real_t cosA2 = Mathf.Cos(halfA2); + real_t sinA2 = Mathf.Sin(halfA2); + real_t cosA3 = Mathf.Cos(halfA3); + real_t sinA3 = Mathf.Sin(halfA3); + + return new Quaternion( + (sinA1 * cosA2 * sinA3) + (cosA1 * sinA2 * cosA3), + (sinA1 * cosA2 * cosA3) - (cosA1 * sinA2 * sinA3), + (cosA1 * cosA2 * sinA3) - (sinA1 * sinA2 * cosA3), + (sinA1 * sinA2 * sinA3) + (cosA1 * cosA2 * cosA3) + ); + } + /// <summary> /// Composes these two quaternions by multiplying them together. /// This has the effect of rotating the second quaternion diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Variant.cs b/modules/mono/glue/GodotSharp/GodotSharp/Variant.cs index 1f37694995..d354509dbf 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Variant.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Variant.cs @@ -766,6 +766,58 @@ public partial struct Variant : IDisposable CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSignalInfo(from)); [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(byte[] from) => + (Variant)from.AsSpan(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(int[] from) => + (Variant)from.AsSpan(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(long[] from) => + (Variant)from.AsSpan(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(float[] from) => + (Variant)from.AsSpan(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(double[] from) => + (Variant)from.AsSpan(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(string[] from) => + (Variant)from.AsSpan(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Vector2[] from) => + (Variant)from.AsSpan(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Vector3[] from) => + (Variant)from.AsSpan(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Color[] from) => + (Variant)from.AsSpan(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(Godot.Object[] from) => + CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemArrayOfGodotObject(from)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(StringName[] from) => + (Variant)from.AsSpan(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(NodePath[] from) => + (Variant)from.AsSpan(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Variant(RID[] from) => + (Variant)from.AsSpan(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator Variant(Span<byte> from) => CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedByteArray(from)); @@ -802,10 +854,6 @@ public partial struct Variant : IDisposable CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromPackedColorArray(from)); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator Variant(Godot.Object[] from) => - CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemArrayOfGodotObject(from)); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator Variant(Span<StringName> from) => CreateTakingOwnershipOfDisposableValue(VariantUtils.CreateFromSystemArrayOfStringName(from)); |