The simplest method of applying surface friction?

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

Recommended Posts

Hello,

I'm working on my first game at the moment, an arcade style racing game, running on my proprietary 3D engine in AS3.

For performance reasons I'm also doing all physics and collision detection from scratch.

I have a basic car model working, basically a 3D rectangle comprised of 4 wheels and some constraints that can drive around and collide with the environment.

Albiet in basic and somewhat glitchy fashion, it works, but now I need to implement surface friction, so that for example if the car is perpendicular to the road on a hill, it won't slide down sideways.

Something of note is that I'm purposefully NOT following realistic car physics. I'm basically making the handling up, because I want it to be arcadey. The inspiration for this game is more Ridge Racer/Outrun 2 than Forza.

So without developing a fairly complex handling/physics system that references real racing physics, what is the best way to implement surface friction?

How do you think a game like Ridge Racer does it, with it's very basic, stylised handling?

Cheers,
RumbleSushi

Share on other sites
I'm no expert, but would the easiest way to implement friction would be to fake it?

Share on other sites
The simplest answer I can think of:

1. Compute net force on car, with constraints.
2. Project off lateral component.
3. Update velocity.
4. Multiply velocity by, say, 0.8.

This will give you a car that will never slide sideways, and whose velocity will slowly decay.

Share on other sites
smr, absolutely the best way would be to fake it, but I guess I'm just looking for the best way to fake it ;)

Emergent, thanks for your suggestion. I've been thinking perhaps the best way to fake it would be to just generate a sideways force on each wheel, then remove this force to initiate a drift etc. (Right now the car almost behaves as if it's on ice).

This should be relatively easy.

The tricky part is transferring the gravity into angled velocity according to car/wheel rotation.

Right now if the car is on a hill, gravity makes it slide down the hill, but without taking into account the wheel angles. It's basically a sliding plane collision response. So if the car is at a right angle to the road direction, it still slides down, but of course it shouldn't. The surface friction of the wheels should stop it.

I've tried rotating the velocity generated from the slide plane collision response according to the wheel rotation, but for some reason I can't get it working.

This image should illustrate how the surface friction should behave.

http://rumblesushi.com/stuff/gravity.jpg

Share on other sites
Quote:
 Original post by rumblesushiRight now if the car is on a hill, gravity makes it slide down the hill, but without taking into account the wheel angles.

That's what the "project off lateral component" part of my reply was about. I.e., if the car's left vector is 'n,' and the net force you calculate in step 1 is 'f' then the projected force is

f_proj = f - <f,n>/<n,n> n .

This doesn't take into account having multiple wheels, or the current steering angle; it's a very simple "quarter rolling"-type model.

I can describe fancier stuff too, but it seemed you wanted something simple, and simple this is. :-)

(I should add that you'll need to add a centrifical term when you turn.)

Share on other sites
Cheers. I'll try to get this working tonight.

How I'm handling the car now (RWD car model) is applying most of the force to the rear wheels, and a small amount to the front wheels, and of course rotating the velocity of the front wheels according to the car orientation and steering angle. Well, rotating the rear wheel velocity according to the orientation of the car too.

It's actually soft body mechanics basically, the car is comprised of 6 springs. Then the model is positioned by averaging the points and rotated according to the angles of the front/rear particles etc.

I update the velocity, process collisions with the environment, then update the constraints.

By "f_proj = f - <f,n>/<n,n> n" do you mean it's simply force - (F/lateral_vector) normalized? I'm not familiar with the pseudo code used.

How should this force be integrated exactly? Do you know of any source code with a basic "quarter rolling" source code?

Should it be integrated before sending the object to the collision routine, or as part of the collision response?

Cheers,
RumbleSushi

Share on other sites
Quote:
 Original post by rumblesushiI'm not familiar with the pseudo code used.

My bad; the angle brackets denote inner products (dot products).

Quote:
 Original post by rumblesushiHow should this force be integrated exactly? Do you know of any source code with a basic "quarter rolling" source code?

It's not too crucial how. Verlet, symplectic Euler, even plain old Euler... I might be able to come up with some code later...

Quote:
 Original post by rumblesushiShould it be integrated before sending the object to the collision routine, or as part of the collision response?

Not totally sure how your code works, but my guess is "after collision response."

Share on other sites
Thanks for the help Emergent.

It seems basic, so I'm annoyed I haven't been able to get it working. It's mainly because I have no experience of vehicle physics and no reference, literally just making it up as I go along.

In regards to pseudo code, it's not really used at all in the Flash development community so I'm often confused by some of it on this site ;)

What about the "n" after the dot products? What does that mean?

Some example code would be great if you would be so kind.

The basic physics pipeline per wheel is like this.

Apply force from wheels to velocity vector, integrate velocity to a destination position, send to collision class, return new position after slide plane collision response.

Then satisfy constraints.

Share on other sites
I use something like this:

$\mathbf{F}_{\perp} = \mathbf{n}\,(\mathbf{n}\bullet \mathbf{F})$

$\mathbf{v}_{\perp} = \mathbf{n}\,(\mathbf{n}\bullet \mathbf{v})$

$F_{fr} = \mu \, |\mathbf{F}_{\perp}|$

$\mathbf{I} = -\mathbf{v}_{\perp}\,\frac{m}{dt}$

$\mbox{if:}\;|\mathbf{I}| < F_{fr}$
$\mbox{.}\;\mathbf{F} = \mathbf{F} + \mathbf{I}$
$\mbox{else:}$
$\mbox{.}\;\mathbf{F} = \mathbf{F} + F_{fr}\,\frac{\mathbf{I}}{|\mathbf{I}|}$

So first get the component of force (including gravity) and velocity in direction of surface normal. Then calculate the kinetic friction magnitude. Then calculate an impulse that, when applied, will stop the car dead. Finally, if the strength of friction is too great, stop the vehicle dead using the impulse (approximating static friction). Otherwise apply friction force magnitude in direction of impulse (i.e. opposite direction of velocity).

That's linear friction. Angular friction is such a pain. But one step at a time, eh.

[Edited by - dangerdaveCS on December 3, 2010 6:24:14 PM]

Share on other sites
When your car is on a slope and you calculate the force vector (due to gravity causing the car to slide), you can project this vector onto the direction the wheels are facing, and also onto the vector perpendicular to the direction the wheels are facing. Then you apply separate friction modifiers to each vector. How you handle this is up to you, but normally you'd apply a friction term to the perpendicular vector which is large anough so the vehicle will resist sliding sideways on all but the steepest inclines, while it only takes a slight incline in the direction of the wheels to produce forward motion.
In a simple simulation the wheel axes don't turn during steering, but your program appears to be more complicated, so you handle each wheel separately, with the axis of the front wheels possibly being different to the back. On occasion you'll have situations where some of the wheels are on an incline while the others are flat. This introduces angular forces and center of mass, which you might want to fudge heavily unless you're familiar with that stuff.

Share on other sites
dangerDave, thanks for your suggestion. Right now the friction that is implemented is ultra simple air drag, and I'm looking to implement angular friction alongside this, but I'll look into your method.

Taz - thanks for your reply, that's pretty much what I tried to do actually. Logically, it seems like the best/simplest method doesn't it?

The collision response diverts the velocity along the polygon's surface, and right now, it behaves as if the wheels are balls.

So the first thing I thought of was to simply rotate the new diverted velocity vector according to the wheel's direction. Logically this seems to the absolute simplest way to implement surface/side friction, without having to complicate my simple, arcadey handling/physics.

But annoyingly, I just couldn't get it working.

Do you know of any source code that features this method?

If not, could you point me in the right direction of how to apply these new projections? I generally like to do things myself from scratch, but I tried something similar to what you describe, and there was obviously something I wasn't doing correctly.

My collision response manipulates a new position point, then the new velocity is simply velocity = newPos - startPos, and position = newPos. Pretty straightforward, and like Emergent said, it seems like this angular friction should be applied AFTER this collision response, after the gravity has done it's thing etc.

Cheers.

[Edited by - rumblesushi on December 4, 2010 5:01:09 PM]

