cyclone-physics icon indicating copy to clipboard operation
cyclone-physics copied to clipboard

Incorrect impulse calculation in ParticleContact::resolveVelocity

Open snickerbockers opened this issue 12 years ago • 2 comments

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

snickerbockers avatar Dec 26 '12 22:12 snickerbockers

@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

LucasCampos avatar Feb 28 '13 12:02 LucasCampos

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.

lch32111 avatar Sep 08 '18 03:09 lch32111