Replace Matrix2 with Matrix3x2 (#870)

* Replace `Matrix2` with `Matrix3x2`

* Update benchmarks

* Add XML documentation for `Matrix3x2`
This commit is contained in:
Christopher Whitley
2024-05-27 15:44:38 -04:00
committed by GitHub
parent d008b1bd41
commit 49038f5d42
23 changed files with 1447 additions and 1150 deletions
+1 -1
View File
@@ -20,7 +20,7 @@
################################################################################
### Build artifacts directory
################################################################################
.artifacts/
*.[Aa]rtifacts/
################################################################################
### OS specific auto generated files
+2 -2
View File
@@ -32,7 +32,7 @@
</ItemGroup>
<!-- Setup Code Analysis using the .editorconfig file -->
<PropertyGroup>
<!-- <PropertyGroup>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<AnalysisLevel>latest</AnalysisLevel>
@@ -41,6 +41,6 @@
<CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningsAsErrors>nullable</WarningsAsErrors>
</PropertyGroup>
</PropertyGroup> -->
</Project>
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<Import Project="$(MSBuildThisFileDirectory)..\Directory.Build.props" />
<PropertyGroup>
<ArtifactsPath>$(SolutionDirectory).artifacts/benchmarks</ArtifactsPath>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<IsPackable>false</IsPackable>
<NoWarn>NU1701</NoWarn>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MonoGame.Framework.DesktopGL"
Version="3.8.1.303"
PrivateAssets="All" />
<PackageReference Include="BenchmarkDotNet"
Version="0.13.12" />
</ItemGroup>
</Project>
@@ -7,11 +7,6 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.10" />
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.1.303" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\src\cs\MonoGame.Extended.Collisions\MonoGame.Extended.Collisions.csproj" />
</ItemGroup>
@@ -0,0 +1,195 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using Microsoft.Xna.Framework;
namespace MonoGame.Extended.Benchmarks;
[MemoryDiagnoser]
public class Matrix3x2Benchmarks
{
private Matrix2 _matrix2;
private Matrix3x2 _matrix3x2;
[GlobalSetup]
public void Setup()
{
_matrix2 = new Matrix2(1, 2, 3, 4, 5, 6);
_matrix3x2 = new Matrix3x2(1, 2, 3, 4, 5, 6);
}
[Benchmark]
public Vector2 Matrix2_getTranslation() => _matrix2.Translation;
[Benchmark]
public Vector2 Matrix3x2_getTranslation() => _matrix3x2.Translation;
// [Benchmark]
// public float Matrix2_getRotation() => _matrix2.Rotation;
// [Benchmark]
// public float Matrix3x2_getRotation() => _matrix3x2.Rotation;
// [Benchmark]
// public Vector2 Matrix2_getScale() => _matrix2.Scale;
// [Benchmark]
// public Vector2 Matrix3x2_getScale() => _matrix3x2.Scale;
// [Benchmark]
// public (Vector2, float, Vector2) Matrix2_Decompose()
// {
// Vector2 translation = _matrix2.Translation;
// float rotation = _matrix2.Rotation;
// Vector2 scale = _matrix2.Scale;
// return (translation, rotation, scale);
// }
// [Benchmark]
// public (Vector2, float, Vector2) Matrix3x2_Decompose()
// {
// _matrix3x2.Decompose(out Vector2 translation, out float rotation, out Vector2 scale);
// return (translation, rotation, scale);
// }
// [Benchmark]
// public Vector2 Matrix2_Transform() => _matrix2.Transform(Vector2.One);
// [Benchmark]
// public Vector2 Matrix3x2_Transform() => _matrix3x2.Transform(Vector2.One);
// [Benchmark]
// public float Matrix2_Determinant() => _matrix2.Determinant();
// [Benchmark]
// public float Matrix3x2_Determinant() => _matrix3x2.Determinant();
// [Benchmark]
// public Matrix2 Matrix2_CreateFrom()
// {
// Matrix2.CreateFrom(Vector2.Zero, 1.0f, Vector2.One, Vector2.Zero, out Matrix2 result);
// return result;
// }
// [Benchmark]
// public Matrix3x2 Matrix3x2_CreateFrom()
// {
// Matrix3x2.CreateFrom(Vector2.Zero, 1.0f, Vector2.One, Vector2.Zero, out Matrix3x2 result);
// return result;
// }
// [Benchmark]
// public Matrix2 Matrix2_CreateRotationZ()
// {
// Matrix2.CreateRotationZ(1.0f, out Matrix2 result);
// return result;
// }
// [Benchmark]
// public Matrix3x2 Matrix3x2_CreateRotationZ()
// {
// Matrix3x2.CreateRotationZ(1.0f, out Matrix3x2 result);
// return result;
// }
// [Benchmark]
// public Matrix2 Matrix2_CreateScale()
// {
// Matrix2.CreateScale(1.0f, out Matrix2 result);
// return result;
// }
// [Benchmark]
// public Matrix3x2 Matrix3x2_CreateScale()
// {
// Matrix3x2.CreateScale(1.0f, out Matrix3x2 result);
// return result;
// }
// [Benchmark]
// public Matrix2 Matrix2_CreateTranslation()
// {
// Matrix2.CreateTranslation(1.0f, 1.0f, out Matrix2 result);
// return result;
// }
// [Benchmark]
// public Matrix3x2 Matrix3x2_CreateTranslation()
// {
// Matrix3x2.CreateTranslation(1.0f, 1.0f, out Matrix3x2 result);
// return result;
// }
// [Benchmark]
// public Matrix2 Matrix2_Invert()
// {
// Matrix2.Invert(ref _matrix2, out Matrix2 result);
// return result;
// }
// [Benchmark]
// public Matrix3x2 Matrix3x2_Invert()
// {
// Matrix3x2.Invert(_matrix3x2);
// return _matrix3x2;
// }
// [Benchmark]
// public Matrix2 Matrix2_Add()
// {
// return Matrix2.Add(_matrix2, _matrix2);
// }
// [Benchmark]
// public Matrix3x2 Matrix3x2_Add()
// {
// return Matrix3x2.Add(_matrix3x2, _matrix3x2);
// }
// [Benchmark]
// public Matrix2 Matrix2_Subtract()
// {
// return Matrix2.Subtract(_matrix2, _matrix2);
// }
// [Benchmark]
// public Matrix3x2 Matrix3x2_Subtract()
// {
// return Matrix3x2.Subtract(_matrix3x2, _matrix3x2);
// }
// [Benchmark]
// public Matrix2 Matrix2_Multiply()
// {
// return Matrix2.Subtract(_matrix2, _matrix2);
// }
// [Benchmark]
// public Matrix3x2 Matrix3x2_Multiply()
// {
// return Matrix3x2.Multiply(_matrix3x2, _matrix3x2);
// }
// [Benchmark]
// public Matrix2 Matrix2_Divide()
// {
// return Matrix2.Divide(_matrix2, _matrix2);
// }
// [Benchmark]
// public Matrix3x2 Matrix3x2_Divide()
// {
// return Matrix3x2.Divide(_matrix3x2, _matrix3x2);
// }
// [Benchmark]
// public Matrix Matrix2_ToMatrix()
// {
// return _matrix2.ToMatrix();
// }
// [Benchmark]
// public Matrix Matrix3x2_ToMatrix()
// {
// return _matrix3x2.ToMatrix();
// }
}
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\source\MonoGame.Extended\MonoGame.Extended.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,7 @@
using BenchmarkDotNet.Running;
using MonoGame.Extended.Benchmarks;
BenchmarkRunner.Run<Matrix3x2Benchmarks>();
Console.WriteLine("finished");
@@ -273,13 +273,13 @@ namespace MonoGame.Extended.Collisions
private static Vector2 PenetrationVector(CircleF circleA, OrientedRectangle orientedRectangleB)
{
var rotation = Matrix2.CreateRotationZ(orientedRectangleB.Orientation.Rotation);
var rotation = Matrix3x2.CreateRotationZ(orientedRectangleB.Orientation.Rotation);
var circleCenterInRectangleSpace = rotation.Transform(circleA.Center - orientedRectangleB.Center);
var circleInRectangleSpace = new CircleF(circleCenterInRectangleSpace, circleA.Radius);
var boundingRectangle = new BoundingRectangle(new Point2(), orientedRectangleB.Radii);
var penetrationVector = PenetrationVector(circleInRectangleSpace, boundingRectangle);
var inverseRotation = Matrix2.CreateRotationZ(-orientedRectangleB.Orientation.Rotation);
var inverseRotation = Matrix3x2.CreateRotationZ(-orientedRectangleB.Orientation.Rotation);
var transformedPenetration = inverseRotation.Transform(penetrationVector);
return transformedPenetration;
+18 -18
View File
@@ -91,7 +91,7 @@ namespace MonoGame.Extended.Graphics
// Upload the indices to the GPU and then select that index stream for drawing
_indexBuffer.SetData(_sortedIndices, 0, _indexCount);
GraphicsDevice.Indices = _indexBuffer;
_indexCount = 0;
_vertexCount = 0;
}
@@ -136,12 +136,12 @@ namespace MonoGame.Extended.Graphics
}
/// <summary>
/// Draws a sprite using a specified <see cref="Texture" />, transform <see cref="Matrix2" />, source
/// Draws a sprite using a specified <see cref="Texture" />, transform <see cref="Matrix3x2" />, source
/// <see cref="Rectangle" />, and an optional
/// <see cref="Color" />, origin <see cref="Vector2" />, <see cref="FlipFlags" />, and depth <see cref="float" />.
/// </summary>
/// <param name="texture">The <see cref="Texture" />.</param>
/// <param name="transformMatrix">The transform <see cref="Matrix2" />.</param>
/// <param name="transformMatrix">The transform <see cref="Matrix3x2" />.</param>
/// <param name="sourceRectangle">
/// The texture region <see cref="Rectangle" /> of the <paramref name="texture" />. Use
/// <code>null</code> to use the entire <see cref="Texture2D" />.
@@ -151,7 +151,7 @@ namespace MonoGame.Extended.Graphics
/// <param name="depth">The depth <see cref="float" />. The default value is <code>0</code>.</param>
/// <exception cref="InvalidOperationException">The <see cref="Batcher{TDrawCallInfo}.Begin(ref Matrix, ref Matrix, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect)" /> method has not been called.</exception>
/// <exception cref="ArgumentNullException"><paramref name="texture" /> is null.</exception>
public void DrawSprite(Texture2D texture, ref Matrix2 transformMatrix, ref Rectangle sourceRectangle,
public void DrawSprite(Texture2D texture, ref Matrix3x2 transformMatrix, ref Rectangle sourceRectangle,
Color? color = null, FlipFlags flags = FlipFlags.None, float depth = 0)
{
_geometryBuilder.BuildSprite(_vertexCount, ref transformMatrix, texture, ref sourceRectangle, color, flags, depth);
@@ -159,17 +159,17 @@ namespace MonoGame.Extended.Graphics
}
/// <summary>
/// Draws a <see cref="Texture" /> using the specified transform <see cref="Matrix2" /> and an optional
/// Draws a <see cref="Texture" /> using the specified transform <see cref="Matrix3x2" /> and an optional
/// <see cref="Color" />, origin <see cref="Vector2" />, <see cref="FlipFlags" />, and depth <see cref="float" />.
/// </summary>
/// <param name="texture">The <see cref="Texture" />.</param>
/// <param name="transformMatrix">The transform <see cref="Matrix2" />.</param>
/// <param name="transformMatrix">The transform <see cref="Matrix3x2" />.</param>
/// <param name="color">The <see cref="Color" />. Use <code>null</code> to use the default <see cref="Color.White" />.</param>
/// <param name="flags">The <see cref="FlipFlags" />. The default value is <see cref="FlipFlags.None" />.</param>
/// <param name="depth">The depth <see cref="float" />. The default value is <code>0</code>.</param>
/// <exception cref="InvalidOperationException">The <see cref="Batcher{TDrawCallInfo}.Begin(ref Matrix, ref Matrix, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect)" /> method has not been called.</exception>
/// <exception cref="ArgumentNullException"><paramref name="texture" /> is null.</exception>
public void DrawTexture(Texture2D texture, ref Matrix2 transformMatrix, Color? color = null,
public void DrawTexture(Texture2D texture, ref Matrix3x2 transformMatrix, Color? color = null,
FlipFlags flags = FlipFlags.None, float depth = 0)
{
var rectangle = default(Rectangle);
@@ -193,12 +193,12 @@ namespace MonoGame.Extended.Graphics
/// <summary>
/// Draws unicode (UTF-16) characters as sprites using the specified <see cref="BitmapFont" />, text
/// <see cref="StringBuilder" />, transform <see cref="Matrix2" /> and optional <see cref="Color" />, origin
/// <see cref="StringBuilder" />, transform <see cref="Matrix3x2" /> and optional <see cref="Color" />, origin
/// <see cref="Vector2" />, <see cref="FlipFlags" />, and depth <see cref="float" />.
/// </summary>
/// <param name="bitmapFont">The <see cref="BitmapFont" />.</param>
/// <param name="text">The text <see cref="StringBuilder" />.</param>
/// <param name="transformMatrix">The transform <see cref="Matrix2" />.</param>
/// <param name="transformMatrix">The transform <see cref="Matrix3x2" />.</param>
/// <param name="color">
/// The <see cref="Color" />. Use <code>null</code> to use the default
/// <see cref="Color.White" />.
@@ -207,7 +207,7 @@ namespace MonoGame.Extended.Graphics
/// <param name="depth">The depth <see cref="float" />. The default value is <code>0f</code>.</param>
/// <exception cref="InvalidOperationException">The <see cref="Batcher{TDrawCallInfo}.Begin(ref Matrix, ref Matrix, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect)" /> method has not been called.</exception>
/// <exception cref="ArgumentNullException"><paramref name="bitmapFont" /> is null or <paramref name="text" /> is null.</exception>
public void DrawString(BitmapFont bitmapFont, StringBuilder text, ref Matrix2 transformMatrix,
public void DrawString(BitmapFont bitmapFont, StringBuilder text, ref Matrix3x2 transformMatrix,
Color? color = null, FlipFlags flags = FlipFlags.None, float depth = 0f)
{
EnsureHasBegun();
@@ -316,19 +316,19 @@ namespace MonoGame.Extended.Graphics
float rotation = 0f, Vector2? origin = null, Vector2? scale = null,
FlipFlags flags = FlipFlags.None, float depth = 0f)
{
Matrix2 transformMatrix;
Matrix2.CreateFrom(position, rotation, scale, origin, out transformMatrix);
Matrix3x2 transformMatrix;
Matrix3x2.CreateFrom(position, rotation, scale, origin, out transformMatrix);
DrawString(bitmapFont, text, ref transformMatrix, color, flags, depth);
}
/// <summary>
/// Draws unicode (UTF-16) characters as sprites using the specified <see cref="BitmapFont" />, text
/// <see cref="string" />, transform <see cref="Matrix2" /> and optional <see cref="Color" />, origin
/// <see cref="string" />, transform <see cref="Matrix3x2" /> and optional <see cref="Color" />, origin
/// <see cref="Vector2" />, <see cref="FlipFlags" />, and depth <see cref="float" />.
/// </summary>
/// <param name="bitmapFont">The <see cref="BitmapFont" />.</param>
/// <param name="text">The text <see cref="string" />.</param>
/// <param name="transformMatrix">The transform <see cref="Matrix2" />.</param>
/// <param name="transformMatrix">The transform <see cref="Matrix3x2" />.</param>
/// <param name="color">
/// The <see cref="Color" />. Use <code>null</code> to use the default
/// <see cref="Color.White" />.
@@ -337,7 +337,7 @@ namespace MonoGame.Extended.Graphics
/// <param name="depth">The depth <see cref="float" />. The default value is <code>0f</code></param>
/// <exception cref="InvalidOperationException">The <see cref="Batcher{TDrawCallInfo}.Begin(ref Matrix, ref Matrix, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect)" /> method has not been called.</exception>
/// <exception cref="ArgumentNullException"><paramref name="bitmapFont" /> is null or <paramref name="text" /> is null.</exception>
public void DrawString(BitmapFont bitmapFont, string text, ref Matrix2 transformMatrix, Color? color = null,
public void DrawString(BitmapFont bitmapFont, string text, ref Matrix3x2 transformMatrix, Color? color = null,
FlipFlags flags = FlipFlags.None, float depth = 0f)
{
EnsureHasBegun();
@@ -394,8 +394,8 @@ namespace MonoGame.Extended.Graphics
float rotation = 0f, Vector2? origin = null, Vector2? scale = null,
FlipFlags flags = FlipFlags.None, float depth = 0f)
{
Matrix2 matrix;
Matrix2.CreateFrom(position, rotation, scale, origin, out matrix);
Matrix3x2 matrix;
Matrix3x2.CreateFrom(position, rotation, scale, origin, out matrix);
DrawString(bitmapFont, text, ref matrix, color, flags, depth);
}
@@ -447,4 +447,4 @@ namespace MonoGame.Extended.Graphics
}
}
}
}
}
@@ -12,7 +12,7 @@ namespace MonoGame.Extended.Graphics.Geometry
{
}
public void BuildSprite(int indexOffset, ref Matrix2 transformMatrix, Texture2D texture,
public void BuildSprite(int indexOffset, ref Matrix3x2 transformMatrix, Texture2D texture,
ref Rectangle sourceRectangle,
Color? color = null, FlipFlags flags = FlipFlags.None, float depth = 0)
{
@@ -5,7 +5,7 @@ using Microsoft.Xna.Framework;
namespace MonoGame.Extended
{
// Real-Time Collision Detection, Christer Ericson, 2005. Chapter 4.2; Bounding Volumes - Axis-aligned Bounding Boxes (AABBs). pg 77
// Real-Time Collision Detection, Christer Ericson, 2005. Chapter 4.2; Bounding Volumes - Axis-aligned Bounding Boxes (AABBs). pg 77
/// <summary>
/// An axis-aligned, four sided, two dimensional box defined by a centre <see cref="Point2" /> and a radii
@@ -112,7 +112,7 @@ namespace MonoGame.Extended
/// <summary>
/// Computes the <see cref="BoundingRectangle" /> from the specified <see cref="BoundingRectangle" /> transformed by
/// the
/// specified <see cref="Matrix2" />.
/// specified <see cref="Matrix3x2" />.
/// </summary>
/// <param name="boundingRectangle">The bounding rectangle.</param>
/// <param name="transformMatrix">The transform matrix.</param>
@@ -129,7 +129,7 @@ namespace MonoGame.Extended
/// </para>
/// </remarks>
public static void Transform(ref BoundingRectangle boundingRectangle,
ref Matrix2 transformMatrix, out BoundingRectangle result)
ref Matrix3x2 transformMatrix, out BoundingRectangle result)
{
PrimitivesHelper.TransformRectangle(ref boundingRectangle.Center, ref boundingRectangle.HalfExtents, ref transformMatrix);
result.Center = boundingRectangle.Center;
@@ -139,7 +139,7 @@ namespace MonoGame.Extended
/// <summary>
/// Computes the <see cref="BoundingRectangle" /> from the specified <see cref="BoundingRectangle" /> transformed by
/// the
/// specified <see cref="Matrix2" />.
/// specified <see cref="Matrix3x2" />.
/// </summary>
/// <param name="boundingRectangle">The bounding rectangle.</param>
/// <param name="transformMatrix">The transform matrix.</param>
@@ -155,7 +155,7 @@ namespace MonoGame.Extended
/// </para>
/// </remarks>
public static BoundingRectangle Transform(BoundingRectangle boundingRectangle,
ref Matrix2 transformMatrix)
ref Matrix3x2 transformMatrix)
{
BoundingRectangle result;
Transform(ref boundingRectangle, ref transformMatrix, out result);
@@ -576,4 +576,4 @@ namespace MonoGame.Extended
internal string DebugDisplayString => ToString();
}
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -29,9 +29,9 @@ namespace MonoGame.Extended
public Vector2 Radii;
/// <summary>
/// The rotation matrix <see cref="Matrix2" /> of the bounding rectangle <see cref="OrientedRectangle" />.
/// The rotation matrix <see cref="Matrix3x2" /> of the bounding rectangle <see cref="OrientedRectangle" />.
/// </summary>
public Matrix2 Orientation;
public Matrix3x2 Orientation;
/// <summary>
/// Initializes a new instance of the <see cref="BoundingRectangle" /> structure from the specified centre
@@ -39,8 +39,8 @@ namespace MonoGame.Extended
/// </summary>
/// <param name="center">The centre <see cref="Point2" />.</param>
/// <param name="radii">The radii <see cref="Vector2" />.</param>
/// <param name="orientation">The orientation <see cref="Matrix2" />.</param>
public OrientedRectangle(Point2 center, Size2 radii, Matrix2 orientation)
/// <param name="orientation">The orientation <see cref="Matrix3x2" />.</param>
public OrientedRectangle(Point2 center, Size2 radii, Matrix3x2 orientation)
{
Center = center;
Radii = radii;
@@ -82,15 +82,15 @@ namespace MonoGame.Extended
/// transformed by <paramref name="transformMatrix"/>.
/// </summary>
/// <param name="rectangle">The <see cref="OrientedRectangle"/> to transform.</param>
/// <param name="transformMatrix">The <see cref="Matrix2"/> transformation.</param>
/// <param name="transformMatrix">The <see cref="Matrix3x2"/> transformation.</param>
/// <returns>A new <see cref="OrientedRectangle"/>.</returns>
public static OrientedRectangle Transform(OrientedRectangle rectangle, ref Matrix2 transformMatrix)
public static OrientedRectangle Transform(OrientedRectangle rectangle, ref Matrix3x2 transformMatrix)
{
Transform(ref rectangle, ref transformMatrix, out var result);
return result;
}
private static void Transform(ref OrientedRectangle rectangle, ref Matrix2 transformMatrix, out OrientedRectangle result)
private static void Transform(ref OrientedRectangle rectangle, ref Matrix3x2 transformMatrix, out OrientedRectangle result)
{
PrimitivesHelper.TransformOrientedRectangle(
ref rectangle.Center,
@@ -169,14 +169,14 @@ namespace MonoGame.Extended
var radii = new Size2(rectangle.Width * 0.5f, rectangle.Height * 0.5f);
var centre = new Point2(rectangle.X + radii.Width, rectangle.Y + radii.Height);
return new OrientedRectangle(centre, radii, Matrix2.Identity);
return new OrientedRectangle(centre, radii, Matrix3x2.Identity);
}
public static explicit operator RectangleF(OrientedRectangle orientedRectangle)
{
var topLeft = -orientedRectangle.Radii;
var rectangle = new RectangleF(topLeft, orientedRectangle.Radii * 2);
var orientation = orientedRectangle.Orientation * Matrix2.CreateTranslation(orientedRectangle.Center);
var orientation = orientedRectangle.Orientation * Matrix3x2.CreateTranslation(orientedRectangle.Center);
return RectangleF.Transform(rectangle, ref orientation);
}
@@ -60,7 +60,7 @@ namespace MonoGame.Extended
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void TransformRectangle(ref Point2 center, ref Vector2 halfExtents, ref Matrix2 transformMatrix)
internal static void TransformRectangle(ref Point2 center, ref Vector2 halfExtents, ref Matrix3x2 transformMatrix)
{
// Real-Time Collision Detection, Christer Ericson, 2005. Chapter 4.2; Bounding Volumes - Axis-aligned Bounding Boxes (AABBs). pg 86-87
@@ -74,8 +74,8 @@ namespace MonoGame.Extended
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void TransformOrientedRectangle(
ref Point2 center,
ref Matrix2 orientation,
ref Matrix2 transformMatrix)
ref Matrix3x2 orientation,
ref Matrix3x2 transformMatrix)
{
// Real-Time Collision Detection, Christer Ericson, 2005. Chapter 4.4; Oriented Bounding Boxes (OBBs), pg 101-105.
+4 -4
View File
@@ -223,7 +223,7 @@ namespace MonoGame.Extended
/// <summary>
/// Computes the <see cref="RectangleF" /> from the specified <see cref="RectangleF" /> transformed by
/// the specified <see cref="Matrix2" />.
/// the specified <see cref="Matrix3x2" />.
/// </summary>
/// <param name="rectangle">The rectangle to be transformed.</param>
/// <param name="transformMatrix">The transform matrix.</param>
@@ -240,7 +240,7 @@ namespace MonoGame.Extended
/// </para>
/// </remarks>
public static void Transform(ref RectangleF rectangle,
ref Matrix2 transformMatrix, out RectangleF result)
ref Matrix3x2 transformMatrix, out RectangleF result)
{
var center = rectangle.Center;
var halfExtents = (Vector2)rectangle.Size * 0.5f;
@@ -256,7 +256,7 @@ namespace MonoGame.Extended
/// <summary>
/// Computes the <see cref="RectangleF" /> from the specified <see cref="Extended.BoundingRectangle" /> transformed by
/// the
/// specified <see cref="Matrix2" />.
/// specified <see cref="Matrix3x2" />.
/// </summary>
/// <param name="rectangle">The bounding rectangle.</param>
/// <param name="transformMatrix">The transform matrix.</param>
@@ -271,7 +271,7 @@ namespace MonoGame.Extended
/// not desired.
/// </para>
/// </remarks>
public static RectangleF Transform(RectangleF rectangle, ref Matrix2 transformMatrix)
public static RectangleF Transform(RectangleF rectangle, ref Matrix3x2 transformMatrix)
{
RectangleF result;
Transform(ref rectangle, ref transformMatrix, out result);
+1 -1
View File
@@ -74,7 +74,7 @@ namespace MonoGame.Extended
/// <returns>True if the circle and oriented bounded rectangle intersects, otherwise false.</returns>
public static bool Intersects(CircleF circle, OrientedRectangle orientedRectangle)
{
var rotation = Matrix2.CreateRotationZ(orientedRectangle.Orientation.Rotation);
var rotation = Matrix3x2.CreateRotationZ(orientedRectangle.Orientation.Rotation);
var circleCenterInRectangleSpace = rotation.Transform(circle.Center - orientedRectangle.Center);
var circleInRectangleSpace = new CircleF(circleCenterInRectangleSpace, circle.Radius);
var boundingRectangle = new BoundingRectangle(new Point2(), orientedRectangle.Radii);
+17 -17
View File
@@ -45,10 +45,10 @@ namespace MonoGame.Extended
}
/// <summary>
/// Gets the model-to-local space <see cref="Matrix2" />.
/// Gets the model-to-local space <see cref="Matrix3x2" />.
/// </summary>
/// <value>
/// The model-to-local space <see cref="Matrix2" />.
/// The model-to-local space <see cref="Matrix3x2" />.
/// </value>
public TMatrix LocalMatrix
{
@@ -60,10 +60,10 @@ namespace MonoGame.Extended
}
/// <summary>
/// Gets the local-to-world space <see cref="Matrix2" />.
/// Gets the local-to-world space <see cref="Matrix3x2" />.
/// </summary>
/// <value>
/// The local-to-world space <see cref="Matrix2" />.
/// The local-to-world space <see cref="Matrix3x2" />.
/// </value>
public TMatrix WorldMatrix
{
@@ -106,9 +106,9 @@ namespace MonoGame.Extended
public event Action TranformUpdated; // observer pattern for after the world (or local) matrix was re-calculated
/// <summary>
/// Gets the model-to-local space <see cref="Matrix2" />.
/// Gets the model-to-local space <see cref="Matrix3x2" />.
/// </summary>
/// <param name="matrix">The model-to-local space <see cref="Matrix2" />.</param>
/// <param name="matrix">The model-to-local space <see cref="Matrix3x2" />.</param>
public void GetLocalMatrix(out TMatrix matrix)
{
RecalculateLocalMatrixIfNecessary();
@@ -116,9 +116,9 @@ namespace MonoGame.Extended
}
/// <summary>
/// Gets the local-to-world space <see cref="Matrix2" />.
/// Gets the local-to-world space <see cref="Matrix3x2" />.
/// </summary>
/// <param name="matrix">The local-to-world space <see cref="Matrix2" />.</param>
/// <param name="matrix">The local-to-world space <see cref="Matrix3x2" />.</param>
public void GetWorldMatrix(out TMatrix matrix)
{
RecalculateWorldMatrixIfNecessary();
@@ -189,7 +189,7 @@ namespace MonoGame.Extended
/// <summary>
/// Represents the position, rotation, and scale of a two-dimensional game object.
/// </summary>
/// <seealso cref="BaseTransform{Matrix2D}" />
/// <seealso cref="BaseTransform{Matrix3x2D}" />
/// <seealso cref="IMovable" />
/// <seealso cref="IRotatable" />
/// <seealso cref="IScalable" />
@@ -200,7 +200,7 @@ namespace MonoGame.Extended
/// objects hierarchically.
/// </para>
/// </remarks>
public class Transform2 : BaseTransform<Matrix2>, IMovable, IRotatable, IScalable
public class Transform2 : BaseTransform<Matrix3x2>, IMovable, IRotatable, IScalable
{
private Vector2 _position;
private float _rotation;
@@ -298,12 +298,12 @@ namespace MonoGame.Extended
}
}
protected internal override void RecalculateWorldMatrix(ref Matrix2 localMatrix, out Matrix2 matrix)
protected internal override void RecalculateWorldMatrix(ref Matrix3x2 localMatrix, out Matrix3x2 matrix)
{
if (Parent != null)
{
Parent.GetWorldMatrix(out matrix);
Matrix2.Multiply(ref localMatrix, ref matrix, out matrix);
Matrix3x2.Multiply(ref localMatrix, ref matrix, out matrix);
}
else
{
@@ -311,11 +311,11 @@ namespace MonoGame.Extended
}
}
protected internal override void RecalculateLocalMatrix(out Matrix2 matrix)
protected internal override void RecalculateLocalMatrix(out Matrix3x2 matrix)
{
matrix = Matrix2.CreateScale(_scale) *
Matrix2.CreateRotationZ(_rotation) *
Matrix2.CreateTranslation(_position);
matrix = Matrix3x2.CreateScale(_scale) *
Matrix3x2.CreateRotationZ(_rotation) *
Matrix3x2.CreateTranslation(_position);
}
public override string ToString()
@@ -453,4 +453,4 @@ namespace MonoGame.Extended
return $"Position: {Position}, Rotation: {Rotation}, Scale: {Scale}";
}
}
}
}
@@ -0,0 +1,20 @@
using Microsoft.Xna.Framework;
namespace MonoGame.Extended.Tests;
public sealed class Matrix3x2Tests
{
[Fact]
public void ConstructorTest()
{
Vector2 x = new Vector2(1, 2);
Vector2 y = new Vector2(3, 4);
Vector2 z = new Vector2(5, 6);
var matrix = new Matrix3x2(x.X, x.Y, y.X, y.Y, z.X, z.Y);
Assert.Equal(x, matrix.X);
Assert.Equal(y, matrix.Y);
Assert.Equal(z, matrix.Z);
}
}
@@ -5,7 +5,7 @@
//namespace MonoGame.Extended.Tests.Primitives
//{
//
//
// public class BoundingRectangleTests
// {
// public IEnumerable<TestCaseData> ConstructorTestCases
@@ -88,11 +88,11 @@
// get
// {
// yield return
// new TestCaseData(new BoundingRectangle(), Matrix2.Identity, new BoundingRectangle()).SetName(
// new TestCaseData(new BoundingRectangle(), Matrix3x2.Identity, new BoundingRectangle()).SetName(
// "The bounding rectangle created from the empty bounding rectangle transformed by the identity matrix is the empty bounding rectangle.")
// ;
// yield return
// new TestCaseData(new BoundingRectangle(new Point2(0, 0), new Size2(20, 20)), Matrix2.CreateScale(2), new BoundingRectangle(new Point2(0, 0), new Size2(40, 40))).SetName(
// new TestCaseData(new BoundingRectangle(new Point2(0, 0), new Size2(20, 20)), Matrix3x2.CreateScale(2), new BoundingRectangle(new Point2(0, 0), new Size2(40, 40))).SetName(
// "The bounding rectangle created from a non-empty bounding rectangle transformed by a non-identity matrix is the expected bounding rectangle.")
// ;
// }
@@ -100,7 +100,7 @@
// [Fact]
// [TestCaseSource(nameof(CreateFromTransformedTestCases))]
// public void CreateFromTransformed(BoundingRectangle boundingRectangle, Matrix2 transformMatrix,
// public void CreateFromTransformed(BoundingRectangle boundingRectangle, Matrix3x2 transformMatrix,
// BoundingRectangle expectedBoundingRectangle)
// {
// var actualBoundingRectangle = BoundingRectangle.Transform(boundingRectangle, ref transformMatrix);
@@ -10,11 +10,11 @@ public class OrientedRectangleTests
[Fact]
public void Initializes_oriented_rectangle()
{
var rectangle = new OrientedRectangle(new Point2(1, 2), new Size2(3, 4), new Matrix2(5, 6, 7, 8, 9, 10));
var rectangle = new OrientedRectangle(new Point2(1, 2), new Size2(3, 4), new Matrix3x2(5, 6, 7, 8, 9, 10));
Assert.Equal(new Point2(1, 2), rectangle.Center);
Assert.Equal(new Vector2(3, 4), rectangle.Radii);
Assert.Equal(new Matrix2(5, 6, 7, 8, 9, 10), rectangle.Orientation);
Assert.Equal(new Matrix3x2(5, 6, 7, 8, 9, 10), rectangle.Orientation);
CollectionAssert.Equal(
new List<Vector2>
{
@@ -31,14 +31,14 @@ public class OrientedRectangleTests
new object[]
{
"empty compared with empty is true",
new OrientedRectangle(Point2.Zero, Size2.Empty, Matrix2.Identity),
new OrientedRectangle(Point2.Zero, Size2.Empty, Matrix2.Identity)
new OrientedRectangle(Point2.Zero, Size2.Empty, Matrix3x2.Identity),
new OrientedRectangle(Point2.Zero, Size2.Empty, Matrix3x2.Identity)
},
new object[]
{
"initialized compared with initialized true",
new OrientedRectangle(new Point2(1, 2), new Size2(3, 4), new Matrix2(5, 6, 7, 8, 9, 10)),
new OrientedRectangle(new Point2(1, 2), new Size2(3, 4), new Matrix2(5, 6, 7, 8, 9, 10))
new OrientedRectangle(new Point2(1, 2), new Size2(3, 4), new Matrix3x2(5, 6, 7, 8, 9, 10)),
new OrientedRectangle(new Point2(1, 2), new Size2(3, 4), new Matrix3x2(5, 6, 7, 8, 9, 10))
}
};
@@ -57,8 +57,8 @@ public class OrientedRectangleTests
[Fact]
public void Center_point_is_not_translated()
{
var rectangle = new OrientedRectangle(new Point2(1, 2), new Size2(), Matrix2.Identity);
var transform = Matrix2.Identity;
var rectangle = new OrientedRectangle(new Point2(1, 2), new Size2(), Matrix3x2.Identity);
var transform = Matrix3x2.Identity;
var result = OrientedRectangle.Transform(rectangle, ref transform);
@@ -68,8 +68,8 @@ public class OrientedRectangleTests
[Fact]
public void Center_point_is_translated()
{
var rectangle = new OrientedRectangle(new Point2(0, 0), new Size2(), new Matrix2());
var transform = Matrix2.CreateTranslation(1, 2);
var rectangle = new OrientedRectangle(new Point2(0, 0), new Size2(), new Matrix3x2());
var transform = Matrix3x2.CreateTranslation(1, 2);
var result = OrientedRectangle.Transform(rectangle, ref transform);
@@ -79,8 +79,8 @@ public class OrientedRectangleTests
[Fact]
public void Radii_is_not_changed_by_identity_transform()
{
var rectangle = new OrientedRectangle(new Point2(), new Size2(10, 20), new Matrix2());
var transform = Matrix2.Identity;
var rectangle = new OrientedRectangle(new Point2(), new Size2(10, 20), new Matrix3x2());
var transform = Matrix3x2.Identity;
var result = OrientedRectangle.Transform(rectangle, ref transform);
@@ -90,8 +90,8 @@ public class OrientedRectangleTests
[Fact]
public void Radii_is_not_changed_by_translation()
{
var rectangle = new OrientedRectangle(new Point2(1, 2), new Size2(10, 20), new Matrix2());
var transform = Matrix2.CreateTranslation(1, 2);
var rectangle = new OrientedRectangle(new Point2(1, 2), new Size2(10, 20), new Matrix3x2());
var transform = Matrix3x2.CreateTranslation(1, 2);
var result = OrientedRectangle.Transform(rectangle, ref transform);
@@ -101,22 +101,22 @@ public class OrientedRectangleTests
[Fact]
public void Orientation_is_rotated_45_degrees_left()
{
var rectangle = new OrientedRectangle(new Point2(), new Size2(), Matrix2.Identity);
var transform = Matrix2.CreateRotationZ(MathHelper.PiOver4);
var rectangle = new OrientedRectangle(new Point2(), new Size2(), Matrix3x2.Identity);
var transform = Matrix3x2.CreateRotationZ(MathHelper.PiOver4);
var result = OrientedRectangle.Transform(rectangle, ref transform);
Assert.Equal(new Point2(), result.Center);
Assert.Equal(new Vector2(), result.Radii);
Assert.Equal(Matrix2.CreateRotationZ(MathHelper.PiOver4), result.Orientation);
Assert.Equal(Matrix3x2.CreateRotationZ(MathHelper.PiOver4), result.Orientation);
}
[Fact]
public void Orientation_is_rotated_to_45_degrees_from_180()
{
var rectangle = new OrientedRectangle(new Point2(), new Size2(), Matrix2.CreateRotationZ(MathHelper.Pi));
var transform = Matrix2.CreateRotationZ(-3 * MathHelper.PiOver4);
var expectedOrientation = Matrix2.CreateRotationZ(MathHelper.PiOver4);
var rectangle = new OrientedRectangle(new Point2(), new Size2(), Matrix3x2.CreateRotationZ(MathHelper.Pi));
var transform = Matrix3x2.CreateRotationZ(-3 * MathHelper.PiOver4);
var expectedOrientation = Matrix3x2.CreateRotationZ(MathHelper.PiOver4);
var result = OrientedRectangle.Transform(rectangle, ref transform);
@@ -133,8 +133,8 @@ public class OrientedRectangleTests
[Fact]
public void Points_are_same_as_center()
{
var rectangle = new OrientedRectangle(new Point2(1, 2), new Size2(), Matrix2.Identity);
var transform = Matrix2.Identity;
var rectangle = new OrientedRectangle(new Point2(1, 2), new Size2(), Matrix3x2.Identity);
var transform = Matrix3x2.Identity;
var result = OrientedRectangle.Transform(rectangle, ref transform);
@@ -152,8 +152,8 @@ public class OrientedRectangleTests
[Fact]
public void Points_are_translated()
{
var rectangle = new OrientedRectangle(new Point2(0, 0), new Size2(2, 4), Matrix2.Identity);
var transform = Matrix2.CreateTranslation(10, 20);
var rectangle = new OrientedRectangle(new Point2(0, 0), new Size2(2, 4), Matrix3x2.Identity);
var transform = Matrix3x2.CreateTranslation(10, 20);
var result = OrientedRectangle.Transform(rectangle, ref transform);
@@ -207,11 +207,11 @@ public class OrientedRectangleTests
* :
* :
*/
var rectangle = new OrientedRectangle(new Point2(1, 2), new Size2(2, 4), Matrix2.Identity);
var rectangle = new OrientedRectangle(new Point2(1, 2), new Size2(2, 4), Matrix3x2.Identity);
var transform =
Matrix2.CreateRotationZ(MathHelper.PiOver2)
Matrix3x2.CreateRotationZ(MathHelper.PiOver2)
*
Matrix2.CreateTranslation(10, 20);
Matrix3x2.CreateTranslation(10, 20);
var result = OrientedRectangle.Transform(rectangle, ref transform);
@@ -219,7 +219,7 @@ public class OrientedRectangleTests
Assert.Equal(21, result.Center.Y, 6);
Assert.Equal(2, result.Radii.X, 6);
Assert.Equal(4, result.Radii.Y, 6);
Assert.Equal(Matrix2.CreateRotationZ(MathHelper.PiOver2), result.Orientation);
Assert.Equal(Matrix3x2.CreateRotationZ(MathHelper.PiOver2), result.Orientation);
CollectionAssert.Equal(
new List<Vector2>
{
@@ -38,7 +38,7 @@ namespace MonoGame.Extended.Tests.Primitives
public void Center_point_is_not_translated()
{
var rectangle = new RectangleF(new Point2(0, 0), new Size2(20, 30));
var transform = Matrix2.Identity;
var transform = Matrix3x2.Identity;
var result = RectangleF.Transform(rectangle, ref transform);
@@ -49,7 +49,7 @@ namespace MonoGame.Extended.Tests.Primitives
public void Center_point_is_translated()
{
var rectangleF = new RectangleF(new Point2(0, 0), new Size2(20, 30));
var transform = Matrix2.CreateTranslation(1, 2);
var transform = Matrix3x2.CreateTranslation(1, 2);
var result = RectangleF.Transform(rectangleF, ref transform);
@@ -60,7 +60,7 @@ namespace MonoGame.Extended.Tests.Primitives
public void Size_is_not_changed_by_identity_transform()
{
var rectangle = new RectangleF(new Point2(0, 0), new Size2(20, 30));
var transform = Matrix2.Identity;
var transform = Matrix3x2.Identity;
var result = RectangleF.Transform(rectangle, ref transform);
@@ -71,7 +71,7 @@ namespace MonoGame.Extended.Tests.Primitives
public void Size_is_not_changed_by_translation()
{
var rectangle = new RectangleF(new Point2(0, 0), new Size2(20, 30));
var transform = Matrix2.CreateTranslation(1, 2);
var transform = Matrix3x2.CreateTranslation(1, 2);
var result = RectangleF.Transform(rectangle, ref transform);
@@ -119,9 +119,9 @@ namespace MonoGame.Extended.Tests.Primitives
*/
var rectangle = new RectangleF(new Point2(0, 0), new Size2(2, 4));
var transform =
Matrix2.CreateRotationZ(MathHelper.PiOver2)
Matrix3x2.CreateRotationZ(MathHelper.PiOver2)
*
Matrix2.CreateTranslation(10, 20);
Matrix3x2.CreateTranslation(10, 20);
var result = RectangleF.Transform(rectangle, ref transform);
@@ -99,7 +99,7 @@ public class ShapeTests
* :
* :
*/
IShapeF rectangle = new OrientedRectangle(Point2.Zero, new Size2(1, 1), Matrix2.Identity);
IShapeF rectangle = new OrientedRectangle(Point2.Zero, new Size2(1, 1), Matrix3x2.Identity);
var circle = new CircleF(Point2.Zero, 1);
Assert.True(rectangle.Intersects(circle));
@@ -117,7 +117,7 @@ public class ShapeTests
* :
* :
*/
IShapeF rectangle = new OrientedRectangle(Point2.Zero, new Size2(1, 1), Matrix2.Identity);
IShapeF rectangle = new OrientedRectangle(Point2.Zero, new Size2(1, 1), Matrix3x2.Identity);
var circle = new CircleF(new Point2(-2, 1), .99f);
Assert.False(rectangle.Intersects(circle));
@@ -135,7 +135,7 @@ public class ShapeTests
* * *
* :* *
*/
IShapeF rectangle = new OrientedRectangle(new Point2(-1, 1), new Size2(1.42f, 1.42f), Matrix2.CreateRotationZ(-MathHelper.PiOver4));
IShapeF rectangle = new OrientedRectangle(new Point2(-1, 1), new Size2(1.42f, 1.42f), Matrix3x2.CreateRotationZ(-MathHelper.PiOver4));
var circle = new CircleF(new Point2(1, -1), 1.4f);
Assert.False(rectangle.Intersects(circle));
@@ -153,7 +153,7 @@ public class ShapeTests
* :**
* :
*/
IShapeF rectangle = new OrientedRectangle(new Point2(-1, 0), new Size2(1, 1), Matrix2.Identity);
IShapeF rectangle = new OrientedRectangle(new Point2(-1, 0), new Size2(1, 1), Matrix3x2.Identity);
var rect = new RectangleF(new Point2(0.001f, 0), new Size2(2, 2));
Assert.False(rectangle.Intersects(rect));
@@ -171,7 +171,7 @@ public class ShapeTests
* :**
* :
*/
IShapeF rectangle = new OrientedRectangle(new Point2(-1, 0), new Size2(1, 1), Matrix2.Identity);
IShapeF rectangle = new OrientedRectangle(new Point2(-1, 0), new Size2(1, 1), Matrix3x2.Identity);
var rect = new RectangleF(new Point2(0, 0), new Size2(2, 2));
Assert.True(rectangle.Intersects(rect));