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.Immutable;
using System.Numerics;
using MoonTools.Core.Structs;
namespace MoonTools.Core.Bonk
@ -22,11 +23,17 @@ namespace MoonTools.Core.Bonk
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)
{
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>
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; }
}
@ -88,7 +88,7 @@ namespace MoonTools.Core.Bonk
/// <returns></returns>
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; }
}
@ -106,9 +106,9 @@ namespace MoonTools.Core.Bonk
/// <returns></returns>
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; }
}

View File

@ -1,26 +1,21 @@
using System;
using System.Numerics;
using MoonTools.Core.Structs;
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 Vector2 Motion { 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;
Motion = motion;
ID = id;
Shape = shape;
Transform = transform;
}
}
}

View File

@ -7,7 +7,7 @@ namespace MoonTools.Core.Bonk
public static class SweepTest
{
/// <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>
/// <typeparam name="T"></typeparam>
/// <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="ray">Given in world-space.</param>
/// <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 sweepBox = SweepBox(transformedAABB, ray);
@ -108,14 +108,19 @@ namespace MoonTools.Core.Bonk
var overlapPosition = ray * shortestDistance;
var correctionX = -Math.Sign(ray.X);
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
{
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)
{
return new AABB(