private static bool TestAABBAABB(Shape2D s1, Shape2D s2, ref Contact2D contact)
{
CD_AABB2D a = (CD_AABB2D)s1;
CD_AABB2D b = (CD_AABB2D)s2;
// Minimum Translation Vector parameters
float mtv_Distance = float.MaxValue; // Set current minimum distance (max float value so next value is always less)
Vector2 mtv_Axis = Vector2.Zero; // Axis along which to travel with the minimum distance
// Clip length of ray to the segment boundaries
// Initialise times of first and last contact
float t_Enter = 0.0f; // Time of entry (for ray)
float t_Exit = 1.0f; // Time of exit (for ray)
if (!IntersectThruAxisSwept(Vector2.UnitX, a, b, ref t_Enter, ref t_Exit, ref mtv_Distance, ref mtv_Axis))
{
return false;
}
if (!IntersectThruAxisSwept(Vector2.UnitY, a, b, ref t_Enter, ref t_Exit, ref mtv_Distance, ref mtv_Axis))
{
return false;
}
// Calculate Minimum Translation Vector (MTV)
Vector2 d = a.Position - b.Position;
mtv_Axis = Vector2.Dot(d, mtv_Axis) < 0 ? -mtv_Axis : mtv_Axis;
contact.normal = mtv_Axis;
contact.penetration = Math.Abs(mtv_Distance) + Math_Util.EPSILON;
contact.t_Enter = t_Enter;
contact.t_Exit = t_Exit;
// Objects are intersecting
return true;
}
private static bool IntersectThruAxisSwept(Vector2 axis, CD_AABB2D a, CD_AABB2D b, ref float t_Enter, ref float t_Exit, ref float mtv_Distance, ref Vector2 mtv_Axis)
{
Vector2 v = a.Velocity - b.Velocity;
if (v.LengthSquared() < 0.0001f)
{
return false;
}
float a_Min = float.MaxValue;
float a_Max = float.MinValue;
float b_Min = float.MaxValue;
float b_Max = float.MinValue;
a.CalculateSlab(axis, ref a_Min, ref a_Max);
b.CalculateSlab(axis, ref b_Min, ref b_Max);
// Find distance intervals for current two slabs
// Distance is between slab min/max values
float d_S0 = a_Min - b_Max;
float d_S1 = b_Min - a_Max;
// The distance is positive if the intervals do not overlap
// Must be >= to 0 and not > 0, otherwise MTV can equal Vector2.Zero and cause NaN
if (d_S0 > 0f || d_S1 > 0f)
{
return false;
}
// Current distance interval for slabs [A_Min, A_Max] and [B_Min, B_Max]
float d = (d_S0 > d_S1) ? -d_S0 : d_S1;
// If d is the smallest distance so far
if (Math.Abs(d) < Math.Abs(mtv_Distance))
{
// Store the distance and the current axis
mtv_Distance = d;
mtv_Axis = axis;
}
//===========================================================
//---[Swept Test]--------------------------------------------
//===========================================================
// Convert the slab for B into a 1D ray
float origin = (b_Max + b_Min) * 0.5f; // Origin of ray
float e = (b_Max - b_Min) * 0.5f; // Extent of slab B
float direction = Vector2.Dot(b.Velocity - a.Velocity, axis); // Direction of ray (projected onto current axis of separation)
// Expand the slab for A by the extent of the slab for B
// This transforms a slab/slab collision test into a ray/slab collision test
a_Min -= e;
a_Max += e;
// Do a 1 dimensional collision check on projected axis
return RaySlabIntersect(a_Min, a_Max, origin, direction, ref t_Enter, ref t_Exit);
}
private static bool RaySlabIntersect(float slab_Min, float slab_Max, float ray_Origin, float ray_End, ref float tb_Enter, ref float tb_Exit)
{
float ray_Direction = ray_End - ray_Origin;
// If ray is parallel to the slab
if (Math.Abs(ray_Direction) < float.Epsilon)
{
// Ray is parallel to slab, but NOT inside the slab
if (ray_Origin < slab_Min || ray_Origin > slab_Max)
{
return false;
}
}
else
{
// Compute intersection t value of ray with near and far plane of slab
float ood = 1.0f / ray_Direction;
float ts_Enter = (slab_Min - ray_Origin) * ood;
float ts_Exit = (slab_Max - ray_Origin) * ood;
// Make "ts_Enter" be intersection with near plane, "ts_Exit" with far plane
if (ts_Enter > ts_Exit)
{
Math_Util.Swap(ref ts_Enter, ref ts_Exit);
}
// Compute the intersection of slab intersection intervals
tb_Enter = Math.Max(tb_Enter, ts_Enter);
tb_Exit = Math.Min(tb_Exit, ts_Exit);
// Exit with no collision as soon as slab intersection becomes empty
if (tb_Enter > tb_Exit)
{
return false;
}
}
if (tb_Enter > 0 && tb_Enter < 1)
{
Console.WriteLine("STOP"); // NEVER happens, ever!
}
return true;
}
[C#] Why is t_Enter always 0?
When colliding with more than one object at the same time, I require the time of collision between two objects in order to resolve the collision correctly.
Here I have a test that correctly determines if two AABBs are intersecting, but the swept test using a ray always returns 0.0f for t_Enter:
Why am I not getting any collision times, other than 0 for the RaySlabIntersect?
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement