Sphere-Sphere sweep problem

Started by
1 comment, last by Bhewnobu 12 years, 4 months ago
Hi, i have been making a simple physics simulation with spheres and it works well but in some situations the sweep test I use fails.


// sphere-sphere sweep
// ((p2 + t * v2) - (p1 + t * v1)) * ((p2 + t * v2) - (p1 + t * v1)) = (r1 + r2)^2
// (p2 + t * v2 - p1 - t * v1) * (p2 + t * v2 - p1 - t * v1) = (r1 + r2)^2
// (p2 - p1 + t * (v2 - v1)) * (p2 - p1 + t * (v2 - v1)) = (r1 + r2)^2
// |p2|^2 - 2(p2 dot p1) + t * 2(p2 dot (v2 - v1)) + |p1|^2 - t * 2(p1 dot (v2 - v1)) + (v2 - v1)(v2 - v1) * t^2 = (r1 + r2)^2

// a = (v2 - v1)(v2 - v1)

// b = 2(p2 dot (v2 - v1)) - 2(p1 dot (v2 - v1))
// b = 2(p2 dot (v2 - v1) - p1 dot (v2 - v1))
// b = 2((p2 - p1) dot (v2 - v1))

// c = |p2|^2 - 2(p2 dot p1) + |p1|^2 - (r1 + r2)^2
// c = (p2 dot p2) - 2(p2 dot p1) + (p1 dot p1) - (r1 + r2)^2
// c = (p2 dot p2 - 2 * p2 dot p1 + p1 dot p1) - (r1 + r2)^2
// c = (p2 - p1)(p2 - p1) - (r1 + r2)^2

void CBallManager::CheckCollision(BALL_COLLISION *info)
{
D3DXVECTOR3 vel1 = info->ball1->m_vel * info->dt; //multiply by delta time so it doesnt detect the collision too early
D3DXVECTOR3 vel2 = info->ball2->m_vel * info->dt;

D3DXVECTOR3 vel12 = vel2 - vel1;
if(D3DXVec3LengthSq(&vel12) == 0.0f) //if the balls have equal velocity they cant collide
{
info->collision = false;
return;
}

D3DXVECTOR3 pos12 = info->ball2->m_pos - info->ball1->m_pos;
float r12 = info->ball1->m_radius + info->ball2->m_radius;
float t;

float a = D3DXVec3Dot(&vel12, &vel12);
float b = 2.0f * D3DXVec3Dot(&pos12, &vel12);
float c = D3DXVec3Dot(&pos12, &pos12) - (r12 * r12);
if(GetLowestRoot(a, b, c, t)) //this solves the quadratic and returns the lowest root in t if there is any
{
if(t > 0.0f && t < 1.0f) //if the collision happened in between time moments 0 and 1
{
info->t = t;
info->cPos1 = info->ball1->m_pos + t * vel1; //calculate some stuff for the collision response
info->cPos2 = info->ball2->m_pos + t * vel2;
D3DXVECTOR3 dir = info->cPos2 - info->cPos1;
D3DXVec3Normalize(&dir, &dir);
info->collisionPoint = info->cPos1 + info->ball1->m_radius * dir;

info->d1 = D3DXVec3Length(&(info->cPos1 - info->ball1->m_pos));
info->d2 = D3DXVec3Length(&(info->cPos2 - info->ball2->m_pos));

info->collision = true;
}
}
else
info->collision = false; //no collision occurred
}

Heres the code I use for the sweep, I understand how it works and so on, i have written that code myself and I reduced the equation for fun at the top and it equals the equation that i found in internet so it should be correct. The problem appears when 2 spheres move directly towards each other so that the movement is aligned with X, Y or Z axis. For example if I have a sphere at position (0, 0, 0) with velocity also (0, 0, 0) so its staying still, and other sphere at (100, 0, 0) moving with velocity (-5.0f, 0, 0) directly towards it they will just go through each other. This doesnt happen if they are moving directly towards each other in a arbitrary angle. Is there some mistake in my code or has someone else had the same problem?
Advertisement


if(t > 0.0f && t < 1.0f) //if the collision happened in between time moments 0 and 1



Why do you ignore collisions that happen at t==1.0f? I suspect that's what's happening in your case. This should be able to verify with a debugger, however.
I changed it to t <= 1.0f and its working well :) Thanks for the response, I just had implemented the ellipsoid collision system from here and it used t < 1.0f in the sample code. I managed to get 2 spheres go through each other at some random angle but i guess thats caused by the collision response code that ill check next.

This topic is closed to new replies.

Advertisement