# Collsion Response (2D) - Need Help

This topic is 4732 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi, I have a physics engine for a 2D pool game, basically collsion response isn't working quite right and I would like some suggestions as to how to solve it. Basically, the tranfers of energies is not always working right, sometimes it does. I have a feeling that it is something to do with the way I am calculating the impluse, I have more or less copied it from those articles by Chris Hecker and stuff on www.myphysicslab.com. The formula i'm currently using is
[SOURCE]
-2 * (Relative Velocity).Normal
impulse =    -------------------------------
Normal.Normal * 1/Ma + 1/Mb

[/SOURCE]
I'm stuck as to why it is not working.

##### Share on other sites
Maybe some code will help, here is the code I'm using to calculate response to collision, I think I might be calculating relative velocity incorrectly, It's in 16.16 fixed point i'm afraid:

[source lang = "java" ]Delta = new Vector2D( ballPOS[ j ].x - ballPOS[ i ].x, ballPOS[ j ].y - ballPOS[ i ].y );CNormal = Delta;CNormal.normalise();//Relative Velocity							tempV.x = FPMUL( ballSPEED[ i ], ballDIR[ i ].x )        - FPMUL( ballSPEED[ j ], ballDIR[ j ].x );tempV.y = FPMUL( ballSPEED[ i ], ballDIR[ i ].y )	- FPMUL( ballSPEED[ j ], ballDIR[ j ].y );							temp2 = tempV.dot( CNormal );							System.out.println( "Before " + ( FPMUL( ballSPEED[ i ], BALL_MASS ) + FPMUL( ballSPEED[ j ], BALL_MASS ) ) );							temp1 = FPDIV( FPMUL( -65536, temp1 ), 524288 );System.out.println( "Impulse = " + temp1 );temp2 = FPDIV( temp1, BALL_MASS );				ballDIR[ i ].x = FPMUL( ballSPEED[ i ], ballDIR[ i ].x ) - FPMUL( temp2, CNormal.x );ballDIR[ i ].y = FPMUL( ballSPEED[ i ], ballDIR[ i ].y ) - FPMUL( temp2, CNormal.y );ballSPEED[ i ] = ballDIR[ i ].length();ballDIR[ i ].normalise();ballDIR[ j ].x = FPMUL( ballSPEED[ j ], ballDIR[ j ].x ) + FPMUL( temp2, CNormal.x );ballDIR[ j ].y = FPMUL( ballSPEED[ j ], ballDIR[ j ].y ) + FPMUL( temp2, CNormal.y );ballSPEED[ j ] = ballDIR[ j ].length();ballDIR[ j ].normalise();System.out.println( "After " + ( FPMUL( ballSPEED[ i ], BALL_MASS ) + FPMUL( ballSPEED[ j ], BALL_MASS ) ) );

##### Share on other sites
I don't see anything wrong with the impulse equation, it must be a bug in your implementation (the code is too obfuscated). Also, make sure the resulting impulse is always positive.

##### Share on other sites
Quote:
 Original post by oliiiI don't see anything wrong with the impulse equation, it must be a bug in your implementation (the code is too obfuscated). Also, make sure the resulting impulse is always positive.

I know the code is a little hard to read. This is for a mobile phone, so it has to be tight. The nutter asking this want angular velocity too so i think things are gonna go FUBAR soon. It's just difficult when it seems to be working and suddenly things fly out of control. Am I calculating relative velocity correctly?

##### Share on other sites
personnaly, I'd write a less painful example on a PC, then do a quick port on the mobile. Especially when it will get more complicated as you say so. Better make sure the method works first then it's easier to debug it step by step since you have a code and exe to reference to.

there are a couple of intriguing things though...

temp1 = FPDIV( FPMUL( -65536, temp1 ), 524288 );
temp2 = FPDIV( temp1, BALL_MASS );

I guess temp1 is just some weird fixed-point maths, but temp1 seems undefined when it's calculated. typo?

BALL_MASS I guess is equivalent to (1/ma + 1/mb).

but then, when adding the impulse to both balls, you don't use the masses back to the impulses.

to clarify...
Vel             = VelA - VelB;float numer     = -2.0f * (Vel * Normal);float denom     = InvMassA + InvMassB;float impulse   = numer / denom;Vector vImpulse = Normal * impulse;VelA -= vImpulse * InvMassA;VelB -= vImpulse * InvMassB;

and a typo, I guess

