cyclone-physics
cyclone-physics copied to clipboard
Incorrect impulse calculation in ParticleContact::resolveVelocity
resolveVelocity calculates impulse using the sum of the inverse mass of two particles:
real totalInverseMass = particle[0]->getInverseMass();
if (particle[1]) totalInverseMass += particle[1]->getInverseMass();
This is not correct because (1 / x) + (1 / y) != (1 / (x + y)). A more correct implementation would be:
real totalInverseMass = 1.0 / particle[0]->getInverseMass();
if (particle[1]) totalInverseMass += 1.0 / particle[1]->getInverseMass();
totalInverseMass = 1.0 / totalInverseMass
@jayelliott at first, I agreed with you, but taking a more careful look at the code, I noticed one thing, totalInverse mass is not, as you pointed
1.0/(ma+mb)
but
ma*mb/(ma+mb)
This is correct, as reading the formulae on page 124
\Delta p_a = \frac{m_b}{m_a+m_b}
\Delta p_b = \frac{-m_a}{m_a+m_b}
and comparing with lines 112
particleMovement[0] = movePerIMass * particle[0]->getInverseMass();
and 114
particleMovement[1] = movePerIMass * particle[1]->getInverseMass();
we notice that they indeed are the same equation. Yet choosing totalInverseMass as the name of such variable was indeed an unfortunate choice.
P.S.: The latex code can be rendered here: http://www.codecogs.com/latex/eqneditor.php
Edit ver 4. I think what @LucasCampos says is right on the case of resolveInterpenetration method.
In the code, Line 109 of the resolveInterpenetration
Vector3 movePerIMass = contactNormal * (penetration / totalInverseMass);
idmillington uses the division with totalInverseMass.
it means that
totalInverseMass before this code was (m_a + m_b)/ m_a * m_b
.
because the code of totalInverseMass is
// The movement of each object is based on their inverse mass, so
// total that.
real totalInverseMass = particle[0]->getInverseMass();
if (particle[1]) totalInverseMass += particle[1]->getInverseMass();
which is 1/m_a + 1/m_b == (m_a + m_b) / m_a * m_b
in the case of particle[1] existing.
and then with the movePerlMass variable using division with totalInverseMass,
the equation becomes m_a * m_b / (m_a + m_b)
.
and then if you multiply 1 /m_a(the inverse mass of object a) with this new equation, you can get the delta(p_a).
As LucasCampos pointed out, I think the variable name should be modified for the better understandings of the codes.
However, In the case of resolveVelocity method, the situation is a little different.
At first, I thought what @snickerbockers says is right.
However, I wrote all the code of bridge demo, and tested it. and the code was not working properly. I saw the particle suddenly bounce extremely over the sky. After removing snickerbockers' thought, the code is working well.
So, I searched for some detail of physics in impulse equation. And I think the point is on the real equation of impulse calculation. Actually, I don't fully understand the equation, but Someone who is interested in this can search for it more.
Anyway, All the codes in pcontacts.cpp is working well.