Not logged in, Join Here! or Log In Below:  
 
News Articles Search    
 

 Home / Game Design & Programming / Coefficient of resititution in Jakobsen article Account Manager
 
Archive Notice: This thread is old and no longer active. It is here for reference purposes. This thread was created on an older version of the flipcode forums, before the site closed in 2005. Please keep that in mind as you view this thread, as many of the topics and opinions may be outdated.
 
arctwelve

January 12, 2005, 10:58 PM

In Verlet integration the default collision response seems to be a coefficient of restitution of 0. The first example in the Jakobsen article shows this, with the particles being constrained to the inside of the cube.

What is the correct way to add a coefficient of resititution other than zero?

 
I'M BRIAN FELLOWS

January 12, 2005, 11:04 PM

WHAT'S THE JAKOBSEN ARTICLE.

 
arctwelve

January 12, 2005, 11:05 PM

I mean the paper by Thomas Jakobsen: "Advanced Character Physics"

 
John Schultz

January 13, 2005, 02:10 AM

Reflect the particle's velocity about the surface normal.
Mirror the particle position onto the inside of the box.

  1.  
  2. // [i]coeffRest[/i] ranges from 0 to 1.
  3. // [i]n[/i] is the surface normal, in the case of the box example, points inward.
  4. vel = cur - old
  5. newVel = vel - (1+coeffRest)*n*(n dot vel) // Reflect velocity.
  6. // [i]np[/i] is a point on the plane (a box vert used by the box face, for example).
  7. cur = cur - (1+coeffRest)*n(n dot (cur-np)) // Mirror position.
  8. old = cur - newVel // Update [i]old[/i] to set new velocity.
  9.  

 
arctwelve

January 13, 2005, 03:38 PM

Once again, Thanks for your excellent reply.

 
arctwelve

January 18, 2005, 01:18 AM

John,

Your code snippet worked great. However I realized I dont know how to apply friction. Can you take me a little further and explain how to implement friction too?

thanks in advance

 
NCCAChris

January 18, 2005, 02:33 AM

similar principle - in the same way u reflect the velocity around the normal - just use the inverse of the current velocity - scale it by mu (friction coefficient. (this is actually just drag - but should work ok....

otherwise - resolve the velocity into the velocity component which is perpendicular to the surface and work with this (when a collision is detected)

 
John Schultz

January 18, 2005, 03:12 PM

As NCCAChris mentioned, you can directly damp velocity every time you have a collision. This will be a duplicate damping depending on your coeffRest.

For more flexibility, you must compute friction/drag in the plane of contact. You already have the projection equation:

  1.  
  2. // From:
  3. newVel = vel - (1+coeffRest)*n*(n dot vel) // Reflect velocity.
  4. // Velocity in plane:
  5. velInDirOfPlane = n*(n dot vel)
  6. velInPlane = vel - velInDirOfPlane
  7.  


You can apply simple linear drag as:

  1.  
  2. newVel = vel - velInPlane*coeffDrag // coeffDrag ranges from 0..1
  3.  


If you want to implement Coulomb friction, you'll have two coefficients, coeffStaticFriction and coeffDynamicFriction. Here's David Baraff's approximation method, which works OK:

http://graphics.stanford.edu/courses/cs448-01-spring/papers/baraff.pdf
http://www.gamasutra.com/features/20000510/lander_03.htm

Another way is to think about everything in terms of momentum and impulses instead of forces (the velocity reflector code is actually a momentum reflector (when mass = 1)).

Mosts references for friction use:

Fs = muS*FN // static friction force
Fk = muK*FN // kinetic (dynamic) friction force

Where FN is the normal force and mu* are coefficients of static and kinetic friction.

If the perpendicular force Fp is muS*FN, we use the kinetic (dynamic) friction equation (slowing down the moving particle).

Given:

F = ma

We can also use:

F = d(mv)/dt // were d means delta, so d(mv) is change in momentum.

If only the velocity is changing:

F = m*dv/dt // remember a = dv/dt

The impulse equation:

(mv)1 + F*dt = (mv)2 // (mv) written this way to show that mass and/or velocity can change.

or

F*dt = (mv)2 - (mv)1 // the impulse is a change in momentum.

and from F = m*dv/dt

F*dt = m*dv

In the case when m is always 1 (your particle simulation)

F*dt = dv // impulse.

If you think about everything in terms of momentum and impulses (instead of forces), your simulation work becomes easier.

The basic idea is that you have a routine called pointMomentumInDir(), which computes the momentum of a particle in a direction:

  1.  
  2. // normalDir must be unit length (normalized).
  3. Vec3 pointMomentumInDir(Vec3 vel,float mass,Vec3 normalDir,float coeffRest) {
  4.   return mass*(1+coeffRest)*normalDir*(normalDir dot vel)
  5. } // pointMomentumInDir
  6.  


You should recognize this equation from the previous example. You can use this equation for collisions with static objects, as well as for friction.

For example:

  1.  
  2. // particleCoeffRest can be substituted with 0 if you don't want restitution
  3. // to affect friction (or your can use different variables for more tuning ability).
  4. velDirProjectedToGround = normalize(vel - groundNormalDir*(groundNormalDir dot vel))
  5. momentumInDirOfGroundNormal = pointMomentumInDir(particleVel,particleMass,groundNormalDir,particleCoeffRest)
  6. momentumPerpToGroundNormal = pointMomentumInDir(particleVel,particleMass,velDirProjectedToGround,0)
  7.  
  8. if (length(momentumPerpToGroundNormal) <= length(momentumInDirOfGroundNormal)*coeffStaticFriction) {
  9.   particleVel = particleVel - momentumPerpToGroundNormal/particleMass // Stop all motion in the ground plane.
  10. } else { // Apply friction proportional to clamping.
  11.   particleVel = particleVel - velDirProjectedToGround*length(momentumInDirOfGroundNormal)*coeffDynamicFriction/particleMass
  12. } // if
  13.  


You can optimize the previous method using the following routine:

  1.  
  2. // normalDir must be unit length (normalized).
  3. float pointMomentumInDirLength(Vec3 vel,float mass,Vec3 normalDir,float coeffRest) {
  4.   return -mass*(1+coeffRest)*(normalDir dot vel)
  5. } // pointMomentumInDirLength
  6.  


You can optimize further when mass is always equal to 1 (if mass varies, store
1/mass as massInv and multiply instead of divide).

 
arctwelve

January 19, 2005, 01:31 PM

thanks

 
arctwelve

January 19, 2005, 01:32 PM


amazing. thanks again for your generous and knowlegdable reply.

 
This thread contains 10 messages.
 
 
Hosting by Solid Eight Studios, maker of PhotoTangler Collage Maker.