Collision detection between spheres

Started by
0 comments, last by Zakwayda 14 years, 3 months ago
Hello, I want to find when a collision between a static and a moving ball occurs, but the algorithm I came up with, sometimes doesn't detect a collision and the moving ball goes through the static one. The moving ball is affected by gravity and the static one is not. Here's my collision detection code:

    GLfloat whenSpheresCollide(const sphere2d &firstSphere, const sphere2d &secondSphere)
    {
    	Vector2f relativePosition = subtractVectors(firstSphere.vPosition, secondSphere.vPosition);
    	Vector2f relativeVelocity = subtractVectors(firstSphere.vVelocity, secondSphere.vVelocity);
    	
    	GLfloat radiusSum = firstSphere.radius + secondSphere.radius;
    	
    	//We'll find the time when objects collide if a collision takes place
    	
    	//r(t) = P[0] + t * V[0]
    	//
    	//d^2(t) = P[0]^2 + 2 * t * P[0] * V[0] + t^2 * V[0]^2
    	//
    	//d^2(t) = V[0]^2 * t^2 + 2t( P[0] . V[0] ) + P[0]^2
    	//
    	//d(t) = R
    	//
    	//d(t)^2 = R^2
    	//
    	//V[0]^2 * t^2 + 2t( P[0] . V[0] ) + P[0]^2 - R^2 = 0
    	//
    	//delta = ( P[0] . V[0] )^2 - V[0]^2 * (P[0]^2 - R^2)
    	//
    	//	We are interested in the lowest t:
    	//
    	//t = ( -( P[0] . V[0] ) - sqrt(delta) ) / V[0]^2
    	//
    	
    	GLfloat equationDelta = squaref( dotProduct(relativePosition, relativeVelocity) ) - squarev( relativeVelocity ) * ( squarev( relativePosition ) - squaref(radiusSum)  );
    	
    	if (equationDelta >= 0.0f)
    	{
    		GLfloat collisionTime = ( - dotProduct(relativePosition, relativeVelocity) - sqrtf(equationDelta) ) / squarev(relativeVelocity);
    		
    		if (collisionTime >= 0.0f && collisionTime <= 1.0f / GAME_FPS)
    		{
    			return collisionTime;
    		}
    	}
    	
    	return -1.0f;
    }


And here is the updating function that calls collision detection:

    void GamePhysicsManager::updateBallPhysics()
    {
    	//
    	//Update velocity
    	vVelocity->y -= constG / GAME_FPS;	//v = a * t = g * 1 sec / (updates per second)
    	
    	shouldApplyForcesToBall = TRUE;
    	
    	vPosition->x += vVelocity->x / GAME_FPS;
    	vPosition->y += vVelocity->y / GAME_FPS;

    	if ( distanceBetweenVectors( *pBall->getPositionVector(), *pBasket->getPositionVector() ) <= pBasket->getRadius() + vectorLength(*vVelocity) / GAME_FPS )
    	{
    		//Ball sphere
    		sphere2d ballSphere;
    		ballSphere.radius = pBall->getRadius();
    		ballSphere.mass = 1.0f;
    		ballSphere.vPosition = *( pBall->getPositionVector() );
    		ballSphere.vVelocity = *( pBall->getVelocityVector() );
    		
    		
    		sphere2d ringSphereRight;
    		ringSphereRight.radius = 0.05f;
    		ringSphereRight.mass = -1.0f;
    		ringSphereRight.vPosition = *( pBasket->getPositionVector() );
    		//ringSphereRight.vPosition.x += pBasket->getRadius();
    		ringSphereRight.vPosition.x += (pBasket->getRadius() - ringSphereRight.radius);
    		ringSphereRight.vVelocity = zeroVector();
    		
    		
    		GLfloat collisionTime = whenSpheresCollide(ballSphere, ringSphereRight);
    		
    		if ( collisionTime >= 0.0f )
    		{
    			DebugLog("collision");
    			respondToCollision(&ballSphere, &ringSphereRight, collisionTime, pBall->getRestitution() * 0.75f );
    		}
    				
    		//
    		//Implement selection of the results that are first to collide collision
    		
    		vVelocity->x = ballSphere.vVelocity.x;
    		vVelocity->y = ballSphere.vVelocity.y;
    		
    		vPosition->x = ballSphere.vPosition.x;
    		vPosition->y = ballSphere.vPosition.y;
    	}


Problem seems to be solved when I change FPS from 30 to 10. How does FPS affect my collision detection? Why isn't the collision being detected in 100% of cases? It's being detected only in 70% of cases. Thanks.
Advertisement
I didn't review the code, but I can make a couple of suggestions as to how you might go about debugging.

The first thing I'd probably do is try to isolate the problem to determine whether it's an error in the intersection algorithm, an error in the intersection function implementation, or an error in how the simulation is being handled.

Since the swept sphere-sphere test can be implemented as a sphere raycast (and it looks like this is how you're doing it), a good first step might be write a simple sphere raycast function and then test it thoroughly to make sure it's correct. Then, you can write the sphere-sphere test in terms of the sphere raycast test, and test *that* function under various circumstances. (When I was writing a lot of this kind of code, I'd set up a test bed where you could use the mouse to assign start and end positions for the objects in the scene, and then run a simulation step to see if collisions were detected correctly.)

If you've determined that the intersection function is correct and it's still not working, then presumably the problem is in how you're handling the simulation and/or the collision data itself.

If you could break some of the longer lines, I'd be happy to take a look at the code (I have my monitor set at 1024x768 right now, so longer lines mean having to scroll back and forth to read code samples).

This topic is closed to new replies.

Advertisement