AABB vs OBB Collision Resolution jitter on corners
- by patt4179
I've implemented a collision library for a character who is an AABB and am resolving collisions between AABB vs AABB and AABB vs OBB. I wanted slopes for certain sections, so I've toyed around with using several OBBs to make one, and it's working great except for one glaring issue; The collision resolution on the corner of an OBB makes the player's AABB jitter up and down constantly. I've tried a few things I've thought of, but I just can't wrap my head around what's going on exactly. Here's a video of what's happening as well as my code:
Here's the function to get the collision resolution (I'm likely not doing this the right way, so this may be where the issue lies):
public Vector2 GetCollisionResolveAmount(RectangleCollisionObject resolvedObject, OrientedRectangleCollisionObject b)
{
Vector2 overlap = Vector2.Zero;
LineSegment edge = GetOrientedRectangleEdge(b, 0);
if (!SeparatingAxisForRectangle(edge, resolvedObject))
{
LineSegment rEdgeA = new LineSegment(), rEdgeB = new LineSegment();
Range axisRange = new Range(), rEdgeARange = new Range(), rEdgeBRange = new Range(), rProjection = new Range();
Vector2 n = edge.PointA - edge.PointB;
rEdgeA.PointA = RectangleCorner(resolvedObject, 0);
rEdgeA.PointB = RectangleCorner(resolvedObject, 1);
rEdgeB.PointA = RectangleCorner(resolvedObject, 2);
rEdgeB.PointB = RectangleCorner(resolvedObject, 3);
rEdgeARange = ProjectLineSegment(rEdgeA, n);
rEdgeBRange = ProjectLineSegment(rEdgeB, n);
rProjection = GetRangeHull(rEdgeARange, rEdgeBRange);
axisRange = ProjectLineSegment(edge, n);
float axisMid = (axisRange.Maximum + axisRange.Minimum) / 2;
float projectionMid = (rProjection.Maximum + rProjection.Minimum) / 2;
if (projectionMid > axisMid)
{
overlap.X = axisRange.Maximum - rProjection.Minimum;
}
else
{
overlap.X = rProjection.Maximum - axisRange.Minimum;
overlap.X = -overlap.X;
}
}
edge = GetOrientedRectangleEdge(b, 1);
if (!SeparatingAxisForRectangle(edge, resolvedObject))
{
LineSegment rEdgeA = new LineSegment(), rEdgeB = new LineSegment();
Range axisRange = new Range(), rEdgeARange = new Range(), rEdgeBRange = new Range(), rProjection = new Range();
Vector2 n = edge.PointA - edge.PointB;
rEdgeA.PointA = RectangleCorner(resolvedObject, 0);
rEdgeA.PointB = RectangleCorner(resolvedObject, 1);
rEdgeB.PointA = RectangleCorner(resolvedObject, 2);
rEdgeB.PointB = RectangleCorner(resolvedObject, 3);
rEdgeARange = ProjectLineSegment(rEdgeA, n);
rEdgeBRange = ProjectLineSegment(rEdgeB, n);
rProjection = GetRangeHull(rEdgeARange, rEdgeBRange);
axisRange = ProjectLineSegment(edge, n);
float axisMid = (axisRange.Maximum + axisRange.Minimum) / 2;
float projectionMid = (rProjection.Maximum + rProjection.Minimum) / 2;
if (projectionMid > axisMid)
{
overlap.Y = axisRange.Maximum - rProjection.Minimum;
overlap.Y = -overlap.Y;
}
else
{
overlap.Y = rProjection.Maximum - axisRange.Minimum;
}
}
return overlap;
}
And here is what I'm doing to resolve it right now:
if (collisionDetection.OrientedRectangleAndRectangleCollide(obb, player.PlayerCollision))
{
var resolveAmount = collisionDetection.GetCollisionResolveAmount(player.PlayerCollision, obb);
if (Math.Abs(resolveAmount.Y) < Math.Abs(resolveAmount.X))
{
var roundedAmount = (float)Math.Floor(resolveAmount.Y);
player.PlayerCollision._position.Y -= roundedAmount;
}
else if (Math.Abs(resolveAmount.Y) <= 30.0f) //Catch cases where the player should be able to step over the top of something
{
var roundedAmount = (float)Math.Floor(resolveAmount.Y);
player.PlayerCollision._position.Y -= roundedAmount;
}
else
{
var roundedAmount = (float)Math.Floor(resolveAmount.X);
player.PlayerCollision._position.X -= roundedAmount;
}
}
Can anyone see what might be the issue here, or has anyone experienced this before that knows a possible solution? I've tried for a few days to figure this out on my own, but I'm just stumped.