A procedural rolling wheel

We would like to create a system whereby the translation of this wheel results in the correct corresponding rotation of the wheel through the use of an expression.

For this to work we first have to understand that for one rotation of this wheel the wheel will translate forward by a value equal to its circumfrence.

So for one rotation of the wheel the wheel advances a distance of one circumfrence. Or put mathematically

1 rotation = 360 degrees = a translation of one circumfrence:Pi (3.1415)xthe diameter of the wheel

Therefore

1 degree in rotation = the circumfrence / 360

In our example 1 degree equals 0.0065 units of translation.

so 1 unit of translation equals 1/0.0065 = 154.23 degrees.

So to interpret this into a MEL expression we can say

Wheel.rotateX = 154.23*Wheel.translateZ;

Now translate the wheel around and you will see that the wheel rotates perfectly with respect to the surface.

Taking to the next level: Procedural Rigging of a car.

Open the file: Mustang_start.ma

Now we have four similar wheels nested in the Mustang heirarchy.

Start by creating the expression for each of the wheels.

wheelRearLfGeo.rotateX = 154.23*mustang.translateZ;
wheelRearRtGeo.rotateX = 154.23*mustang.translateZ;
wheelfrontLfGeo.rotateX = 154.23*mustang.translateZ;
wheelfrontRtGeo.rotateX = 154.23*mustang.translateZ;

Now when you translate the parent node mustang all the wheels rotate perfectly without any effort.

 

Adding some Shock Absorbers

Open the scene Mustang_Terrain_Start.mb

Now we would like our car not only to roll correctly, but also to adjust theirselves accordingly with different kinds of terrain. We need to write an expression that changes the wheel height with the surface. The easiest way to do that is to implement a height gauge at the wheel that measures the altitude of the ground at the wheel.

A Surface height measure.

Create a locator and call it R_Front_ShockAbs. Select your terrain, then the locator then create a geometry constraint (Constrain>geometry constraint). This will constrain the locator such that its XYZ coordinates always fall on the surface. You can now point constrain the same locator to the wheel. Now when you move the car around, the locator moves up and down with the terrain. All that is left to do now is to write an expression that updates the wheel height with the locator shock absorber.

wheelfrontRtGeo.translateY = R_Front_ShockAbs.translateY;

Repeat the creation of each shockabsorber locator for each wheel; geometry constrain the locator to the surface; then point contrain it to the wheel. Finish the process off by adding the following expression.

wheelRearLfGeo.translateY = L_Back_ShockAbs.translateY;
wheelRearRtGeo.translateY = R_Back_ShockAbs.translateY;
wheelfrontLfGeo.translateY = L_Front_ShockAbs.translateY;

Now as we roll our car around the the wheels happily lift up and down with the terrain, BUT they also rip up through the chassis of the car...

Raising the chassis a bit helps... but some procedural control of the shell rotation would be better.

Our axle on inspection is around 1.55 units wide, so we can calculate the average twist in the front and back axle through basic trigonometry.

Front axle twist = arc tan ((Left Front Wheel Translate Y - RightFront Wheel TransY)/1.55)

Averaging this for the front and back axle give a fair approximation of what happens for the torsion of a rigid body like the car chassis.

The following expression describes this in MEL

shell.rotateZ = (abs(atand(abs((wheelRearLfGeo.translateY-wheelRearRtGeo.translateY)/1.55)))-abs(atand(abs((wheelfrontLfGeo.translateY-wheelfrontRtGeo.translateY)/1.55))))/2;

repeat this for the X rotation of the shell;

shell.rotateX = (abs(atand(abs((wheelRearLfGeo.translateY-wheelfrontLfGeo.translateY)/1.55)))-abs(atand(abs((wheelfrontRtGeo.translateY-wheelRearRtGeo.translateY)/1.55))))/2;

and you should have a fairly good looking sloppy jalopy...