diff --git a/.gitignore b/.gitignore index fb2d7c28..a58de14f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ # Rider .idea/ +*.user # macOS .DS_Store diff --git a/src/cs/MonoGame.Extended/Math/PrimitivesHelper.cs b/src/cs/MonoGame.Extended/Math/PrimitivesHelper.cs index 543d23d0..ef151bcb 100644 --- a/src/cs/MonoGame.Extended/Math/PrimitivesHelper.cs +++ b/src/cs/MonoGame.Extended/Math/PrimitivesHelper.cs @@ -65,10 +65,10 @@ namespace MonoGame.Extended // Real-Time Collision Detection, Christer Ericson, 2005. Chapter 4.2; Bounding Volumes - Axis-aligned Bounding Boxes (AABBs). pg 86-87 center = transformMatrix.Transform(center); - halfExtents.X = halfExtents.X * Math.Abs(transformMatrix.M11) + halfExtents.X * Math.Abs(transformMatrix.M12) + - halfExtents.X * Math.Abs(transformMatrix.M31); - halfExtents.Y = halfExtents.Y * Math.Abs(transformMatrix.M21) + halfExtents.Y * Math.Abs(transformMatrix.M22) + - halfExtents.Y * Math.Abs(transformMatrix.M32); + var xRadius = halfExtents.X; + var yRadius = halfExtents.Y; + halfExtents.X = xRadius * Math.Abs(transformMatrix.M11) + yRadius * Math.Abs(transformMatrix.M12); + halfExtents.Y = xRadius * Math.Abs(transformMatrix.M21) + yRadius * Math.Abs(transformMatrix.M22); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -109,7 +109,7 @@ namespace MonoGame.Extended internal static void ClosestPointToPointFromRectangle(Point2 minimum, Point2 maximum, Point2 point, out Point2 result) { // Real-Time Collision Detection, Christer Ericson, 2005. Chapter 5.1.2; Basic Primitive Tests - Closest-point Computations. pg 130-131 - + result = point; // For each coordinate axis, if the point coordinate value is outside box, clamp it to the box, else keep it as is @@ -125,4 +125,4 @@ namespace MonoGame.Extended } } -} \ No newline at end of file +} diff --git a/src/cs/Tests/MonoGame.Extended.Tests/Primitives/RectangleFTests.cs b/src/cs/Tests/MonoGame.Extended.Tests/Primitives/RectangleFTests.cs index 92d1370f..9121d6ad 100644 --- a/src/cs/Tests/MonoGame.Extended.Tests/Primitives/RectangleFTests.cs +++ b/src/cs/Tests/MonoGame.Extended.Tests/Primitives/RectangleFTests.cs @@ -1,45 +1,135 @@ -//using Microsoft.Xna.Framework; -//using Xunit; +using Microsoft.Xna.Framework; +using Xunit; -//namespace MonoGame.Extended.Tests.Primitives -//{ -// -// public class RectangleFTests -// { -// [Fact] -// public void RectangleF_Intersects_Test() -// { -// var rect1 = new RectangleF(0, 0, 32, 32); -// var rect2 = new RectangleF(32, 32, 32, 32); +namespace MonoGame.Extended.Tests.Primitives +{ + public class RectangleFTests + { + [Fact] + public void Rectangle_Intersects_Test() + { + var rect1 = new Rectangle(0, 0, 32, 32); + var rect2 = new Rectangle(32, 32, 32, 32); -// Assert.IsFalse(rect1.Intersects(rect2)); -// } + Assert.False(rect1.Intersects(rect2)); + } -// [Fact] -// public void Rectangle_Intersects_Test() -// { -// var rect1 = new Rectangle(0, 0, 32, 32); -// var rect2 = new Rectangle(32, 32, 32, 32); + [Fact] + public void PassVector2AsConstructorParameter_Test() + { + var rect1 = new RectangleF(new Vector2(0, 0), new Size2(12.34f, 56.78f)); + var rect2 = new RectangleF(new Vector2(0, 0), new Vector2(12.34f, 56.78f)); -// Assert.IsFalse(rect1.Intersects(rect2)); -// } + Assert.Equal(rect1, rect2); + } -// [Fact] -// public void PassVector2AsConstructorParameter_Test() -// { -// var rect1 = new RectangleF(new Vector2(0, 0), new Size2(12.34f, 56.78f)); -// var rect2 = new RectangleF(new Vector2(0, 0), new Vector2(12.34f, 56.78f)); + [Fact] + public void PassPointAsConstructorParameter_Test() + { + var rect1 = new RectangleF(new Vector2(0, 0), new Size2(12, 56)); + var rect2 = new RectangleF(new Vector2(0, 0), new Size2(12, 56)); -// Assert.Equal(rect1, rect2); -// } + Assert.Equal(rect1, rect2); + } -// [Fact] -// public void PassPointAsConstructorParameter_Test() -// { -// var rect1 = new RectangleF(new Vector2(0, 0), new Size2(12, 56)); -// var rect2 = new RectangleF(new Vector2(0, 0), new Size2(12, 56)); + public class Transform + { + [Fact] + public void Center_point_is_not_translated() + { + var rectangle = new RectangleF(new Point2(0, 0), new Size2(20, 30)); + var transform = Matrix2.Identity; -// Assert.Equal(rect1, rect2); -// } -// } -//} \ No newline at end of file + var result = RectangleF.Transform(rectangle, ref transform); + + Assert.Equal(new Point2(10, 15), result.Center); + } + + [Fact] + 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 result = RectangleF.Transform(rectangleF, ref transform); + + Assert.Equal(new Point2(11, 17), result.Center); + } + + [Fact] + 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 result = RectangleF.Transform(rectangle, ref transform); + + Assert.Equal(new Size2(20, 30), result.Size); + } + + [Fact] + 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 result = RectangleF.Transform(rectangle, ref transform); + + Assert.Equal(new Size2(20, 30), result.Size); + } + + [Fact] + public void Applies_rotation_and_translation() + { + /* Rectangle with center point aligned in coordinate system with origin 0. + * + * : + * : + * +-+ + * | | + * |p| + * | | + * ...............0-+............ + * : + * : + * : + * + * Rotate center point p, 90 degrees around origin 0. + * + * : + * : + * +---+ + * | p | + * ...........+---0.............. + * : + * : + * : + * + * Then translate rectangle by x=10 and y=20. + * : + * : +---+ + * : | p | + * y=21 - - - - - - - -> +---+ + * . + * : + * ...............0.............. + * : + * : + * : + */ + var rectangle = new RectangleF(new Point2(0, 0), new Size2(2, 4)); + var transform = + Matrix2.CreateRotationZ(MathHelper.PiOver2) + * + Matrix2.CreateTranslation(10, 20); + + var result = RectangleF.Transform(rectangle, ref transform); + + Assert.Equal(-2 + 10, result.Center.X, 6); + Assert.Equal(1 + 20, result.Center.Y, 6); + Assert.Equal(4, result.Size.Width, 6); + Assert.Equal(2, result.Size.Height, 6); + } + } + } +}