Collision responces & multiple collisions

Started by
9 comments, last by haphazardlynamed 17 years, 1 month ago
Hi, so i have this enviroment where i have a pile of balls bouncing around inside a box. the collisions with the box are ok, but sometimes things get glitchy. the ball will 'get stuck' on the wall and sorta walk along it. i believe this is due to how i'm doing the collisions... basically every frame i move the sphere by a fraction based on the sphere velocity and the time since the last frame. however this can sometimes mean that the sphere is intersecting with the plane slightly by the time the collision happens. then, if it hasn't left the face of the plane it will bounce 'along' the plane, before falling out of the box. not too realistic ;) so to combat this i've tried putting in some code so that, when the sphere and plane intersect, the sphere is translated so it's just touching the plane.

//distance = distance from sphere centre to plane

//Translate the sphere back a bit so that it's just touching
float translate = aBall[j]->radius - distance;	//distance to move by
aBall[j]->mPosVec.x -= (translate* aBall[j]->mVelocity.x) + 0.01;
aBall[j]->mPosVec.y -= (translate* aBall[j]->mVelocity.y) + 0.01;
aBall[j]->mPosVec.z -= (translate* aBall[j]->mVelocity.z) + 0.01;

will this work? is it the best way of doing it? further to this i have another question. One of the other things i'm not sure about (and this too may be a cause of bugs) is what to do if the sphere collides with 2 or 3 planes at once. Whats the best way to handle this scenario?
Advertisement
A common approach to resolving the first problem is slightly expanding the radius of the sphere when calculating the amount to translate the sphere, so that you never end up putting the sphere directly on the plane. So rather than adjusting the final position as you have, include the factor in the calculation for "translate".

For the second problem, you'll need to keep running the collision code until you have accounted for all the movement for this update, clipping the sphere velocity each time it hits a plane. Roughly like the following:

// dt is timestep // if collide returns true a collision was detected at "time" with "normal"while (Collide(center, vel, dt, time, normal)){   center += vel * time;  // note: adjust the distance here as I described above   vel -= 2.0f * Dot(vel, normal) * normal;  // assume perfectly elastic bounce   dt -= time;}center += vel * dt;


It can also be helpful to have a check for negligible translations and terminate the loop.

Hope that helps!
The reason that it sticks to the wall is that you're not taking the normal of the wall into account. Lets look at the wall on the left for example, the normal is (1,0) in 2D. Suppose that the equation of the wall is x=-5, the radius of the ball is 1 and the position of the ball is -4.2. Now you push the ball in the direction of the wall normal - (1,0) - so the ball will move to the right, even though it's intersecting a little. It should NEVER get "stuck" to the wall.
"We've all heard that a million monkeys banging on a million typewriters will eventually reproduce the entire works of Shakespeare. Now, thanks to the internet, we know this is not true." -- Professor Robert Silensky
Rather than move the sphere to be 'just touching' the wall that it hit.
You should really check the exact Time of collision versus the current time, and calculate where the ball would have moved to after bouncing (typically it moves away from the wall by now).

Since you're just using a box, that calculation can be simplified to just reflecting the ball's coordinate across the plane it hit. (assuming perfect bouncing, no energy loss).

As for hitting more than one wall at once, for a box the order does not matter, just reflect the coordinate across each of them.
However if you want to eventually do non-box walls; then order becomes important.
and You'll need to calculate the exact collision Time for each wall, see which one hit first, and bounce the ball against that one (the bounce will typically cause it to miss the other walls, or hit them in a different order...thus you keep readjusting, one wall at a time, till you solve the collision order and final path of the ball...
haphazardlynamed, are you suggesting that rather than an approach of

for each object
check for collision
if collision, respond
go to next object


i try

for each object
check for collision
go to next object

for each object
find which collision would happen first (by distance probibally)
respond

?


also, i've looked around the internet but i can't seem to find equations for 3d collision responces. I just want to know how to make the spheres bounce realistically when they collide. I have notes from physics that cover 2d collisions, but the internet seems sadly berift of 3d collision stuff :/ I found some stuff on how to calculate the velocity, but since my coeficient of restitution is 1, thats not too useful.
The code in my post shows how to do a perfectly elastic collision response when a sphere hits a wall. It comes down to just reflecting the impact direction in the plane. For spheres hitting each other you also just want to reflect their direction vectors around the collision normal, which in this case is the vector between their centers.
Quote:Original post by d00fus
The code in my post shows how to do a perfectly elastic collision response when a sphere hits a wall. It comes down to just reflecting the impact direction in the plane. For spheres hitting each other you also just want to reflect their direction vectors around the collision normal, which in this case is the vector between their centers.


just so i understand this properly, are you saying that i find the vector between the centres of the spheres at collision, then translate each sphere along this vector (in different directions)?
Quote:Original post by Winegums
haphazardlynamed, are you suggesting that rather than an approach of

for each object
check for collision
if collision, respond
go to next object


i try

for each object
check for collision
go to next object

for each object
find which collision would happen first (by distance probibally)
respond


Yes.

This is especially important for example, in a billiards game; where the order that the balls hit each other drastically affects the ultimate paths they take.

If the balls do not hit each other -they only hit walls, then it becomes less important since you won't see critical causality interactions (like in billards) as much.
But in your example, of balls moving very fast and hitting more than one wall at once; it is still important for determining just what happened in the intermediate time between updates... (hopefully this is pretty rare though)

And like I said, if your walls are always going to be just the simple box with 90degree walls; then you have a lucky special case where order of wall hits doesnt matter(you can just reflect the coordinate across each one).



Really though thats only if accuracy matters for what you're doing. (what are you building anyway?)
If all you want is to fix the 'stuck to wall' bug, then:
when a ball passes through a wall (collided) Vector Reflect it's *position* and velocity across that wall.
My physics engine handles multiple simultaneous collisions well. I sort collisions by time, only the first one matters. The colliding object's motion is scaled back. Then in the static pass, I collect a list of objects that are within EPSILON of that object, and find the normals. That's the place where contacts are actually generated from. That way, say that object A hits B and C at the same time. If A hits B and A's motion is scaled back, the static pass will still discover that A is touching B and C, and A's collision code can account for that. It works pretty well.

Ok so i've gotten to the point where I want to bounce spheres. If I understand the method correctly I need to reflect them in the plane whos normal is the vector of collision. with that in mind i've been trying to find the point on the plane defined by the intersection of the spheres (and therefore generate the plane through D3DXPlaneFromPointNormal() ), but to no avail.

My thought was to create two floats between 0.0f and 1.0f based on the ratio of each spheres radius divided total length of the combined radii. then to find the position of intersection by dividing each spheres coordinates by this value...ie

float distanceToCentres = cSphere1->radius + cSphere2->radius;float ratio1 = cSphere1->radius/distanceToCentres;float ratio2 = cSphere2->radius/distanceToCentres;D3DXVECTOR3 collisionPoint;collisionPoint.x = ratio1 * cSphere1->mPosVec.x + ratio2 * cSphere2->mPosVec.x;collisionPoint.y = ratio1 * cSphere1->mPosVec.y + ratio2 * cSphere2->mPosVec.y;collisionPoint.z = ratio1 * cSphere1->mPosVec.z + ratio2 * cSphere2->mPosVec.z;


however this doesn't seem to work. is this method off or could it be my implimentation?

This topic is closed to new replies.

Advertisement