2019-10-25 10:46:47 +00:00
using Microsoft.Xna.Framework ;
2019-09-06 08:11:58 +00:00
using MoonTools.Core.Structs ;
2019-10-25 10:46:47 +00:00
using MoonTools.Core.Bonk.Extensions ;
2019-09-06 08:11:58 +00:00
namespace MoonTools.Core.Bonk
{
public static class GJK2D
{
2019-10-25 21:01:36 +00:00
/// <summary>
/// Tests if the two shape-transform pairs are overlapping.
/// </summary>
2019-10-25 10:46:47 +00:00
public static bool TestCollision ( IShape2D shapeA , Transform2D transformA , IShape2D shapeB , Transform2D transformB )
2019-09-06 08:11:58 +00:00
{
2019-10-25 19:37:25 +00:00
var minkowskiDifference = new MinkowskiDifference ( shapeA , transformA , shapeB , transformB ) ;
2019-10-25 20:09:03 +00:00
var a = minkowskiDifference . Support ( Vector2 . UnitX ) ;
var b = minkowskiDifference . Support ( - a ) ;
2019-09-06 08:11:58 +00:00
2019-10-25 20:09:03 +00:00
return Vector2 . Dot ( a , b ) > 0 ? false : CheckSimplex ( new Simplex ( minkowskiDifference , a , b ) ) ;
2019-10-25 10:46:47 +00:00
}
2019-09-06 08:11:58 +00:00
2019-10-25 20:09:03 +00:00
private static bool CheckSimplex ( Simplex simplex )
2019-10-25 10:46:47 +00:00
{
2019-10-25 20:09:03 +00:00
var a = simplex . DirectionA ;
var b = simplex . DirectionB ;
2019-09-06 08:11:58 +00:00
2019-10-25 20:09:03 +00:00
var axb = a . Cross ( b ) ;
var c = simplex . Support ( ( b - a ) . Perpendicular ( ) ) ;
var axc = a . Cross ( c ) ;
var bxc = b . Cross ( c ) ;
var cxb = - bxc ;
2019-09-06 08:11:58 +00:00
2019-10-25 20:09:03 +00:00
return ( b - a ) = = Vector2 . Zero | | ( axb . Y > 0 ! = bxc . Y > 0 ? CheckSimplex ( simplex . WithDirections ( b , c ) ) : ( axc . Y > 0 ! = cxb . Y > 0 ? CheckSimplex ( simplex . WithDirections ( a , c ) ) : true ) ) ;
2019-10-25 10:46:47 +00:00
}
2019-09-06 08:11:58 +00:00
2019-10-25 21:01:36 +00:00
/// <summary>
/// Tests if the two shape-transform pairs are overlapping, and returns a simplex that can be used by the EPA algorithm to determine a miminum separating vector.
/// </summary>
2019-10-25 20:09:03 +00:00
public static ( bool , Simplex ) FindCollisionSimplex ( IShape2D shapeA , Transform2D transformA , IShape2D shapeB , Transform2D transformB )
2019-10-25 10:46:47 +00:00
{
2019-10-25 20:09:03 +00:00
var minkowskiDifference = new MinkowskiDifference ( shapeA , transformA , shapeB , transformB ) ;
2019-10-25 19:37:25 +00:00
var a = minkowskiDifference . Support ( Vector2 . UnitX ) ;
var b = minkowskiDifference . Support ( - a ) ;
2019-09-06 08:11:58 +00:00
2019-10-25 20:09:03 +00:00
return Vector2 . Dot ( a , b ) > 0 ? ( false , default ( Simplex ) ) : Simplex ( new Simplex ( minkowskiDifference , a , b ) ) ;
2019-10-25 10:46:47 +00:00
}
2019-09-06 08:11:58 +00:00
2019-10-25 20:09:03 +00:00
private static ( bool , Simplex ) Simplex ( Simplex simplex )
2019-10-25 10:46:47 +00:00
{
2019-10-25 20:09:03 +00:00
var a = simplex . DirectionA ;
var b = simplex . DirectionB ;
2019-09-06 08:11:58 +00:00
2019-10-25 10:46:47 +00:00
if ( ( b - a ) = = Vector2 . Zero )
{
2019-10-25 20:09:03 +00:00
return ( false , simplex . WithDirections ( a , b ) ) ;
2019-10-25 10:46:47 +00:00
}
else
{
2019-10-25 20:09:03 +00:00
var c = simplex . Support ( ( b - a ) . Perpendicular ( ) ) ;
2019-10-25 10:46:47 +00:00
var axb = a . Cross ( b ) ;
var bxc = b . Cross ( c ) ;
if ( axb . Y > 0 ! = bxc . Y > 0 )
{
2019-10-25 20:09:03 +00:00
return Simplex ( simplex . WithDirections ( b , c ) ) ;
2019-10-25 10:46:47 +00:00
}
else
{
var axc = a . Cross ( c ) ;
var cxb = - bxc ;
if ( axc . Y > 0 ! = cxb . Y > 0 )
2019-09-06 08:11:58 +00:00
{
2019-10-25 20:09:03 +00:00
return Simplex ( simplex . WithDirections ( a , b ) ) ;
2019-09-06 08:11:58 +00:00
}
else
{
2019-10-25 20:09:03 +00:00
return ( true , simplex . WithDirections ( a , b ) ) ;
2019-09-06 08:11:58 +00:00
}
2019-10-25 10:46:47 +00:00
}
2019-09-06 08:11:58 +00:00
}
}
}
}