Two round objects collide in space. You know the speed along the x and y axises (vx and vy) for both objects and their position when they collide (from this you could i.e. calculate the angle of an imaginary line that connects the centerpoints of the objects). If you want to be somewhat physically correct, how would you calculate new vx and vy'ses for the two objects?
I know how to do it if the collision is "straight on" (as in, the speed vectors of both objects pass through the centerpoint of the other object), but it may not be in this case.
I'm not going to take spin, friction into account. Assume both objects have the same mass. It's just a simple, hopefully somewhat believable, system for my space shoot-em-up
When I think about it, it's just a billiards problem, only this time the playing field has no friction..
Any help appriciated
Ulfenstein
If they are spheres, then you can simply mirror the velocities around the plane at the collision tengeant.
Otherwise, you get into Rigid Body Dynamics.
Lookup Chris Hecker's articles on google, they're really good.
Hmm.. but if I understand you right, won't that mean that if the second object was originally standing still, then the first (hitting) object will always stand still after the collision, regardless of how it hits the second object? (zero force rotated either way is still is a zero force)
This is obviously not always the case in billiards..
Ulfalizer
D'oh, you're right of course, what I said applies if the other object has an infinite mass
Find out Hecker's papers. I couldn't tell you the
formulas here off the top of my head, but it does exactly what you need.
I've needed a whole week to completely understand the whole thing though.
Approx:
get the collision normal
apply an impulse(instant force) to each body
that's proportional to the dot product between collision velocity and collision normal and object's mass wrt. sum of the masses
this impulse modifies the quantity of movement (french term, can't remember how Hecker calls it)
you then deduce the new velocity
works a peach when once of the bodies has infinite mass (eg you can't modify its course) so it can be used for billiards table too.
I've got a model which works perfectly as long as one of the objects is initially still. I thought it'd be a piece of cake to just "pretend" one object is always standing still by subtracting it's velocity...
relVX = vX1 - vX2; relVY = vY1 - vY2;
edit: "rel" is for "relative"
...and then add back the speed lost due to the "relativity adjustment" at the point of setting the final resulting speeds for the objects...
(*firstObjectIter) -> setVX(newRelVX1 + vX2); (*firstObjectIter) -> setVY(newRelVY1 + vY2); (*secondObjectIter) -> setVX(newRelVX2 + vX2); (*secondObjectIter) -> setVY(newRelVY2 + vY2);
This is problematic. For one thing, the total speed of both objects will be less after the collision than it was before it (if both objects are moving, if one is standing still everything's fine..). In an elastic collision it should be constant
How am I thinking wrong?
Ulfalizer
Make sure the equality newRelV?1+newRelV?2==relV? always holds.
[EDIT]
I'm assuming now that no speed is "exchanged" between the X and Y components. This generalization is left as an exercise to the reader.
[/EDIT]
The problem is that my "relativity" approach is obviously faulty. If i could find some way to extend my one-object-still algorithm to two moving objects, i'd be all done
Ulfalizer
This is the algorithm I use. It seems correct for elastic collisions between circles with no spin, but I've never checked it against a physics book or anything like that.
1 | float dx = a1->x - a2->x; |
2 | float dy = a1->y - a2->y; |
3 | float dvx = a1->vx - a2->vx; |
4 | float dvy = a1->vy - a2->vy; |
5 | float distance = sqrt(dx * dx + dy * dy); |
6 | float impact = -2 / distance * (dx * dvx + dy * dvy); |
7 | if (distance == 0) return;//we can't handle this... |
8 | dx /= distance; |
9 | dy /= distance; |
10 | if (impact < 0) return;//weird collision (should only happen in unusual circumstances) |
11 | //adjust velocities for newtonian physics |
12 | impact = impact / (a1->mass + a2->mass); |
13 | a1->vx += impact * a2->mass * dx; |
14 | a1->vy += impact * a2->mass * dy; |
15 | a2->vx -= impact * a1->mass * dx; |
16 | a2->vy -= impact * a1->mass * dy; |
Thanks, I'm not at a place where I can test the code now, but I will tommorow
I can't grasp how it works though. For example, in what way does the distance between the centerpoints matter? After you have determined that the objects actually Have collided that is. And what does that -2 come from? Hmz..
Ulfalizer
EDIT:
With that algorithm, is the sum of the speed of the first object (sqrt(a1->vx * a1->vx + a1->vy * a1->vy)) and the second object the same before and after the collision? What I have now looks right at a glance but leads to all balls eventually moving very slow due to losses in the collisions
The code I posted, assuming I didn't mess it up when I editted it for posting, produces results that appear correct in my games and simulations.
Thd distance doesn't matter - it was used by a non-newtonian bit of physics that I editted out. However, the distance is used in the newtonian calculations there in the process of figuring out the direction in which the collision occured (i.e. the difference between their positions divided by the distance between their positions equals the unit vector in the direction from object 1 pointing at object 2, which, since they're circular, is equal to the unit vector in the direction normal to the collision). Anyway, then I take the dot product of that vector with the vector of their relative velocities and multiply by 2 (I think if you multiply by a smaller number you'll end up with in-ellastic collisions... but don't quote me on that... or any of this shit...) to get the force of impact. Then I give each object a portion of that force based upon its mass.
The check for negative impact force is there to protect against weird cases. I have weird cases sometimes for a few different reasons. The most common is due to objects teleporting into each other, in games that include teleportation. Another reason it happens is because of the flawed discrete time simulations an object involved in many collisions per game tick can end up at physically impossible combinations of position and velocity. And when doing pixel-perfect collisions I use the simplifying assumption that the sprites are aproximately circular and apply this formula, but if the sprites collide on a particularly non-circular portion, they can end up being weird also.
My physics is a bit rusty, but since you're dealing with elastic collisions, you only have to worry about conservation of momentum and kinteic energy.
Given objects (m1, v1) and (m2, v2), where m is mass and v is velocity before collision and v' is velocity after,
By conservation of momentum you have:
m1 * v1 + m2 * v2 = m1 * v1' + m2 * v2'
You also have conservation of kinetic energy, which give you this formula:
1/2 m1 * v1^2 + 1/2 m2 * v2^2
= 1/2 m1 * v1'^2 + 1/2 m2 * v2'^2
So how do you calculate the new velocities?
Using the above formulas, you get:
v1' = ((m1 - m2) / (v1 + m2)) * v1
v2' = ((2 * m2) / (v1 + m2)) * v1
However, this may be a little simplistic for you, since it assumes that both objects are a single point. This would not be the case for real objects, such as billiard balls, where not all collisions are direct, but also involve glancing blows, etc.. My knowldege is physics is not so great as to explain that case
But the above may suffice for you.
Conservation of momentum and internal energy holds in all (elastic) collisions. If collisions are not head-on (ie, the colliders are not simple points), you also need to consider conservation of the total angular momentum (L = r x p). If you're not considering rotating spheres, then this is not so hard (in the equation, r is the position vector of one object and p is its momentum. x denotes the vector product. In two dimensions, you only need the magnitude of L, since no collision should produce a `bump' out of the plane).
I don't have time to work out the equations myself now. I might have time to do it this evening when I get home (though I should probably work on something else). It shouldn't be too hard to work out, though.
Andrew Ellem:
While your reasoning sounds right, and the conservation formulas you start with are correct as well, your resulting formula is wrong. For instance, if you switch object 1 and object 2 you should still get the same result, but you won't with that formula. Also, in your formula you add v1 and m2; but v1 is a vector of velocity, m2 is a scalar of mass, so the two don't add like that.
Orz:
I tried your code, and found the same problems I had with mine. Performing some random collisions between asteroids and the player spaceship, the total speed of both objects was often different after the collision (by a magnitude I don't think can be explained solely by rounding errors). Here's some trace data I cought:
!Before collision!
First object:
x = 171.406
y = 279.15
vX = -1.58721
vY = 0.735375
Second object:
x = 152.439
y = 319.148
vX = -0.0129988
vY = 0.199577
Total speed:
hypot(vX1, vY1) + hypot(vX2, vY2) = 1.94929
!After collision!
First object:
vX = -1.09078
vY = -0.311503
Second object:
vX = -0.509424
vY = 1.24646
Total speed:
hypot(vX1, vY1) + hypot(vX2, vY2) = 2.48093
For simple tests, like the tangeant at at the point of impact having a 45 angle and both objects moving towards eatch other at equal speed, the code worked perfectly.
Ulfalizer
The sum of speeds is not supposed to match. Instead, the sum of momentums is supposed to match, and the sum of energies. And the sum of momentums does match.
Hmm... uh-oh... the sum of energies isn't matching in my calculations... maybe I made a mistake...
(30 minutes later....)
Okay, the sum of energies matched. I should have written a program to theck the numbers, with all the stupid mistakes I've been making typing this in to a calculator...
Anyway, before collision the sum of energies is 1.5500 energy units, afterwards it's 1.5500 energy units. Before collision the sum of momentums is (1.600, 0.935), afterwards it's (1.600, 0.935). This is assuming they both have a mass of 1 mass unit.
edit:
So, in summary, that means that those numbers correspond to a 100% correct newtonian physics calculation, discounting rounding errors.
Vincent Penquerc'h:
Your link is broken for me.
Firstly we're talking floating point world, where if you add a set of numbers and then subtract that very same set of numbers you won't get zero...so over time things like Total KE will devolve slowly. But this probably doesn't matter.
Secondly, I recommend writing a 2D vector class/struct with a set of basic functions such as addition, subtraction, scaling, magnitude, dot product, cross product. If you haven't already done so, that is. It makes life much easier when dealing with these problems.
Thirdly, you don't need to worry about KE, rather total momentum (m * v). KE is only for elastic collisions, which are collisions where KE is preserved. These are only a subset of all collisions - and if you have any half-complicated physics preservation of KE will no longer hold.
Here is some code off the top of my head which will preserve momentum (p1, p2 position vectors, v1, v2 velocity vectors):
2Dvector d = p1 - p2;
d = d.normalise() * force_constant;
v1 += d;
v2 -= d;
What this means is that this always keeps momentum constant because it always creates opposing and equal force vectors. It's Newton's third law.
Ops.. I forgot to mention that (currently) all objects in the game have the same mass. Thus the total speed should be the same before and after the collision
edit:
If the total speed need not be the same before and after the collision (providing the mass is the same for all objects), couldn't that i.e. mean that objects could slowly "gain" more and more speed until the speeds of the objects reaches a unplayable level?
I have yet to take whatever math course dot product is introduced in, I don't know what it is and for
Ulfalizer
The total speed should NOT be the same before & after. See my previous post. There is no conservation of speed law.
Heh, if so, maybe my old code is correct after all
I guess i could test it with some sample data with a known correct answer..
Ulfalizer
The total speed should NOT be the same before & after. See my previous post. There is no conservation of speed law.
There is if all objects have equal mass, and that is the case he was refering to, if I read his post correctly.
Evert: No, there isn't. There is if all objects have equal mass and all collisions are head on. There is not for glancing collisions.
edit: to clarify, for glancing collisions, there is, but it's for each dimension independantly. i.e. the X component of velocity is conserved, and the Y component of velocity is conserved, but total speed is not. Total speed is only preserved in the special case of head-on collisions. Needless to say, this only applies when masses are equal.
edit2: minor terminology correction
orz: this worked for me:
[url http://www.d6.com/users/checker/pdfs/]
It seems [1-4] means there's 4 URLs where you replace [1-4] with a number 1 to 4 inclusive.
Hmm.. but there are obviously collisions in which the total x momentum and y momentum will be different after the collision, aren't there? (if that's what "conservation" is about)
Like in the following collision:
<code>
/\ ->
/ -> <- /\
<- /
<code>
Assuming the normal in the impact point gets a 45 angle, the leftmost object will continue straight up and the rightmost straight down
hmm..
Ulfalizer
Evert: No, there isn't. There is if all objects have equal mass and all collisions are head on. There is not for glancing collisions.
Conservation of momentum says that:
sum_i p_i = sum_i q_i
(note: p and q are vectors, as are v and u below).
where i labels the particles in the collision, p_i is the momentum of particle i prior to collision and q_i is the momentum of particle i after collission. The sum runs over all particles.
Now let p_i = m_i v_i and q_i = m_i u_i, where v_i and u_i are the velocities before and after collision respectively.
If all particles have equal mass (say m), then m_i = m for all i and the sum reduces to
m sum_i v_i = m sum_i u_i
and the mass drops out. So yes, if all particles have the same mass, then conservation of momentum is equivalent to the statement that the total (CM) velocity is conserved in the collision.
Actually, that may be a general result (non-relativistically) - I'll need to read back on my newtonian mechanics.
edit: to clarify, for glancing collisions, there is, but it's for each dimension independantly. i.e. the X component of velocity is conserved, and the Y component of velocity is conserved, but total speed is not. Total speed is only preserved in the special case of head-on collisions. Needless to say, this only applies when masses are equal.
I'm not sure what you're saying here, but if the x and y components are conserved, then naturally the total velocity is also conserved: if all components of a vector are conserved, then the vector as a whole is conserved.
EDIT:
Hmm.. but there are obviously collisions in which the total x momentum and y momentum will be different after the collision, aren't there? (if that's what "conservation" is about)
Yes - in describing collisions that are not head-on, you need to consider conservation of angular momentum as well (see my original post).
> It seems [1-4] means there's 4 URLs where you replace [1-4] with a number 1 to 4 inclusive.
Heh, yes, thought that was obvious, sorry
Been doing regexp searches too often, I guess...
Ulf Magnusson: Momentum is still conserved. X momentum was 0 beforehand, is still 0 afterwards. Same for Y momentum. Why 0, you ask? Because the one on the left was +1, the one on the right was -1, the sum was 0.
Vincent: Sorry, yes, it would have been obvious if I bothered to read the URL. I didn't read it, I just copied and pasted it into my browsers navigation bar.
Evert: If masses are equal then velocity is conserved. Speed is not. Velocity is a vector, speed is the magnitude of velocity. Note that the numbers for the earlier collision example:
vX1 = -1.58721
vY1 = 0.735375
vX2 = -0.0129988
vY2 = 0.199577
vX1 + vX2 = 1.60
vY1 + vY2 = 0.934
speed1 + speed2 = 1.94929
vX1' = -1.09078
vY1' = -0.311503
vX2' = -0.509424
vY2' = 1.24646
vX1' + vX2' = 1.60
vY1' + vY2' = 0.934
speed1' + speed2' = 2.48093
Notice how velocity is conserved but speed is not?
If a vector is conserved, then so is its norm. If the velocity vector is conserved, then so must the quantity you call speed (which is the root of the norm of the velocity vector).
How are you calculating it?
BTW. I've never seen the convention that `speed == magnitude of velocity vector' before.
EDIT: I made a slightly different (but easier) analisys than I originally proposed. It is based on the assertion that the momentum can be split in two parts: one along the surface normal at the point of collision, one perpendicular to it.
The first changes in the colission, while the latter is not.
You can have a look at my (handwritten, beware!) work at
http://gene.science.uva.nl/~eglebbk/twosphere.png
HTH
As far as I can tell (not very ), orz's code is working fine. If I let go a couple of objects within an enclosed area the system won't speed up or slow down in the unrealistic way it used to.
I still find it wierd that the total "speed" needn't be the same before and after the collision though, and I can't grasp how the code does its magic
Anyway, thanks, I'll give credits when the final game is released
Ulfenstein
Evert, you're confusing the relative velocity with the sum of velocities. Obviously, a constant sum of velocities does not imply a constant sum of speeds (like Orz's calculation demonstrates). A dramatic demonstration of this is when two perfectly inelastic objects collide head-on. Total speed goes from positive to zero.
BTW, if the collisions ARE elastic then there is an additional constraint of the sum of the squares of the speeds remaining constant.
I posted the following formula before, and it has a stupid mistakes (that orz pointed out). Here's the fixed one:
The proper formula would be:
v1' = ((m1 - m2) / (m1 + m2)) * v1
v2' = ((2 * m1) / (m1 + m2)) * v1
Ulf, you're comment about collisions not always conserving momentium is somewhat true. The formulas discussed are for single point masses, so all collisions will always be direct ones. If you want indirect collisions (hitting at an angle) you would need to find the angle of collision and deal with the transfer of force, taking the dot product of the vectors to determine how much force is transfered.
Evert, you're confusing the relative velocity with the sum of velocities.
Ehm... I don't think so. Where am I doing that?
Obviously, a constant sum of velocities does not imply a constant sum of speeds (like Orz's calculation demonstrates).
I'll reiterate what I said above and try to make more clearly what I meant. It seems there is a confusion between two things here.
I said that if the velocity vector is conserved, then so is its norm (I won't call it speed, since that is confusing to me).
What I did not (mean) to claim is that the sum of norms of individual velocities is conserved.
As far as I know, this sum has no physical meaning anyway, so it doesn't matter.
A dramatic demonstration of this is when two perfectly inelastic objects collide head-on. Total speed goes from positive to zero.
Obviously. The same holds for any other system that has energy dissipation. I don't think I ever claimed otherwise, as the case we were discussing involves elastic collision.
BTW, if the collisions ARE elastic then there is an additional constraint of the sum of the squares of the speeds remaining constant.
This is the same as I said above: the total velocity vector is conserved, therefor, so is its norm (and therefor also the squared norm).
Ulf, you're comment about collisions not always conserving momentium is somewhat true. The formulas discussed are for single point masses, so all collisions will always be direct ones. If you want indirect collisions (hitting at an angle) you would need to find the angle of collision and deal with the transfer of force, taking the dot product of the vectors to determine how much force is transfered.
I think the calculations I made (follow the link in my previous post if you want to see them) cover this case for two spheres. I'd be interested in some comments, though
Andrew Ellem:
That's still not right. It still violates symmetry, and it doesn't factor in object 2s velocity.
Evert:
If masses are equal and collisions are elastic, then these statements are true:
1. magnitude(vel1 + vel2) == magnitude(vel1'+vel2')
2. magnitude(vel1) ^ 2 + magnitude(vel2) ^ 2 == magnitude(vel1') ^ 2 + magnitude(vel2')
And this statement, which Ulf Magnusson believed to be true, is actually not true:
3. magnitude(vel1) + magnitude(vel2) == magnitude(vel1') + magnitude(vel2')
That's all I've been saying. And #2 does not follow from #1. In fact, #1 and #2 combined with knowledge of the direction in which force is applied is sufficient information to calculate the answer for all cases that satisfy the conditions (no spin, elastic collisions, equal mass).
edit: removed typo (changed "inelastic" to "elastic" above.
Ehm... it looks like we have been essentially saying the same thing to each other, except in wording that caused some confusion (at least for me).
However, I think I disagree now
Your #1 is conservation of momentum, while #2 is conservation of kinetic energy. #2 does not hold in inelastic collissions, since some of the kinetic energy is converted to heat.
I should probably make a demo program to test the equations I derived on paper, but I don't have time at the moment (studying for an exam tomorrow::))
If masses are equal and collisions are inelastic then these statements are true:
I believe orz made a mistake here and meant to say elastic. After all he does so later:
In fact, #1 and #2 combined with knowledge of the direction in which force is applied is sufficient information to calculate the answer for all cases that satisfy the conditions (no spin, elastic collisions, equal mass).
Ugh, my physics is really rusty. Actually it's s more like my basic algebra is rusty... hmm, probably closer to broken. I appologize for posing such half-baked responses. I got the two conservation formulae from my head, but just copied the final from the web.
You're completely right. The formula I gave assumes that object 2 is initially at rest. So, yeah, it's no good. But it should be simple enough to just compute the correct formula using the two conservation formulae.
You're completely right. The formula I gave assumes that object 2 is initially at rest. So, yeah, it's no good. But it should be simple enough to just compute the correct formula using the two conservation formulae.
Or just do a coordinate transform to a frame where it isn't at rest.
Ok.. I've gotten a bit further on my game engine and am about to implement damage. When an object hits the player spaceship, I want the resulting damage to be directly proportional to the "force" in the collision. I realize that in the real world it wouldn't be a totally elastic collision if the spaceship aquired damage, but ignore that aspect.
How would you correctly calculate this "impact force" (getting the formula might help me understand the collision code better as well. I grew kinda tired of ball collisions and haven't looked at the code since I copied Orz )?
Ulfalizer
You could use the difference between the absolute speed before the collision and the absolute speed after the collision.
While this is not really correct, it should give you a nice estimation. And since you need to know these two values anyway, it's also pretty simple to implement.
Check my calculations. I think you'll find your answer basically in them.
You need the projection of the momentum vector along the surface normal at the point of collission.