Share on other sites
Are you having trouble calculating the direction vectors? The car's 'up' vector is typically the normal to the plane the car is on (possibly an average of surface normals for uneven surfaces). Perpendicular to this is the drive shaft which is the car's 'forward' vector, and a side vector, perpendicular to both. The car wheels turn in the worldspace plane formed by the forward and side vectors. When the wheels are straight, their normals are equal to the side vectors. The wheels steer by rotating in this plane. i.e. they rotate around the car's up vector. For example, if you turn the steering wheel far enough to produce a turn of 20 degrees, you can determine the wheel normal vector by rotating the car's side vector 20 degrees around the car up vector. Cross product the car's up vector and the wheel's normal vector to find the wheel's forward vector.
Then you can project the force vector onto the wheel normal/forward vectors and apply separate friction terms for each.

Share on other sites
Quote:
 Original post by rumblesushiWhat about the "n" after the dot products? What does that mean?

It's a vector. It's the car's "sideways" vector. Originally I wrote "the car's left vector is 'n.'" That equation projects off any component of the force in the sideways direction.

("n" might have been a bad choice of variable name. Other people will probably use that for the surface normal. I was thinking of it as the normal to a velocity constraint...)

Quote:
 Original post by taz0010you can project this vector onto the direction the wheels are facing, and also onto the vector perpendicular to the direction the wheels are facing. Then you apply separate friction modifiers to each vector.

Taz and I are suggesting very similar things.

Quote:
 Original post by taz0010Are you having trouble calculating the direction vectors?

Yeah, that's what it sounds like.

To elaborate on what Taz wrote: Ordinarily, you keep a set of vectors around that describes the orientation of the car. One points forward. One points left (or right). One points up. All as Taz described.

You may also know these vectors as the columns of the rotation matrix describing the car's orientation; that's what they are.

You might want to try drawing the various force vectors in your simulation, including the projected one. If you can see everything that's happening I think you'll get what's going on.

Share on other sites
Hey Emergent, oh I know what N is. What I mean is, how is the N after the projection part of the equation? Because the projection of the vector F onto the axis N, is simply the dot product divided by N squared right? With it producing a value between 0 and 1 if they are parallel along that axis.

I'm pretty sure it's nothing to do with miscalculating the orientation vectors, because like you say, I store them and use them when rotating my matrices.

I store them as the x, y and z axis of each object, with the xAxis being the column 11, 21, 31, y being 12, 22, 23, and z being 12, 23, and 33.

The car orients to the terrain according to the wheels, and that all works fine.

So Taz and Emergent I think it must simply be how I was trying to rotate the velocity or applying the projected force/friction that was wrong.

I'll try again now.

By the way, yep, good idea, I'll render the forces.

[Edited by - rumblesushi on December 5, 2010 3:53:46 PM]

Share on other sites
Quote:
 Because the projection of the vector F onto the axis N, is simply the dot product divided by N squared right?

The scalar projection of F onto N is d = F.N / sqrt(N.N). Or more simply, the dot product of F and a normalised N. Idealy the vector you're projecting onto is already normalised so you only need to do the dot product.
d can be negative depending on the direction of the vectors, and friction force always opposes the direction of motion. Make sure you're handling this so friction never causes the car to move faster.

Share on other sites
Hey Taz, what I was trying before was slightly different, but I have this working now in it's most basic form, using the side component of the car, I haven't done the front wheels yet.

Oh and in Emergent's equation, the N afterwards means multiplied by normalised N right?

That's what I got working yesterday, but as it happens I'm more familiar with the method of projection you describe, F dot normalised N.

The code is basically like this for each wheel.

side = car.xAxis;

sideForceProjection = dot(velocity, side)/dot(side, side);

velocity.x -= sideForceProjection*side.x;
velocity.y -= sideForceProjection*side.y;
velocity.z -= sideForceProjection*side.z;

This results in a drag racing car that can't steer left or right ;)

So now I'm going to find the side vector of the front wheels and apply that, and then work on making the friction perhaps a tad more natural feeling.

I'm imagining that when I have the front wheels working, the car is going to feel very on rails, a bit like Ridge Racer or Outrun when you're not drifting.

I think I'll make it marginally more complex. Possibly have a threshold for the amount of force acting on the side of the car, and if the force is low, apply ALL the friction as per above, and when the car is going faster, apply a smaller percentage of it, to give the handling a slightly softer feel.

[Edited by - rumblesushi on December 6, 2010 7:10:52 AM]

Share on other sites
Quote:
 Original post by rumblesushiHey Emergent, oh I know what N is. What I mean is, how is the N after the projection part of the equation? Because the projection of the vector F onto the axis N, is simply the dot product divided by N squared right? With it producing a value between 0 and 1 if they are parallel along that axis.

