change how multishape shapes are transformed and add point sweep test

multishape
Evan Hemsley 2020-01-05 21:36:31 -08:00
parent 17084154a2
commit 7875342da8
4 changed files with 25 additions and 18 deletions

View File

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Numerics;
using MoonTools.Core.Structs; using MoonTools.Core.Structs;
namespace MoonTools.Core.Bonk namespace MoonTools.Core.Bonk
@ -22,11 +23,17 @@ namespace MoonTools.Core.Bonk
return AABB.Transformed(AABB, transform); return AABB.Transformed(AABB, transform);
} }
public IEnumerable<(IShape2D, Transform2D)> TransformedShapeTransforms(Transform2D transform) /// <summary>
/// Moves the shapes by pivoting with an offset transform.
/// </summary>
/// <param name="offsetTransform"></param>
/// <returns></returns>
public IEnumerable<(IShape2D, Transform2D)> TransformShapesUsingOffset(Transform2D offsetTransform)
{ {
foreach (var (shape, shapeTransform) in ShapeTransformPairs) foreach (var (shape, shapeTransform) in ShapeTransformPairs)
{ {
yield return (shape, transform.Compose(shapeTransform)); var newTransform = new Transform2D(Vector2.Transform(shapeTransform.Position, offsetTransform.TransformMatrix), offsetTransform.Rotation, offsetTransform.Scale);
yield return (shape, newTransform);
} }
} }

View File

