Character Traction and Slipping

Started by
8 comments, last by oliii 18 years, 9 months ago
Ok i have unlimited movement and gravity effects the objects and allows them to hug the ground or fly and come down again but now i want to know how to model the effects of inclines on the objects. How do i figure the loss of movement due to slipping and slidding. Example going up a hill should be slower than down and some hills at steep angles should be unclimbable without extra traction gear < like wearing climbing boots >. As a part of this i also want the gravity to cause people with low traction to slide off an incline if they are standing still. What are the formulas for this. I know it has something to do with the direction of gravity and the normal of the surface < which i use to orient all objects that move around > i think? Any help, links, or what ever is greatly apretiated. PS. On a side note i love this sight and think it is an excillent place to come and learn more about a subject that is just plain fun to me...if not frustrating sometimes. Wish i payed more attention in physics, calculas, and trig in highschoool and college.
Advertisement
Quote:Original post by TAlchemist
PS. On a side note i love this sight and think it is an excillent place to come and learn more about a subject that is just plain fun to me...if not frustrating sometimes. Wish i payed more attention in physics, calculas, and trig in highschoool and college.


And spelling ;)
I have never said anything about my spelling, it is atrosious<sp?> i am better at coding than i am writing.
the character traction force goes along the incline. THe gravity, when projected on the incline, has a component that will be either, in the same direction of the traction force (moving downhill), or against it (uphill).

So, your character has a direction of movement that's perpendicular to the incline normal (that is, parallel to the incline plane). If you project the gravity vector onto the incline plane, that will give extra thrust, or less thrust.

To project a vector onto a plane, it's simply a matter of removing the component of that vector along the normal.

the amount of gravity aong the normal of the plane is vector Gn (Gnormal).

Gn = Normal * (G.Dot(Normal));

then the gravity acting along the plane Gt (Gtangent) is

Gt = G - Gn;

so, if your normal is inclined, |Gt| <> 0.

If the plane is flat, |Gt| will be 0 (because Gn = G).

If the plane is vertical, Gt is = G (and therefore |Gn| = 0).

THat also gives you the maximum amount of slope a character can climb. If the thrust is lower than Gt, then the character will start to fall.

Also, a friction force cen be deduced from all of this. So you acn make the character stop midway on the slope. Basically, you have to check if the net force along the tangent of the plane is greater or below the net force acting along the normal of teh plane.

Take a cube on a table for example. It will be harder to push along the table if you increase the force acting on top of it (if you push it towards the table). That's the dynamic friction. THe friction force increases with weight.

Also, consider a cube on a very small incline. if the cube is stationary, it will not slide. That is static friction. The componennt of the gravity along the plane is less than the component of the gravity along the normal of the plane (times a coefficient of static friction). make the inline steeper, there will be a point where the cube will start sliding, and eventually fall (That's when the ratio of normal force / tangent force > static grip, of for a perfect system with only gravity, if tan(slope angle) > static grip).

so, to summarise.

Vector Gravity; // gravity acceleration vector (0, -9.81)Vector Thrust; //force acting forward of the character (supposedly)Vector Normal; //normal of the groundfloat  fStaticGrip; // amount of grip under the shoes of the player.float  fDynamicGrip; // amount of friction generated when sliding on the floor.float fMass; //mass of the playerVector F = Gravity * fMass + Thrust; // total sum of forces on the player.float fVert = F.Dot(Normal); // amount of vertical force acting down the plane (should be < 0.0f).Vector Fn = fVert * Normal; // force acting along the normalVector Ft = F - Ft; // force acting along the plane.Vector Ff = Ft.Direction() * fVert * fDynamicGrip; // friction that slows down the player.// force acting on the player. Thrust + gravity + friction, all acting along the ground plane. //THe vertical part gets canceled due to the reaction of teh floor against teh player weight (Newton laws).Vector TotalForce = Ft + Ff; // interesting part. Static frcition will stop the player sliding// until the player exerts enough force to overcome the static friction// Either, enough thrust, or the slope is way too steep.if(TotalForce.Magnitude() < fStaticGrip * Fn.Magnitude()){    // force player to stop sliding on the plane    Player.Velocity = Vector(0.0f, 0.0f);}else{    // move player along the plane with the forces.    Player.Velocity += (TotalForce / fMass) * dt;    Player.Position += Player.Velocity * dt;}

Everything is better with Metal.

Quote:Original post by TAlchemist
What are the formulas for this. I know it has something to do with the direction of gravity and the normal of the surface < which i use to orient all objects that move around > i think?


It's kinda complex topic. I'm doing it in three steps:

1.) Add all forces to the current velocity. Depending on a few factors:
xvec CTerrainEntity::ApplyForces(void){   // Base(previous) velocity.   xvec xvVel = GetVel();   // Apply external forces (gravity, etc.).   xvVel += GetExternalForces();   // Check internal forces.   float fAccPower;   if ((fAccPower=m_pBehaviour->GetAccPower()) == 0.0f || m_bAboveGround) {      // Passive movement.      const xvec xvViscocity = xvVel * (m_bAboveGround ? ENT_VISC_COEFF_AirInv : ENT_VISC_COEFF_PassiveInv);      // No internal forces.      xvVel = xvVel - xvViscocity;   } else {      // Active movement.      const xvec xvViscocity = xvVel * ENT_VISC_COEFF_ActiveInv;      // Apply internal forces.      xvec xvInternal = GetRealDirectionVector() * fAccPower;      xvVel = xvVel - xvViscocity + xvInternal;   };   // Special case: stopping movement (don't let it slide whole eternity).   if (!m_bAboveGround && fAccPower == 0.0f)   {      // Only if horizontal velocity is very small.      const float fHorizVel = lenXZ(xvVel);      if (fHorizVel < ENT_BORDER_MIN_SPEED) {         // Cut horizontal component.         xvVel = cutXZ(xvVel);      };   };   SetVel(xvVel);   return xvVel;}


I'm assuming that viscocity power is proportional to ocject's velocity. May seem funny, but works fine. I don't have to use any artificial upper limits for the velocity. I keep several viscocity coefficients for different cases: on the ground, in the air, active, passive...

2.) Move with current velocity
// Objects handling (with anti-collision).g_CollEnv.move(ivMove, this, &rCollInfo);// Collect new data.CFixVec3 iNewPos = GetFixPos();// Must be successful, since terrain is convex.floay fShadowY;vec vNormTerr;m_pTerrain->GetDataAtPosXZ(iNewPos.x, iNewPos.z, fShadowY, vNormTerr);bool bAboveGround = iNewPos.y - ifix(fShadowY) > iHeightEps;


