using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Microsoft.Xna.Framework;
namespace MonoGame.Extended;
///
/// Represents a 3x2 matrix using floating point values for each component that can store two dimensional translation,
/// scale, and rotation information for a right-handed coordinate system.
///
///
///
/// Matrices use a row vector layout in the XNA / MonoGame Framework but, in general, matrices can be either
/// have a row vector or column vector layout. Row vector matrices view vectors as a row from left to right,
/// while column vector matrices view vectors as a column from top to bottom. For example, the
/// corresponds to the fields and .
///
///
/// The fields see M13 and M23 always have a value of 0.0f, and thus are removed from
/// the to reduce its memory footprint. Same is true for the field M33, except
/// it always has a value of 1.0f.
///
///
[DebuggerDisplay($"{nameof(DebugDisplayString)},nq")]
public struct Matrix3x2 : IEquatable
{
/// The first element of the first row.
/// Represents the scaling factor on the x-axis or a combination of scaling and rotation.
public float M11;
/// The second element of the first row.
/// Represents the shearing factor on the y-axis or a combination of shearing and rotation.
public float M12;
/// The first element of the second row.
/// Represents the shearing factor on the x-axis or a combination of shear and rotation.
public float M21;
/// The second element of the second row.
/// Represents the scaling factor on the y-axis or a combination of scale and rotation.
public float M22;
/// The first element of the third row.
/// Represents the translation on the x-axis
public float M31;
/// The second element of the third row.
/// Represents the translation on the y-axis
public float M32;
///
/// Gets or Sets the vector formed by the first row of this
///
///
///
/// The component of the vector represents the scaling factor on the x-axis or a
/// combination of scaling and rotation.
///
///
/// The component of the vector represents the shearing factor on the y-axis or a
/// combination of shearing and rotation.
///
///
public Vector2 X
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
readonly get => Unsafe.As(ref Unsafe.AsRef(in M11));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set => Unsafe.As(ref M11) = value;
}
///
/// Gets the vector formed by the second row of this
///
///
///
/// The component of the vector represents the shearing factor on the x-axis or a
/// combination of shearing and rotation.
///
///
/// The component of the vector represents the scaling factor on the y-axis or a
/// combination of scaling and rotation.
///
///
public Vector2 Y
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
readonly get => Unsafe.As(ref Unsafe.AsRef(in M21));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set => Unsafe.As(ref M21) = value;
}
///
/// Gets or Sets the vector formed by the third row of this
///
///
///
/// The component of the vector represents the translation on the x-axis.
///
///
/// The component of the vector represents the translation on the y-axis.
///
///
public Vector2 Z
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
readonly get => Unsafe.As(ref Unsafe.AsRef(in M31));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set => Unsafe.As(ref M31) = value;
}
///
/// Gets the multiplicative identity matrix.
///
///
/// The first row of the identity matrix is equal to
/// The second row of the identity matrix is equal to
/// The third row of the identity matrix is equal to
///
public static readonly Matrix3x2 Identity = new Matrix3x2(Vector2.UnitX, Vector2.UnitY, Vector2.Zero);
///
/// Gets the translation component of this .
///
///
/// The translation is equal to the third row vector composed of the and
/// values.
///
[Obsolete("Use Decompose method. This property will be removed in 4.0")]
public readonly Vector2 Translation
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => Z;
}
///
/// Gets the rotation component of this .
///
///
/// The rotation is equal to the arctangent of the and .
/// Math.Atan2(M21, M11);
///
[Obsolete("Use Decompose method. This property will be removed in 4.0")]
public readonly float Rotation
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (float)Math.Atan2(M21, M11);
}
///
/// Gets the scale component of this .
///
///
/// The scale is equal to equal to the square root of the sum of the squares of matrix elements, with sign
/// adjustment.
///
[Obsolete("Use Decompose method. This property will be removed in 4.0")]
public readonly Vector2 Scale
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
var xSign = Math.Sign((M11 * M11) + (M21 * M21)) < 0 ? -1 : 1;
var ySign = Math.Sign((M11 * M12) + (M22 * M22)) < 0 ? -1 : 1;
Vector2 scale;
scale.X = xSign * (float)Math.Sqrt((M11 * M11) + (M21 * M21));
scale.Y = ySign * (float)Math.Sqrt((M11 * M12) + (M22 * M22));
return scale;
}
}
///
/// Creates a 3x2 matrix from the specified components.
///
/// The value to assign to the first element of the first row.
/// The value to assign to the second element of the first row.
/// The value to assign to the first element of the second row.
/// The value to assign to the second element of the second row.
/// The value to assign to the first element of the third row.
/// The value to assign to the second element of the third row.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Matrix3x2(float m11, float m12,
float m21, float m22,
float m31, float m32)
{
M11 = m11;
M12 = m12;
M21 = m21;
M22 = m22;
M31 = m31;
M32 = m32;
}
///
/// Creates a new 3x2 matrix from the specified components.
///
/// The value to assign to the elements of the first row.
/// The value to assign to the elements of the second row.
/// The value to assign to the elements of the third row.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Matrix3x2(Vector2 x, Vector2 y, Vector2 z)
: this(x.X, x.Y, y.X, y.Y, z.X, z.Y) { }
///
/// Transforms the given vector by this
///
/// The vector to transform.
/// The result of the transformation.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector2 Transform(Vector2 vector) => Transform(vector.X, vector.Y);
///
/// Transforms the given vector by this
///
/// The vector to transform.
///
/// When this method returns, contains the result of the transformation. This parameter is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Transform(Vector2 vector, out Vector2 result) => Transform(vector.X, vector.Y, out result);
///
/// Transforms a vector with the specified x- and y-coordinate component values by this
///
/// The x-coordinate component value of the vector to transform.
/// The y-coordinate component value of the vector to transform.
/// The result of the transformation.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector2 Transform(in float x, in float y)
{
Vector2 result;
Transform(x, y, out result);
return result;
}
///
/// Transforms a vector with the specified x- and y-coordinate component values by this
///
/// The x-coordinate component value of the vector to transform.
/// The y-coordinate component value of the vector to transform.
///
/// When this method returns, contains the result of the transformation. This parameter is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Transform(in float x, in float y, out Vector2 result)
{
result.X = (x * M11) + (y * M21) + M31;
result.Y = (x * M12) + (y * M22) + M32;
}
///
/// Transforms a vector with the specified x- and y-coordinate component values by this
///
/// The x-coordinate component value of the vector to transform.
/// The y-coordinate component value of the vector to transform.
/// When this method returns, contains the result of the transformation.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Transform(in float x, in float y, ref Vector3 result)
{
result.X = (x * M11) + (y * M21) + M31;
result.Y = (x * M12) + (y * M22) + M32;
}
///
/// Calculates the determinant of this .
///
///
/// The determinant is calculated by expanding this matrix with a third column whose values are (0, 0, 1).
///
/// The determinant of this .
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Determinant() => (M11 * M22) - (M12 * M21);
///
/// Deconstructs this into its translation, rotation, and scale component representations.
///
///
/// When this method returns, contains the translation component of this . This parameter is
/// passed uninitialized.
///
///
/// When this method returns, contains the rotation component of this . This parameter is
/// passed uninitialized.
///
///
/// When this method returns, contains the scale component of this . This parameter is
/// passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Decompose(out Vector2 translation, out float rotation, out Vector2 scale)
{
translation.X = M31;
translation.Y = M32;
rotation = (float)Math.Atan2(M21, M11);
var x = M11 * M11 + M21 * M21;
var y = M12 * M12 + M22 * M22;
var xSign = Math.Sign(x) < 0 ? -1 : 1;
var ySign = Math.Sign(y) < 0 ? -1 : 1;
scale.X = xSign * (float)Math.Sqrt(x);
scale.Y = ySign * (float)Math.Sqrt(y);
}
///
/// Creates a new value for 2D translation, rotation, and scale.
///
/// Rotation is performed along the z-axis.
/// The amount to translate the matrix by on the x- and y-axis.
/// The amount to rotate, in radians, the matrix along the z-axis.
/// The amount to scale the matrix along the x- and y-axis.
/// The origin point at which to scale and rotate the matrix around.
/// The resulting value created by this method.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 CreateFrom(Vector2 position, in float rotation, Vector2? scale, Vector2? origin)
{
CreateFrom(position, rotation, scale, origin, out Matrix3x2 result);
return result;
}
///
/// Creates a new value for 2D translation, rotation, and scale.
///
/// Rotation is performed along the z-axis.
/// The amount to translate the matrix by on the x- and y-axis.
/// The amount to rotate, in radians, the matrix along the z-axis.
/// The amount to scale the matrix along the x- and y-axis.
/// The origin point at which to scale and rotate the matrix around.
///
/// When this method returns, contains the resulting value for 2D translation rotation, and
/// scale. This parameter is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CreateFrom(Vector2 position, in float rotation, Vector2? scale, Vector2? origin, out Matrix3x2 result)
{
result = Identity;
if (origin.HasValue)
{
result.Z = -origin.Value;
}
if (scale.HasValue)
{
CreateScale(scale.Value, out Matrix3x2 scaleMatrix);
Multiply(result, scaleMatrix, out result);
}
if (rotation != 0.0f)
{
CreateRotationZ(-rotation, out Matrix3x2 rotationMatrix);
Multiply(result, rotationMatrix, out result);
}
CreateTranslation(position, out Matrix3x2 translationMatrix);
Multiply(result, translationMatrix, out result);
}
///
/// Creates a value for 2D rotation.
///
/// Rotation is performed along the z-axis.
/// The mount to rotate, in radians, the matrix along the z-axis.
/// The resulting value created by this method.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 CreateRotationZ(in float radians)
{
CreateRotationZ(radians, out Matrix3x2 result);
return result;
}
///
/// Creates a value for 2D rotation.
///
/// Rotation is performed along the z-axis.
/// The mount to rotate, in radians, the matrix along the z-axis.
///
/// When this method returns, contains the resulting value for 2D rotation. This parameter
/// is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CreateRotationZ(in float radians, out Matrix3x2 result)
{
var cos = (float)Math.Cos(radians);
var sin = (float)Math.Sin(radians);
result.M11 = cos;
result.M12 = sin;
result.M21 = -sin;
result.M22 = cos;
result.M31 = 0;
result.M32 = 0;
}
///
/// Creates a value for 2D scaling.
///
/// The amount to scale the matrix along the x- and y-axis.
/// The value created by this method.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 CreateScale(in float scale)
{
CreateScale(scale, scale, out Matrix3x2 result);
return result;
}
///
/// Creates a value for 2D scaling.
///
/// The amount to scale the matrix along the x- and y-axis.
///
/// When this method returns, contains the resulting value for 2D scaling created. This
/// parameter is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CreateScale(in float scale, out Matrix3x2 result) => CreateScale(scale, scale, out result);
///
/// Creates a value for 2D scaling.
///
/// A vector that represents the x- and y-axis scale factors.
/// The value created by this method.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 CreateScale(Vector2 scale)
{
CreateScale(scale.X, scale.Y, out Matrix3x2 result);
return result;
}
///
/// Creates a value for 2D scaling.
///
/// A vector that represents the x- and y-axis scale factors.
///
/// When this method returns, contains the resulting value for 2D scaling. This parameter
/// is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CreateScale(in Vector2 scale, out Matrix3x2 result) =>
CreateScale(scale.X, scale.Y, out result);
///
/// Creates a value for 2D scaling.
///
/// The scale factor for the x-axis.
/// The scale factor for the y-axis.
/// The value created by this method.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 CreateScale(in float xScale, in float yScale)
{
CreateScale(xScale, yScale, out Matrix3x2 result);
return result;
}
///
/// Creates a value for 2D scaling.
///
/// The scale factor for the x-axis.
/// The scale factor for the y-axis.
///
/// When this method returns, contains the resulting value for 2D scaling. This parameter
/// is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CreateScale(in float xScale, in float yScale, out Matrix3x2 result)
{
result.M11 = xScale;
result.M12 = 0;
result.M21 = 0;
result.M22 = yScale;
result.M31 = 0;
result.M32 = 0;
}
///
/// Creates a value for 2D translation.
///
/// The translation vector
/// The resulting value for 2D translation.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 CreateTranslation(Vector2 vector) => CreateTranslation(vector.X, vector.Y);
///
/// Creates a for 2D translation.
///
/// The translation vector
///
/// When this method returns, contains the resulting value for 2D translation. This
/// parameter is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CreateTranslation(Vector2 vector, out Matrix3x2 result) =>
CreateTranslation(vector.X, vector.Y, out result);
///
/// Creates a value for 2D translation.
///
/// The X-coordinate of the translation vector.
/// The Y-coordinate of the translation vector.
/// The resulting value for 2D translation.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 CreateTranslation(in float x, in float y)
{
CreateTranslation(x, y, out Matrix3x2 result);
return result;
}
///
/// Creates a value for 2D translation.
///
/// The X-coordinate of the translation vector.
/// The Y-coordinate of the translation vector.
///
/// When this method returns, contains the resulting value. This parameter is passed
/// uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CreateTranslation(in float x, in float y, out Matrix3x2 result)
{
result.M11 = 1;
result.M12 = 0;
result.M21 = 0;
result.M22 = 1;
result.M31 = x;
result.M32 = y;
}
///
/// Inverts the provided
///
/// The value to invert.
/// The result of inverting the .
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 Invert(Matrix3x2 matrix)
{
Invert(ref matrix);
return matrix;
}
///
/// Inverts the provided value.
///
/// The value to invert.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Invert(ref Matrix3x2 matrix)
{
var det = 1.0f / matrix.Determinant();
if (float.IsInfinity(det)) // Det(M) = 0
{
matrix = Identity;
return;
}
// The new 3x2 matrix is the first and second column of the inverse of the 3x3 matrix given by adding the third column (0, 0, 1) to the input matrix
matrix = new(
matrix.M22 * det,
-matrix.M12 * det,
-matrix.M21 * det,
matrix.M11 * det,
(matrix.M32 * matrix.M21 - matrix.M31 * matrix.M22) * det,
(matrix.M31 * matrix.M12 - matrix.M32 * matrix.M11) * det
);
}
///
/// Adds the elements of two values.
///
///
/// This operation is performed component-wise.
///
/// The first value.
/// The second value.
/// The result of the addition.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 Add(Matrix3x2 left, Matrix3x2 right) => left + right;
///
/// Adds the elements of two values.
///
///
/// This operation is performed component-wise.
///
/// The first value.
/// The second value.
///
/// When this method returns, contains the result of the addition. This parameter is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Add(Matrix3x2 left, Matrix3x2 right, out Matrix3x2 result) => result = Add(left, right);
///
/// Subtracts the elements of a from the corresponding elements of another
/// .
///
///
/// This operation is performed component-wise.
///
/// The first value.
/// The second value.
/// The result of the subtraction.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 Subtract(Matrix3x2 left, Matrix3x2 right) => left - right;
///
/// Subtracts the elements of a from the corresponding elements of another
/// .
///
///
/// This operation is performed component-wise.
///
/// The first value.
/// The second value.
///
/// When this method returns, contains the result of the subtraction. This method is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Subtract(Matrix3x2 left, Matrix3x2 right, out Matrix3x2 result) => result = Subtract(left, right);
///
/// Multiplies the elements of a by the elements of another .
///
///
/// This operation performs matrix multiplication.
///
/// The first value.
/// The second value.
/// The result of the multiplication.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 Multiply(Matrix3x2 left, Matrix3x2 right) => left * right;
///
/// Multiplies the elements of a by the elements of another .
///
///
/// This operation performs matrix multiplication.
///
/// The first value.
/// The second value.
///
/// When this method returns, contains the result of the multiplication. This parameter is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Multiply(Matrix3x2 left, Matrix3x2 right, out Matrix3x2 result) => result = left * right;
///
/// Multiplies the elements of a by the elements of another .
///
///
/// This operation performs matrix multiplication.
///
/// The first value.
/// The second value.
///
/// When this method returns, contains the result of the multiplication. This parameter is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Multiply(ref Matrix3x2 left, ref Matrix3x2 right, out Matrix3x2 result) => result = left * right;
///
/// Multiplies the elements of a by a scalar value.
///
///
/// This operation is performed component-wise.
///
/// The source .
/// The scalar value.
/// The result of the multiplication.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 Multiply(Matrix3x2 matrix, in float scalar) => matrix * scalar;
///
/// Multiplies the elements of a by a scalar value.
///
///
/// This operation is performed component-wise.
///
/// The source .
/// The scalar value.
///
/// When this method returns, contains the result of the multiplication. This parameter is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Multiply(Matrix3x2 matrix, in float scalar, out Matrix3x2 result) => result = Multiply(matrix, scalar);
///
/// Divides the elements of a by the elements of another .
///
///
/// This operation is performed component-wise.
///
/// The first value.
/// The second value.
/// The result of the division.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 Divide(Matrix3x2 left, Matrix3x2 right) => left / right;
///
/// Divides the elements of a by the elements of another .
///
///
/// This operation is performed component-wise.
///
/// The first value.
/// The second value.
///
/// When this method returns, contains the result of the division. This parameter is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Divide(Matrix3x2 left, Matrix3x2 right, out Matrix3x2 result) => result = Divide(left, right);
///
/// Divides the elements of a by a scalar value.
///
///
/// This operation is performed component-wise.
///
/// The source .
/// The scalar value.
/// The result of the division.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 Divide(Matrix3x2 matrix, in float scalar) => matrix / scalar;
///
/// Divides the elements of a by a scalar value.
///
///
/// This operation is performed component-wise.
///
/// The source .
/// The scalar value.
///
/// When this method returns, contains the result of the division. This parameter is passed uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Divide(Matrix3x2 matrix, in float scalar, out Matrix3x2 result) => result = Divide(matrix, scalar);
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override readonly bool Equals([NotNullWhen(true)] object obj) => obj is Matrix3x2 other && Equals(other);
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly bool Equals(Matrix3x2 other) => this == other;
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override readonly int GetHashCode() => HashCode.Combine(X, Y, Z);
///
/// Converts the specified value into a value.
///
///
/// The third row of the resulting is set to (0, 0, 1, 0), and the fourth row is set to
/// (, , 0, 1).
///
/// The resulting value.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Matrix ToMatrix() => ToMatrix(0.0f);
///
/// Converts the specified value into a value.
///
///
/// The third row of the resulting is set to (0, 0, 1, 0), and the fourth row is set to
/// (, , , 1).
///
///
/// The depth value to be used for the third row of the resulting value.
///
/// The resulting value.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Matrix ToMatrix(in float depth)
{
ToMatrix(depth, out Matrix result);
return result;
}
///
/// Converts the specified value into a value.
///
///
/// The third row of the resulting is set to (0, 0, 1, 0), and the fourth row is set to
/// (, , 0, 1).
///
///
/// When this method returns, contains the resulting value. This parameter is passed
/// uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToMatrix(out Matrix result) => ToMatrix(0.0f, out result);
///
/// Converts the specified value into a value.
///
///
/// The third row of the resulting is set to (0, 0, 1, 0), and the fourth row is set to
/// (, , , 1).
///
///
/// The depth value to be used for the third row of the resulting value.
///
///
/// When this method returns, contains the resulting value. This parameter is passed
/// uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToMatrix(in float depth, out Matrix result) => ToMatrix(this, depth, out result);
///
/// Converts the specified value into a value.
///
///
/// The third row of the resulting is set to (0, 0, 1, 0), and the fourth row is set to
/// (, , 0, 1).
///
/// The source value.
/// The resulting value.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix ToMatrix(Matrix3x2 matrix) => ToMatrix(matrix, 0.0f);
///
/// Converts the specified value into a value.
///
///
/// The third row of the resulting is set to (0, 0, 1, 0), and the fourth row is set to
/// (, , , 1).
///
/// The source value.
///
/// The depth value to be used for the third row of the resulting value.
///
/// The resulting value.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix ToMatrix(Matrix3x2 matrix, in float depth)
{
ToMatrix(matrix, depth, out Matrix result);
return result;
}
///
/// Converts the specified value into a value.
///
///
/// The third row of the resulting is set to (0, 0, 1, 0), and the fourth row is set to
/// (, , 0, 1).
///
/// The source value.
///
/// When this method returns, contains the resulting value. This parameter is passed
/// uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ToMatrix(Matrix3x2 matrix, out Matrix result) => ToMatrix(matrix, 0.0f, out result);
///
/// Converts the specified value into a value.
///
///
/// The third row of the resulting is set to (0, 0, 1, 0), and the fourth row is set to
/// (, , , 1).
///
/// The source value.
///
/// The depth value to be used for the third row of the resulting value.
///
///
/// When this method returns, contains the resulting value. This parameter is passed
/// uninitialized.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ToMatrix(Matrix3x2 matrix, in float depth, out Matrix result)
{
result.M11 = matrix.M11;
result.M12 = matrix.M12;
result.M13 = 0;
result.M14 = 0;
result.M21 = matrix.M21;
result.M22 = matrix.M22;
result.M23 = 0;
result.M24 = 0;
result.M31 = 0;
result.M32 = 0;
result.M33 = 1;
result.M34 = 0;
result.M41 = matrix.M31;
result.M42 = matrix.M32;
result.M43 = depth;
result.M44 = 1;
}
///
/// Converts a value to a value.
///
/// The source value.
/// The resulting value.
public static implicit operator Matrix(Matrix3x2 matrix) => ToMatrix(matrix, 0.0f);
///
/// Checks if two values are equal.
///
///
/// Two values are considered equal if all their corresponding elements are equal.
///
/// The first value.
/// The second value.
/// True if the values are equal; otherwise, false.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Matrix3x2 left, Matrix3x2 right) =>
(left.X == right.X) && (left.Y == right.Y) && (left.Z == right.Z);
///
/// Checks if two values are not equal.
///
///
/// Two values are considered not equal if any of their corresponding elements differ.
///
/// The first value.
/// The second value.
/// True if the values are not equal; otherwise, false.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Matrix3x2 left, Matrix3x2 right) =>
(left.X != right.X) || (left.Y != right.Y) || (left.Z != right.Z);
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Matrix3x2 operator +(Matrix3x2 left, Matrix3x2 right)
{
Matrix3x2 result;
result.M11 = left.M11 + right.M11;
result.M12 = left.M12 + right.M12;
result.M21 = left.M21 + right.M21;
result.M22 = left.M22 + right.M22;
result.M31 = left.M31 + right.M31;
result.M32 = left.M32 + right.M32;
return result;
}
///
public static Matrix3x2 operator -(Matrix3x2 left, Matrix3x2 right)
{
Matrix3x2 result;
result.M11 = left.M11 - right.M11;
result.M12 = left.M12 - right.M12;
result.M21 = left.M21 - right.M21;
result.M22 = left.M22 - right.M22;
result.M31 = left.M31 - right.M31;
result.M32 = left.M32 - right.M32;
return result;
}
///
/// Negates the elements of a .
///
///
/// This operation is performed component-wise.
///
/// The source .
/// The result of the negation.
public static Matrix3x2 operator -(Matrix3x2 matrix)
{
Matrix3x2 result;
result.M11 = -matrix.M11;
result.M12 = -matrix.M12;
result.M21 = -matrix.M21;
result.M22 = -matrix.M22;
result.M31 = -matrix.M31;
result.M32 = -matrix.M32;
return result;
}
///
public static Matrix3x2 operator *(Matrix3x2 left, Matrix3x2 right)
{
Matrix3x2 result;
result.M11 = left.M11 * right.M11 + left.M12 * right.M21;
result.M12 = left.M11 * right.M12 + left.M12 * right.M22;
result.M21 = left.M21 * right.M11 + left.M22 * right.M21;
result.M22 = left.M21 * right.M12 + left.M22 * right.M22;
result.M31 = left.M31 * right.M11 + left.M32 * right.M21 + right.M31;
result.M32 = left.M31 * right.M12 + left.M32 * right.M22 + right.M32;
return result;
}
///
public static Matrix3x2 operator *(Matrix3x2 matrix, in float scalar)
{
Matrix3x2 result;
result.M11 = matrix.M11 * scalar;
result.M12 = matrix.M12 * scalar;
result.M21 = matrix.M21 * scalar;
result.M22 = matrix.M22 * scalar;
result.M31 = matrix.M31 * scalar;
result.M32 = matrix.M32 * scalar;
return result;
}
///
public static Matrix3x2 operator /(Matrix3x2 left, Matrix3x2 right)
{
Matrix3x2 result;
result.M11 = left.M11 / right.M11;
result.M12 = left.M12 / right.M12;
result.M21 = left.M21 / right.M21;
result.M22 = left.M22 / right.M22;
result.M31 = left.M31 / right.M31;
result.M32 = left.M32 / right.M32;
return result;
}
///
public static Matrix3x2 operator /(Matrix3x2 matrix, in float scalar)
{
var num = 1.0f / scalar;
Matrix3x2 result;
result.M11 = matrix.M11 * num;
result.M12 = matrix.M12 * num;
result.M21 = matrix.M21 * num;
result.M22 = matrix.M22 * num;
result.M31 = matrix.M31 * num;
result.M32 = matrix.M32 * num;
return result;
}
///
/// Returns a string representation of this
///
/// The string representation of this
public override string ToString() =>
$"{{M11:{M11} M12:{M12}}} {{M21:{M21} M22:{M22}}} {{M31:{M31} M32:{M32}}}";
internal string DebugDisplayString()
{
if (this == Identity)
{
return nameof(Identity);
}
Decompose(out Vector2 translation, out float rotation, out Vector2 scale);
return $"T:({translation.X:0.##},{translation.Y:0.##}), R:{MathHelper.ToDegrees(rotation):0.##}°, S:({scale.X:0.##},{scale.Y:0.##})";
}
}