What you're calling the "projection onto N" I would call the "component along N."

The component of F along N is a scalar.
The projection of F onto N is a vector.

Lemme break it down.

I wrote,

$f_{\mathrm{proj}} = f - \frac{\left}{\left} n$
which can be written

$f_{\mathrm{proj}} = f - \left \frac{n}{||n||}$
since $\left = ||n||^2$.

This may be more familiar to you, since $\frac{n}{||n||}$ is just n normalized. Yet more simply, letting u be $\frac{n}{||n||}$,

$f_{\mathrm{proj}} = f - \left u$.

In this equation,

1.) $\left$ is the component of f along u.
2.) $\left u$ is the projection of f onto u.
3.) $f - \left u$ is the projection of f onto u's orthogonal complement. I.e., it's the part of f that's orthogonal to u.

Share on other sites
You're absolutely right, I was describing a scalar. Thanks for the explanation. Because I come from a design/photography background, rather than maths etc, I understand code much better than traditional maths syntax.

Share on other sites
By the way thanks to both of you for the help, it's appreciated. Because I'm new to vehicle physics, I've been feeling a bit lost in regards to some of the aspects of handling/physics. Looking at it, it seems simple now.

I've implemented the same friction model on the front wheels now by copying the car's side vector and rotating it by the steering angle.

It works as expected, but not without some side effects. Basically, this large sideways friction force being exerted causes the constraints to go crazy at medium to high speeds. Also I'm not sure why at all, but it seems to have lessened the effect of gravity in some ways.

The front wheels specifically have a tendency to just rise up now, with the car ending up on it's rear, flipping around like a fish. Odd, I can't see where this force is coming from.

Apart from dramatically diluting this friction force at higher speeds, to allow some horizontal sliding, do you have any tips of how to build on this friction model a bit?

Emergent, you mentioned implementing a centripetal force right?

Cheers.

Share on other sites
Quote:
 Original post by rumblesushicauses the constraints to go crazy at medium to high speeds.

In what way?

Quote:
 Emergent, you mentioned implementing a centripetal force right?

I hadn't been thinking in the context of a multiple-wheels model. With multiple wheels, cetripital force should arise naturally as the sum of the constraint forces.

Share on other sites
They essentially twist round and disorient. Aligning sideways etc.

This is the main thing that happens though - at medium to high speed when cornering fairly sharply, the two front wheels just shoot up and the car becomes stuck on it's rear, pointing straight up, flipping around.

It happens regardless of the tension of the constraints, between 0.2 and 0.7.

Oh and by the way, my constraints are manipulating velocity not position, as in this simulation it's more stable, and position constraints didn't get on well with my collision class.

It seems to happen on very slight inclines when cornering. The collision response pushes the wheels up slightly along the polygon, and for some reason the sideways force is creating a force that travels straight up, or exaccerbating the slight force from the collision response. It happens very consistently, take a sharp turn on a slight incline, and the nose shoots straight up. And it didn't come close to happening before this friction force was introduced.

Edit - just tried driving around in the air with gravity switched off and the same thing happens, so it's nothing to do with the force generated by collisions. Hmm, bizarre.

Edit again - I'm going to turn my car into a box rather than a 3D rectangle. I think the added particles and constraints should stabilise the car and make it behave better.

How many constraints do you think are necessary for a soft body box, and what configuration? I remember that guy Jim's talk on GDC, about Rally Cross physics, and he said he used 28 constraints. It seems a lot, I'm wondering if there is a configuration that uses less.

By the way, I think the reason the nose arches up like that is that there is too much force being applied with nowhere to go. Not unlike a bunch of spheres colliding on flat terrain, if they are pushing against each other sidways, the force is going to make them travel upwards.

If I simply reduce the amount of friction this goes away, but that's not really a proper fix, and if I apply 25% of the friction the car still lurches around strangely.

I think I'll achieve improved behaviour and stability from turning the model into a box rather than a rectangle, and also applying more friction on the wheels on the outside of the car.

[Edited by - rumblesushi on December 7, 2010 2:53:11 PM]

Share on other sites

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

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

• Forum Statistics

• Total Topics
628647
• Total Posts
2984035

• 10
• 9
• 9
• 10
• 21