3.) Make necessary adjustments.
if (bAboveGround) {   // Nothing to do. "Fly away".} else {   // Cut velocity to terrain slope.   CutVel(vNormTerr);   // Let it know how to move.   SetUpVector(vNormTerr);   // Place exactly on the ground.   iNewPos.y = ifix(fShadowY);};


If object is slightly under the ground level, we put it onto the ground.
There a case of collisions with other objects, but that's for another thread, it seems.

So this is how I'm handling it. It's not perfect, but what is anyway?
/def
Thanks so very much Oliii i have to play with the variables some so i can test what climbing boots can do and such or better tires on a car but i got your implementation working in less than 3 minutes. cool to have to try to find a good side to climb the mountain on my map or try not to fall down a big steep hole i made.

Hey deffer i liked your idea but i need to look into the viscosity more. Since my game will allow flying, driving, walking, and tunneling < maybe > i like the idea of viscosity. Still dont know how to handle if a player flys into space since that will be possible. i want space to be playable like ground.

I seem to want alot for this little game/project of mine. Well havent had feature creep just lots and lots of wanted features.
hey oliii i found one problem if i keep the grips both set to 0.01 and the mass at 100 or less it works good. But when mass gets over 100 it makes you move uphill. The upward force is overcomming gravity.
grip is usually around 0.5, 1.2 for dynamic grip, and 1 to 2 for static grip. Mass, well depends on the thrust of your character, and the acceleration you wish to attain.

Everything is better with Metal.

i got it working kind of good, falls off hills and down holes and has trouble climbing some hills to velocity increases enough to overcome gravity and slope.

I had to remove one line.

Vector Ff = Ft.Direction() * fVert * fDynamicGrip;

changed to

Vector Ff = Ft.Direction() * fDynamicGrip;

that stoped me from flying up to the highest peek and lets me fall down no matter what the dynamic and static grip is with any mass. I am tweeking it cause the movement is working just looks odd as my pathfinding blindly charges up inclines and keeps trying to get to the target location. I think it is cool that as i increase the staticgrip he gets better at climbing so i will use that for climbing. Skill.Climbing + EquipmentMod<climbing boots> + racialClimbingMod will determine the static for climbing portion.
As usual, all that "3 minute code" stuff is just to give pointers, and not to be taken litteraly. Whatever works for you. [grin]

Friction is tricky, especially static friction and code that make objects rest and wake up. These equations are related to Coulomb Friction model, which is the usual model used to put fricitons in games. It's crude, but does the trick.

|Ff| = Ud.|Fn|, where Ud is the dynamic grip.

then if |sum(Ft)| < Us |Fn|, then static friciton, and the object stops moving down the slope.

And really, the dynamic friction depends on the vertical force applies at the contact point. The more you push down, the faster you're gonna slow down. It's just what brakes are all about. But if it ain't working for you...

As for modeling cars, It's another problem. You have to remember that at the point of contact on a tyre that rolls on the ground, the relative velocity is 0, hence no friction (or very little). When the tyre locks (stop rotating, but still moves forward), then the velocity at the point of contact is huge (=velocity of the car), and the friction increases. So for tyres, you have to be careful, and think about the roll effect. There is also the skidding effect, which effectively reduces the amount of force when a tyre slips on the floor (hence, the useful ABS brakes).

Enough rambling, hope that helped.

Everything is better with Metal.

This topic is closed to new replies.

Advertisement