First loop through all the edges of the box. Check the intersection between the line and circle ( It can be done easily with a quadratic equation)
The algorythm will determine wether the circle intersects or not the box , and also calculates the intersection point.
The contact normal will be the colliding edges' left (or right) normal...
here's a pseudo code :
Code: Select all
bool CIrcle::isCircleIntersectiongTheBox(Box box)
{
for (int edgeIndex = 0; edgeIndex < 4; edgeIndex++)
{
Vector2 result1 ,result2;
if (quadratic(box.getEdge(edgeIndex) , result1 , result2))
{
// Hurray there are intersecting !
// The intersection is stored in the 'result1 and result2
}
}
}
bool CIrcle::qudratic(Edge edge , Vector result1 , Vector result2)
{
// calculate a vector from the circle center to the edge's p0 point (the closest to the origin)
vector pc = edge.p0 - center;
// A * A + B * B + C = 0;
// Where :
float A = edge.getLengthVector().dot(edge.getLengthVector());
float B = edge.p0.dot(edge.p0);
float C = pc.dot(pc)
// Now need to calcualte the discriminant with the qudratic eq solver :
float disc = B * B - 4 * A * C;
// now if disc < 0 , there's no intersection.
// if disc == 0 there is one solution (the circle exacly touches the edge)
// if disc > 0 there are two solutions. (the circle is intersecting the line)
// We will handle the case when disc > 0.
// And the intersection point will be :
// calculate the time :
if (disc > 0)
{
float t1 = (-B + sqrtf(disc)) / (2 * A);
float t2 = (-B - sqrtf(disc)) / (2 * A);
result1 = edge.p0 + ((edge.p1 - edge.p0) * t1);
result2 = edge.p0 + ((edge.p1 - edge.p0) * t2);
return true;
}
return false;
}
EDIT : BTW ,actually , you can't get the REAL contact normal , because you performing a static collision test. Since you have no velocity and without a velocity vector you can't determine the contact normal.