[SOURCE]             -2 * (Relative Velocity).Normalimpulse =    -------------------------------             Normal.Normal * (1/Ma + 1/Mb)[/SOURCE]

but (Normal.Normal) will yield 1 so you can remove it.

you're also doing an awful lot of normalisations as well.

Ditch the Dir/speed combo and use a single Velocity vector for both objects. If you need a dir/speed values, there are ways to make it more efficient, elegant, through the use of class members modifiers and accessors. As an example...

class CBall{private:    Vector m_vVelocity;    Vector m_vDirection;    float  m_fSpeed;    bool   m_bUpdateSpeed;    void SetVelocity(const Vector& vVelocity)    {          m_vVelocity = vVelocity;          m_bUpdateSpeed = true;    }    const Vector& GetDirection()    {         if (m_bUpdateSpeed) UpdateSpeedAndDirection();          return m_vDirection;    }    float GetSpeed()    {         if (m_bUpdateSpeed) UpdateSpeedAndDirection();          return m_fSpeed;    }     void UpdateSpeedAndDirection()     {          m_fSpeed = m_vVelocity.Normalise();          m_bUpdateSpeed = false;     }};

if it brakes the 'const' stuff, just ditch the bool and do

    void SetVelocity(const Vector& vVelocity)    {          m_vVelocity = vVelocity;          UpdateSpeedAndDirection();    }

You can also have a completely transparent floating point maths class. I'm not gonna write a floating point math lib, but as far as vector maths are concerned, it should be hidden away as much as possible.

there is no reason for this

tempV.x = FPMUL( ballSPEED[ i ], ballDIR[ i ].x )        - FPMUL( ballSPEED[ j ], ballDIR[ j ].x );tempV.y = FPMUL( ballSPEED[ i ], ballDIR[ i ].y )	- FPMUL( ballSPEED[ j ], ballDIR[ j ].y );

when it can be replaced by this

VelA = (ballSPEED[ i ] * ballDIR[ i ]);VelB = (ballSPEED[ j ] * ballDIR[ j ]);tempV = VelA - VelB;

Certainly at least in the experimentation stage, save yourself the trouble and use slightly less performant code but easy to maintain. Then at a later stage, you can always add in your vector class

float Vector::operator * (const Vector1 V) const // dot product. WARNING : same overload operator as scalar mul{    (FPMUL(x, V.x) + FPMUL(y, V.y);}Vector Vector::operator * (float k) const {    #ifdef RETAIL_BUILD         Assert("unoptimised code path.");    #endif    return Vector(FPMUL(x, k), FPMUL(y, k));}Vector Vector::operator - (const Vector& V) const {    #ifdef RETAIL_BUILD         Assert("unoptimised code path.");    #endif    return Vector(FPSUB(x, V.x), FPSUB(y, V.y));}

for things as relatively complicated as this, it's well worth having a demo stage, when you make sure all the bases are covered first. So you need readable code, some debugging tools (for your fixed point maths, like bounds checks). YOu can also experiment and proof your FP maths on a PC first if debugging a mobile is a drag, because I think you'll need a solid floating point conversion system.

just my 2 cents.

##### Share on other sites
Thanks man, got it sorted too.

##### Share on other sites
Quote:
 Original post by oliiitemp1 = FPDIV( FPMUL( -65536, temp1 ), 524288 );temp2 = FPDIV( temp1, BALL_MASS );I guess temp1 is just some weird fixed-point maths, but temp1 seems undefined when it's calculated. typo?BALL_MASS I guess is equivalent to (1/ma + 1/mb).

Actually 524288 is (1/ma + 1/mb)

Quote:
 Original post by oliiiDitch the Dir/speed combo and use a single Velocity vector for both objects. If you need a dir/speed values, there are ways to make it more efficient, elegant, through the use of class members modifiers and accessors. As an example...

This is for speed on the phone. I tried ditching it, but it worked better without.

Quote:
 Original post by oliiiYou can also have a completely transparent floating point maths class. I'm not gonna write a floating point math lib, but as far as vector maths are concerned, it should be hidden away as much as possible. there is no reason for this*** Source Snippet Removed ***when it can be replaced by this*** Source Snippet Removed ***

This is JAVA and unfourtuneately JAVA doesn't support operator overloading, thats why it looks awful.

##### Share on other sites
dear oh dear... Must be fun prgramming games in Java on mobiles...

##### Share on other sites

This topic is 4732 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628702
• Total Posts
2984298

• 23
• 10
• 9
• 13
• 13