Sign in to follow this  
elnebuloso

Collision Response

Recommended Posts

Hi there. I have made a sphere collision system that returnes a list of collisions. The returned data for each collision in the list is: CollisionPoint in world space Normal for surface collided with So, my problem is now repositioning the sphere after collisions happen. I was wondering if there is a common way of dealing with this. I made some code to do the response myself but it is very long winded and possibly nonsense. Basically i am subtracting the distance between the centre of the sphere and the collision point from the sphere radius. This gives me how far the sphere has penetrated the surface (I think). I then scale the surface normal by the amount of penetration and add the result to the sphere position which pushes it away from the surface. This works when colliding with several surfaces at once as long as they are at 90 degrees to eachother (Like the corner of a room) but if i move the sphere down toward the narrow end of a wedge shaped room it will go through one of the walls. Hope that all makes sense. Any comments would be much appreciated.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
It is going through one of the walls because the collision response with the first wall is pushing it through the second wall.

One idea is to find any new collisions after performing the collision response, and then responding to them. Then wall 1 pushes the sphere into wall 2, which pushes it back out, and maybe in a bad case it gets bounced back and forth a few times. In the worst case this can cause an infinite loop, so putting a limit on the number of responses may be a good idea.

Share this post


Link to post
Share on other sites
Hi there.
Thanks for the help.

The collision is working better now (but not perfect yet).

I found an example of sphere collision on this site and looked through it. In that example it tests to see if a collision will occur if the sphere moves and if so it does some sliding code I think.

I started with a sphere triangle intersection example in a maths book and just sort of expanded it so at the minute it checks for intersections at the spheres current position.

I'm not sure what the best way to go is now. Is it better to avoid penetration by pre-empting the collisions or is it just a matter of what suits you.

Any thoughts would be much appreciated.

Share this post


Link to post
Share on other sites
I have written code which iterates spheres and checks if they are in contact and moving towrads each other. When this happens (a collision) I back the spheres up along their current trajectory to a 'safe' position (backpedaling). Pushing off in the direction of the normal to the collision isn't necessarily safe...this may cause you to go through other things.

What I've done instead is instead of doing sphere collision detetion by checking for overlaps, I just use swept sphere collision detection. This is the function i currently use to check to see when two spheres will collide, if ever. It uses math from 'mathematics for 3d game programming and comptuer graphics' pg 221. It returns a value between 0 and 1 if the spheres collide, otherwise a negative number.

It checks for collisions between two spheres 'P' and 'Q' where PStart is the starting position, etc. I added an 'epsilon' value such that you may want them not to be exactly touching when they collide, but with a little bit of breathing room to avoid any possible floating point weirdness.



double TimeOfSphereIntersection(Vector3D &PStart,Vector3D &PEnd,
Vector3D &QStart, Vector3D &QEnd,
double PRadius, double QRadius, double Epsilon)
{

Vector3D A = PStart - QStart;
Vector3D B = (PEnd - PStart) - (QEnd - QStart);

double ASq = A.BasicLength(); //Length squared
double AdotB = DotProduct(&A,&B);
double AdotB_sq = AdotB * AdotB;
double BSq = B.BasicLength();

double iBSq = BSq > .0000001f ? (1/BSq) : 1.0f; //Inverse of |B| squared

double sep_dist = PRadius + QRadius + Epsilon;

double sep_dist_sq = sep_dist * sep_dist;

double closest_sep_dist_sq = ASq - (AdotB_sq * iBSq);

if(closest_sep_dist_sq > sep_dist_sq)
{
COLLISION_DEBUG( trace << "closest_sep_dist_sq > sep_dist_sq, returning -1" << "\n"; )
return -1.0f;
}

double under_root = AdotB_sq - (BSq * (ASq - sep_dist_sq));

if(under_root < 0)
{
COLLISION_DEBUG( trace << "negative under radical, no sphere intersection, returning -2" << "\n"; )
return -2.0f;
}

double root = sqrt(under_root);
double time = (-AdotB - root) * iBSq;

if(time >= 1.0f)
{
COLLISION_DEBUG( trace << "Fishy value of time, greater or equal to 1.0f: " << time << "\n"; )
COLLISION_DEBUG( trace << "Root: " << root << "under_root: " << under_root << "AdotB: " << AdotB << "\n"; )
}

return time;
}




You should be able to quickly adopt this to work for you.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this