Jump to content
  • Advertisement
Sign in to follow this  
VanKurt

Friction (2D) reloaded

This topic is 4751 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

I'm sorry to start another thread on this topic :-( Maybe I have not been exact enough in my last one, which made it extremely difficult for you to help me out...in addition my code was buggy what wasn't very helpful, either. So I made up my mind and tried to clearify my question. So here we go again ;-) As far as I understood friction is realized by manipulating the impulse vector, which is then used to modify the object's linear/angular velocities. My simulation is already working correctly without friction (using an unmodified impulse vector). Here's a little demo (only 60 kb): Click me! (About this demo: it uses a fixed timestep, which may cause strange behavior on machines slower/faster than mine. You may press SPACE to start the simulation or stop it again. RETURN advances a single step, if the sim is paused). Of course this looks very odd, because one would expect the ball to roll, not to slide... -> friction is desperately needed! Besides my last thread I took a look into some literature. I found several suggestions, all not working :-( 1) In "Physics for game developers" it said that I should take the full impulse and add it (but only tangential to the collision surfaces) to itself. That makes no sense to me, but maybe I just got the formulas wrong? 2) My personal idea: take the relative velocity, project it onto the collision tangent and subtract this from the impulse vector. I already implemented this solution, but it seems to work in very few cases only. Most of the time it simply sucks ;-) So all I'm looking for is a magic vector X so that "impulse += X;" will make all my objects respect friction :-D What is the right way to find this X? (or am I completely wrong here?) Thanks once again ;-)

Share this post


Link to post
Share on other sites
Advertisement
What I don't get is that you had it working in the original thread right?
All the methods we discussed until now do work and provide acceptable friction.

I think that you should really double-check all you math code and trace values around because you may very well have a nasty bug hidden somewhere. Displaying forces and impulses at the contact point would also help the lisibility but visual debugging only goes so far so checking hard values is certainly required now.

There's not much more I can tell. It's working in my code, the math are the same, it should work in yours... really! ;)
Just come to think of it but Oliii must have done and released that a hundred times already so did you check his code? How is he doing it?

Courage!

edit: The Physics for Game Developer friction example has a typo in its sample code. The friction component is applied positively to both bodies, you don't want that :). But even with that modified I could never get his approach to work with stacks. Single objects kind of work but stacks badly blew up.

[Edited by - b34r on July 30, 2005 8:40:36 AM]

Share this post


Link to post
Share on other sites
"What I don't get is that you had it working in the original thread right?
All the methods we discussed until now do work and provide acceptable friction."

That's what I thought, too. But I realised that it was not working in many cases, so there had to be a big bug in it.
Then I gave up trying around and startet to think about the problem (coding something you don't understand isn't a very good idea)... I also looked at example code (oliii) but until now I didnt get the point ;-)

Share this post


Link to post
Share on other sites
I finally managed to put friction in. here's the demo: Friction demo

s = start/stop
r = reset
t = single step

i had no time to make several tests yet. The friction is based on the formula's on a slide from Bridson. I think it's the one on MrRowls page but it could also be a newer slide.

Share this post


Link to post
Share on other sites
Hi Airo!
Sure that's working correctly? At the beginning the blocks do a strange slide-hop ;-)

Here's what mine is currently looking like: (press SPACE to go)
Click me!
In this scene eveything's fine...but sadly in other scenes everything's still screwed up :-(
(I hate friction) :P


BTW: What papers were you talking about? Got a link? :-)

Share this post


Link to post
Share on other sites
could you post the time at which the hop occurs? i didn;t see anything strange but i'm biased, i so badly want it to look good after all the failed attempts ;)

edit: it appears your right, i'm gaining energy there.

Updated friction demo

the slides are from here http://www.rowlhouse.co.uk and then the jiglib thing, there's a link to a slide. I printed out the slides so I don;t have another direct link.

I've seen that demo. It looks nice. Can you stop the blob from rolling/sliding?

[Edited by - Airo on August 4, 2005 2:41:32 AM]

Share this post


Link to post
Share on other sites
Ahh :-) Your new demo works fine! Respect!
I'll have a look at those papers...(my implementation is worse than I thought) ;-)

Share this post


Link to post
Share on other sites
ok I had a lot of trouble with friction as well when I first did this so I thought id help you out a bit more.

Basically this is my implantation of MrRawl’s friction idea, its ripped out of other code so sorry if its hard to follow:

 
/*
Friction - At each collision point the normal impulse has been calculated.
Applying friction at each point is treated like a collision -
calculate the impulse required to prevent the two points on the two objects diverging.
Now compare this tangential friction impulse to staticFriction*normalImpulse.
If it's greater, then friction won't be able to stop the objects,
so apply dynamicFriction*normalImpulse in the tangential direction.
If it's less then apply the originally calculated tangential friction.
*/


CRigidBody* m_pBodyA;
CRigidBody* m_pBodyB;
BOOL m_bMovable[2];
Vector2 m_vPointA[2]; //collision points
Vector2 m_vPointB[2];


