Sign in to follow this  

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.

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by oliii
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.


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 this post


Link to post
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).Normal
impulse = -------------------------------
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 this post


Link to post
Share on other sites
Quote:
Original post by oliii

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).


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

Quote:
Original post by oliii
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...


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

Quote:
Original post by oliii
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

*** 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 this post


Link to post
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.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this