@ -70,7 +70,7 @@ namespace MoonTools.Core.Bonk
/// <returns></returns> /// <returns></returns>
public static bool TestCollision(MultiShape multiShape, Transform2D multiShapeTransform, IShape2D shape, Transform2D shapeTransform) public static bool TestCollision(MultiShape multiShape, Transform2D multiShapeTransform, IShape2D shape, Transform2D shapeTransform)
{ {
foreach (var (otherShape, otherTransform) in multiShape.TransformedShapeTransforms(multiShapeTransform)) foreach (var (otherShape, otherTransform) in multiShape.TransformShapesUsingOffset(multiShapeTransform))
{ {
if (TestCollision(shape, shapeTransform, otherShape, otherTransform)) { return true; } if (TestCollision(shape, shapeTransform, otherShape, otherTransform)) { return true; }
} }
@ -88,7 +88,7 @@ namespace MoonTools.Core.Bonk
/// <returns></returns> /// <returns></returns>
public static bool TestCollision(IShape2D shape, Transform2D shapeTransform, MultiShape multiShape, Transform2D multiShapeTransform) public static bool TestCollision(IShape2D shape, Transform2D shapeTransform, MultiShape multiShape, Transform2D multiShapeTransform)
{ {
foreach (var (otherShape, otherTransform) in multiShape.TransformedShapeTransforms(multiShapeTransform)) foreach (var (otherShape, otherTransform) in multiShape.TransformShapesUsingOffset(multiShapeTransform))
{ {
if (TestCollision(shape, shapeTransform, otherShape, otherTransform)) { return true; } if (TestCollision(shape, shapeTransform, otherShape, otherTransform)) { return true; }
} }
@ -106,9 +106,9 @@ namespace MoonTools.Core.Bonk
/// <returns></returns> /// <returns></returns>
public static bool TestCollision(MultiShape multiShapeA, Transform2D transformA, MultiShape multiShapeB, Transform2D transformB) public static bool TestCollision(MultiShape multiShapeA, Transform2D transformA, MultiShape multiShapeB, Transform2D transformB)
{ {
foreach (var (shapeA, shapeTransformA) in multiShapeA.TransformedShapeTransforms(transformA)) foreach (var (shapeA, shapeTransformA) in multiShapeA.TransformShapesUsingOffset(transformA))
{ {
foreach (var (shapeB, shapeTransformB) in multiShapeB.TransformedShapeTransforms(transformB)) foreach (var (shapeB, shapeTransformB) in multiShapeB.TransformShapesUsingOffset(transformB))
{ {
if (TestCollision(shapeA, shapeTransformA, shapeB, shapeTransformB)) { return true; } if (TestCollision(shapeA, shapeTransformA, shapeB, shapeTransformB)) { return true; }
} }

View File

@ -1,26 +1,21 @@
using System; using System;
using System.Numerics; using System.Numerics;
using MoonTools.Core.Structs;
namespace MoonTools.Core.Bonk namespace MoonTools.Core.Bonk
{ {
public struct SweepResult<T, U> where T : IEquatable<T> where U : struct, IShape2D public struct SweepResult<T> where T : IEquatable<T>
{ {
public static SweepResult<T, U> False = new SweepResult<T, U>(); public static SweepResult<T> False = new SweepResult<T>();
public bool Hit { get; } public bool Hit { get; }
public Vector2 Motion { get; } public Vector2 Motion { get; }
public T ID { get; } public T ID { get; }
public U Shape { get; }
public Transform2D Transform { get; }
public SweepResult(bool hit, Vector2 motion, T id, U shape, Transform2D transform) public SweepResult(bool hit, Vector2 motion, T id)
{ {
Hit = hit; Hit = hit;
Motion = motion; Motion = motion;
ID = id; ID = id;
Shape = shape;
Transform = transform;
} }
} }
} }

View File

@ -7,7 +7,7 @@ namespace MoonTools.Core.Bonk
public static class SweepTest public static class SweepTest
{ {
/// <summary> /// <summary>
/// Performs a sweep test on rectangles. Returns the position 1 pixel before overlap occurs. /// Performs a sweep test on and against rectangles. Returns the position 1 pixel before overlap occurs.
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="spatialHash">A spatial hash.</param> /// <param name="spatialHash">A spatial hash.</param>
@ -15,7 +15,7 @@ namespace MoonTools.Core.Bonk
/// <param name="transform">A transform by which to transform the IHasAABB2D.</param> /// <param name="transform">A transform by which to transform the IHasAABB2D.</param>
/// <param name="ray">Given in world-space.</param> /// <param name="ray">Given in world-space.</param>
/// <returns></returns> /// <returns></returns>
public static SweepResult<T, Rectangle> Rectangle<T>(SpatialHash<T> spatialHash, Rectangle rectangle, Transform2D transform, Vector2 ray) where T : IEquatable<T> public static SweepResult<T> Test<T>(SpatialHash<T> spatialHash, Rectangle rectangle, Transform2D transform, Vector2 ray) where T : IEquatable<T>
{ {
var transformedAABB = rectangle.TransformedAABB(transform); var transformedAABB = rectangle.TransformedAABB(transform);
var sweepBox = SweepBox(transformedAABB, ray); var sweepBox = SweepBox(transformedAABB, ray);
@ -108,14 +108,19 @@ namespace MoonTools.Core.Bonk
var overlapPosition = ray * shortestDistance; var overlapPosition = ray * shortestDistance;
var correctionX = -Math.Sign(ray.X); var correctionX = -Math.Sign(ray.X);
var correctionY = -Math.Sign(ray.Y); var correctionY = -Math.Sign(ray.Y);
return new SweepResult<T, Rectangle>(true, new Position2D((int)overlapPosition.X + correctionX, (int)overlapPosition.Y + correctionY), nearestID, nearestRectangle.Value, nearestTransform.Value); return new SweepResult<T>(true, new Position2D((int)overlapPosition.X + correctionX, (int)overlapPosition.Y + correctionY), nearestID);
} }
else else
{ {
return SweepResult<T, Rectangle>.False; return SweepResult<T>.False;
} }
} }
public static SweepResult<T> Test<T>(SpatialHash<T> spatialHash, Point point, Transform2D transform, Vector2 ray) where T : IEquatable<T>
{
return Test(spatialHash, new Rectangle(0, 0), transform, ray);
}
private static AABB SweepBox(AABB aabb, Vector2 ray) private static AABB SweepBox(AABB aabb, Vector2 ray)
{ {
return new AABB( return new AABB(