BOOL CCollisionSolver::_SolvePoint(float CoR, I32 n)
{

Vector2 resVelocity = Vector2(0,0);
Vector2 cp1;
Vector2 cp1Perp;
if(m_bMovable[0])
{
cp1 = m_vPointA[n] - m_pBodyA->m_vPosition;
cp1Perp = Vector2(-cp1.y(), cp1.x());
resVelocity = m_pBodyA->m_vVelocity-(cp1Perp*m_pBodyA->m_fRotaionalVelocity);
}

Vector2 cp2;
Vector2 cp2Perp;
if(m_bMovable[1])
{
cp2 = m_vPointB[n] - m_pBodyB->m_vPosition;
cp2Perp = Vector2(-cp2.y(), cp2.x());
resVelocity -= m_pBodyB->m_vVelocity-(cp2Perp*m_pBodyB->m_fRotaionalVelocity);
}

float surfaceReletive = resVelocity*m_vCollisionNormal;

if(surfaceReletive > 0) //moving apart
return false;

float top = (-CoR * surfaceReletive) - surfaceReletive;

float botA;

if(m_bMovable[0])
{
botA = m_pBodyA->m_fInvMass;
float rAPdotN = cp1^m_vCollisionNormal;
botA += ((rAPdotN*rAPdotN)*m_pBodyA->m_fInvInertia);
}
else
botA = 0;

float botB;

if(m_bMovable[1])
{
botB = m_pBodyB->m_fInvMass;
float rBPdotN = cp2^m_vCollisionNormal;

botB += ((rBPdotN*rBPdotN)*m_pBodyB->m_fInvInertia);
}
else
botB = 0;


float j = (top/(botA+botB));

//Friction - At each collision point the normal impulse has been calculated.
Vector2 jN = m_vCollisionNormal*j;

if(m_bMovable[0])
{
m_pBodyA->m_vVelocity += jN*m_pBodyA->m_fInvMass;
m_pBodyA->m_fRotaionalVelocity -= ((cp1^jN)*m_pBodyA->m_fInvInertia);
}

if(m_bMovable[1])
{
m_pBodyB->m_vVelocity -= jN*m_pBodyB->m_fInvMass;
m_pBodyB->m_fRotaionalVelocity += ((cp2^jN)*m_pBodyB->m_fInvInertia);
}

//friction

if(m_fCoefficientOfFriction <= 0 )
return true;

resVelocity = Vector2(0,0);

if(m_bMovable[0])
{
resVelocity = m_pBodyA->m_vVelocity-(cp1Perp*m_pBodyA->m_fRotaionalVelocity);
}
if(m_bMovable[1])
{
resVelocity -= m_pBodyB->m_vVelocity-(cp2Perp*m_pBodyB->m_fRotaionalVelocity);
}

//Applying friction at each point is treated like a collision -
Vector2 tangent_vel = resVelocity - (m_vCollisionNormal*(resVelocity* m_vCollisionNormal));

float tangent_speed = tangent_vel.Length(); //TODO: change this

if (tangent_speed < 0.0f)
return true;


Vector2 T = -tangent_vel / tangent_speed;

top = tangent_speed;

if(m_bMovable[0])
{
botA = m_pBodyA->m_fInvMass;
float rAPdotN = cp1^T;
botA += ((rAPdotN*rAPdotN)*m_pBodyA->m_fInvInertia);
}
else
botA = 0;


if(m_bMovable[1])
{
botB = m_pBodyB->m_fInvMass;
float rBPdotN = cp2^T;
botB += ((rBPdotN*rBPdotN)*m_pBodyB->m_fInvInertia);
}
else
botB = 0;

float denominator = botA+botB;

if (denominator > 0)
{

//calculate the impulse required to prevent the two points on the two objects diverging.
float impulse_to_reverse = top / denominator;
float static_friction = m_fCoefficientOfFriction;
float dynamic_friction = m_fCoefficientOfFriction*0.8;

float impulse_from_normal_impulse = static_friction * j;
float friction_impulse;

//Now compare this tangential friction impulse to staticFriction*normalImpulse
if (impulse_to_reverse < impulse_from_normal_impulse)

//If it's less then apply the originally calculated tangential friction.
friction_impulse = impulse_to_reverse;
else
//If it's greater, then friction won't be able to stop the objects,
//so apply dynamicFriction*normalImpulse in the tangential direction.
friction_impulse = dynamic_friction * j;

Vector2 jT = T*friction_impulse;

if(m_bMovable[0])
{
m_pBodyA->m_vVelocity += jT*m_pBodyA->m_fInvMass;
m_pBodyA->m_fRotaionalVelocity -= ((cp1^jT)*m_pBodyA->m_fInvInertia);
}

if(m_bMovable[1])
{
m_pBodyB->m_vVelocity -= jT*m_pBodyB->m_fInvMass;
m_pBodyB->m_fRotaionalVelocity += ((cp2^jT)*m_pBodyB->m_fInvInertia);
}
}

return true;

}

Share this post


Link to post
Share on other sites
Hey, thank's a lot! I desperately need some code to look at ;-)
I already implemented Oliii's code, but it somehow behaves wrong...oh well!
Maybe Airo want's to post his impulse code as well? :-D

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!