Collision Response

Started by
4 comments, last by tthibault 18 years, 6 months ago
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.
Advertisement
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.
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.
Here's an excellent link that should help you:

http://www.peroxide.dk/papers/collision/collision.pdf



-Steve.
Steve Broumley
Hi there.
Got it working better now. Still work to do but its on the right track now.
Thanks for the info mate.
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.
...and do not wildly extrapolate. Just because Saddam Hussein gassed Kurds in 1990 doesn't mean he eats babies' brains.

This topic is closed to new replies.

Advertisement