I'm developing a physics-engine in Python (I know, it's mostly for "learning") and have it come along quite well. I've been following a lot of online documentation on the matter, and this series of articles was especially helpful: How to Create a Custom Physics Engine.
I've got materials working, that act as a class that holds restitution
and density
of a body. What happens next is that bodies that have a low density and a high restitution (e.g. 0.3, 0.8 respectively), they bounce off each other with such high velocity it doesn't take long for them to shoot off into the "void".
I have a test scene set up with 4 walls that encloses the bodies (ball). When they go at such high velocity, a collision is never registered as the next physics simulation happens after they already passed the "walls".
What I'm really interested in is why they get such high velocity when bouncing off each other, while I don't believe they should. In my example recording, I have a small ball (red) which is controller by the player (me). It has a density of 0.3 and a restitution of 0.8, with a volume of 100 (r * r or 10 * 10), its mass is 30 KGs (100 * 0.3). Another larger ball (green) is not controller by the player, but can be bounced by hitting it with the red ball. It has the same material, therefor has the same density and restitution. However, its mass is higher, because of the higher radius (30). The actual mass of the green ball is 270 (900 * 0.8).
In the recording it's noticeable the balls bounce off of each other in an unnatural way. Shouldn't the small ball get inflicted a higher impulse than the big ball? I tried to work around this by swapping the mass values used when calculating the impulse. So the small ball's impulse is calculated using the mass of the big ball, and vice-versa. You'd think this is due to the bigger ball having a higher mass, but to me they bounce off of each other rather quickly?
Is this normal behaviour for the density and restitution I have on both of these balls? I will share code if needed, but as this text is already getting a bit long, I won't waste space if not needed. My code is almost exactly following what is covered in the articles, only "converted" into Python code.
Code on calculating impulse
# Relative velocity
rv = b.velocity - a.velocity
# Velocity along the normal direction
vel_along_normal = rv.dot(contact_normal)
# EPSILON (use lowest restitution value)
e = min(a.restitution, b.restitution)
# Calculate j, which will be used to get the impulse
j = -(1 + e) * vel_along_normal
j /= a_inv_mass + b_inv_mass
impulse = contact_normal * j
# Using ratio to have lighter bodies bounce with a higher impulse than heavier bodies
mass_sum = a_mass + b_mass
ratio = (b_mass / mass_sum)
a.rigid_body.velocity -= (impulse * ratio) * dt
ratio = (a_mass / mass_sum)
b.rigid_body.velocity += (impulse * ratio) * dt
e
is a value 0 to 1. Assuming e is a positive value aftere = min(a.restitution, b.restitution)
then the next linej = -(1 + e) * vel_along_normal
is incorrect as it makes(1 + e) > 1
which will add energy to the collision (which should never happen in the real world). As it is unclear how you definee
I would assume the standard definition and say that the line calculatingj
should bej = -e * vel_along_normal
– Blindman67e
of 0.8, so it should bounce quite high. But it does not. – Qlii256j
is not properly calculated because of the 0 inverse_mass. What value should I use if one of the bodies has infinite mass? – Qlii256