Vehicles (modeling): Difference between revisions
(major cleanup/gauge animation info) |
|||
Line 3: | Line 3: | ||
}} | }} | ||
[[Category:Modeling]] | [[Category:Modeling]] | ||
This page describes how to set up a model for use as a functional vehicle, with basic animations, and optionally, gauge animations. | |||
=SMD prerequisites= | |||
==Reference model== | |||
Your [[Reference model|reference model]] at minimum needs the following bones in order to work: | |||
* suspension front left -> steering front left -> wheel front left | |||
* suspension front right -> steering front right -> wheel front right | |||
* suspension rear left -> wheel rear left | |||
* suspension rear right -> wheel rear right | |||
* view, located where the driver's view should be | |||
Optionally: | |||
* steering wheel | |||
* gauge needle(s) | |||
All of which should be children of a static root bone, and should follow the above hierarchy. You may name them anything, as long as you edit the following code examples accordingly. | |||
Your respective meshes need to be rigged to their respective bones. | |||
==Collision model== | ==Collision model== | ||
All vehicles need a | All vehicles need physical models, so you need to set up a collision model. See [[$collisionmodel]]. | ||
To get started, you can simply use a copy of the reference model of your vehicle, but make sure to remove the wheels from the model, as wheel collisions aren't defined in the collision model itself, but at runtime, based on the entire compiled model's wheel attachments. Note that doing this will give your model a convex collision model. | |||
If you have the time for it, modelling a low-poly version of the vehicle specifically for use as a collision model can be useful, both for optimization, and because it can be concave. See [[Collision mesh]]. | |||
==Basic animations== | |||
Vehicles require a few basic animations in order to work properly. | |||
* [[Studiomdl Data#Types|An animation SMD]] with only the suspension bones animated. This may be 2 frames (fully compressed, fully extended). This sequence determines the suspension travel each wheel has. | |||
* An animation SMD with only the wheel bones individually spinning one full revolution. This may be 9 frames, and may need a linear animation curve, defined before the animation is exported in the model editor you use. | |||
* An animation SMD with the steering of the wheels, with only the steering bones (and the steering wheel bone if it exists) and not the wheel bones animated. This may be just 3 frames (left, centered, right). Be sure to note the exact angle that the wheels turn to and make it consistent. You’ll need to put that angle into the vehicle’s script file so that the physics will match the animation. | |||
Note that with just 3 frames, if you animate a steering wheel, it can't turn further than 90 degrees one way without breaking the centered position, which might be unsuitable for some models. See [[#Making the steering wheel turn further than 180 degrees|Making the steering wheel turn further than 180 degrees]]. | |||
=QC setup= | |||
==Attachments== | |||
== | ===Wheels=== | ||
You need to set up [[$attachment|attachments]] for all four wheels, to define where they are located in the model. | |||
$attachment "wheel_fl" "<wheel front left bone>" 0 0 8 | |||
$attachment "wheel_fr" "<wheel front right bone>" 0 0 -8 | |||
$attachment "wheel_rl" "<wheel rear left bone>" 0 0 8 | |||
$attachment "wheel_rr" "<wheel rear right bone>" 0 0 –8 | |||
You '''must''' name the attachments as above. You may however name their respective bones anything, and you may place the $attachment lines anywhere in your .QC. | |||
Only four wheels may be simulated in one vehicle. Their attachments are named with two letter codes: | |||
*<code>fl</code> "front left" | *<code>fl</code> "front left" | ||
*<code>fr</code> "front right" | *<code>fr</code> "front right" | ||
Line 32: | Line 65: | ||
*<code>rr</code> "rear right" | *<code>rr</code> "rear right" | ||
One important detail is that the wheels are simulated as spheres. For this reason, you may want to pull the attachments slightly inwards. The origin of the wheel bones is actually the center of the wheel graphically, but in order to avoid having the spherical wheel collisions poke out from the sides of the vehicle (thus brushing against things next to it), you might want to pull the attachments in by a bit. | |||
For example, this would place the wheel sphere exactly over its graphical representation: | |||
$attachment "wheel_fl" "<wheel front left bone>" 0 0 0 | |||
While this adjusts it inwards by 8 inches: | |||
$attachment "wheel_fl" "<wheel front left bone>" 0 0 8 | |||
The amount to pull them in depends on the size of the wheels and the collision model of the vehicle. In this case, the wheels have a radius of about 22.5 inches and I’ve pulled them in by 8 inches. Using this ratio is a good starting point. | |||
===Driver's view=== | |||
This line defines where your view is going to be when driving. | |||
$attachment | $attachment "vehicle_driver_eyes" "<view bone>" 0 0 0 | ||
As with the wheel attachments, this attachment '''must''' be named <code>vehicle_driver_eyes</code>. | |||
===Miscellaneous attachments=== | |||
These are some miscellaneous attachments that might be required, with approximate positions that you might have to tweak. | |||
$attachment "vehicle_feet_passenger0" "<view bone>" 0 0.00 -27.00 | |||
$attachment "vehicle_engine" "<root bone>" 40.00 0.00 17.00 | |||
The | The <code>vehicle_feet_passenger0</code> attachment determines where the driver's third person player model is located. It doesn't need to be based on the view bone - you can instead set up an individual bone for it. | ||
==Pose parameters== | |||
You need the following [[$poseparameter]] lines to allow the physics to interact with your model. | |||
This | This line is for the steering. –1 is left, +1 is right. | ||
$poseparameter "vehicle_steer" -1 1 | $poseparameter "vehicle_steer" -1 1 | ||
These | These lines are for the suspension states of each wheel. 0 is compressed, 1 is extended. | ||
$poseparameter "vehicle_wheel_fl_height" 0 1 | $poseparameter "vehicle_wheel_fl_height" 0 1 | ||
Line 68: | Line 109: | ||
$poseparameter "vehicle_wheel_rr_height" 0 1 | $poseparameter "vehicle_wheel_rr_height" 0 1 | ||
These | These lines are for the rotation of each wheel. +/- 180 degrees from base rotation. | ||
$poseparameter "vehicle_wheel_fl_spin" -180 180 wrap | $poseparameter "vehicle_wheel_fl_spin" -180 180 wrap | ||
Line 75: | Line 116: | ||
$poseparameter "vehicle_wheel_rr_spin" -180 180 wrap | $poseparameter "vehicle_wheel_rr_spin" -180 180 wrap | ||
Here’s an example | All of the above should not be renamed. | ||
==Animations== | |||
Here’s an example .QC snippet that sets up animations for the pose parameters, including a steering wheel in the steering animation. | |||
<pre> | <pre> | ||
$animation neutral " | $animation neutral "<reference model SMD>" frames 0 0 | ||
$weightlist front_wheels { " | // steering | ||
$animation turn_left " | $weightlist front_wheels { "<steering front left bone>" 1.0 "<steering front right bone>" 1.0 "<steering wheel bone>" 1.0 } | ||
$animation turn_right " | $animation turn_left "<steering animation SMD>" frame 0 0 subtract neutral 0 weightlist front_wheels | ||
$animation turn_right "<steering animation SMD>" frame 2 2 subtract neutral 0 weightlist front_wheels | |||
$sequence turning { turn_left turn_right blend vehicle_steer -1 1 } weightlist front_wheels delta autoplay | $sequence turning { turn_left turn_right blend vehicle_steer -1 1 } weightlist front_wheels delta autoplay | ||
// front left | |||
$weightlist wheel_fl { "<steering front left bone>" 1.0 "<suspension front left bone>" 1.0 "<wheel front left bone>" 0.0 } | |||
$animation wheel_fl_low "<suspension animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_fl | |||
$animation wheel_fl_high "<suspension animation SMD>" frame 2 2 subtract neutral 0 weightlist wheel_fl | |||
$sequence wheel_fl_suspension { wheel_fl_low wheel_fl_high blend "vehicle_wheel_fl_height" 0 1.0 } weightlist wheel_fl delta autoplay | |||
$weightlist wheel_fl_spin { "<wheel front left bone>" 1.0 } | |||
$animation wheel_fl_spin0 "<wheelspin animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_fl_spin | |||
$animation wheel_fl_spin120 "<wheelspin animation SMD>" frame 3 3 subtract neutral 0 weightlist wheel_fl_spin | |||
$animation wheel_fl_spin240 "<wheelspin animation SMD>" frame 6 6 subtract neutral 0 weightlist wheel_fl_spin | |||
$sequence wheel_fl_spin { wheel_fl_spin0 wheel_fl_spin120 wheel_fl_spin240 wheel_fl_spin0 blendwidth 4 blend "vehicle_wheel_fl_spin" -180 180 } weightlist wheel_fl_spin delta autoplay | |||
// front right | // front right | ||
$weightlist wheel_fr { " | $weightlist wheel_fr { "<steering front right bone>" 1.0 "<suspension front right bone>" 1.0 "<wheel front right bone>" 0.0 } | ||
$animation wheel_fr_low " | $animation wheel_fr_low "<suspension animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_fr | ||
$animation wheel_fr_high " | $animation wheel_fr_high "<suspension animation SMD>" frame 2 2 subtract neutral 0 weightlist wheel_fr | ||
$sequence wheel_fr_suspension { wheel_fr_low wheel_fr_high blend "vehicle_wheel_fr_height" 0 1.0 } weightlist wheel_fr delta autoplay | $sequence wheel_fr_suspension { wheel_fr_low wheel_fr_high blend "vehicle_wheel_fr_height" 0 1.0 } weightlist wheel_fr delta autoplay | ||
$animation wheel_fr_spin0 " | $weightlist wheel_fr_spin { "<wheel front right bone>" 1.0 } | ||
$animation wheel_fr_spin120 " | $animation wheel_fr_spin0 "<wheelspin animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_fr_spin | ||
$animation wheel_fr_spin240 " | $animation wheel_fr_spin120 "<wheelspin animation SMD>" frame 3 3 subtract neutral 0 weightlist wheel_fr_spin | ||
$sequence wheel_fr_spin { wheel_fr_spin0 wheel_fr_spin120 wheel_fr_spin240 wheel_fr_spin0 blendwidth 4 blend "vehicle_wheel_fr_spin" -180 180 } weightlist | $animation wheel_fr_spin240 "<wheelspin animation SMD>" frame 6 6 subtract neutral 0 weightlist wheel_fr_spin | ||
$sequence wheel_fr_spin { wheel_fr_spin0 wheel_fr_spin120 wheel_fr_spin240 wheel_fr_spin0 blendwidth 4 blend "vehicle_wheel_fr_spin" -180 180 } weightlist wheel_fr_spin delta autoplay | |||
// rear left | |||
$weightlist wheel_rl { "<suspension rear left bone>" 1.0 "<wheel rear left bone>" 0.0 } | |||
$animation wheel_rl_low "<suspension animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_rl | |||
$animation wheel_rl_high "<suspension animation SMD>" frame 2 2 subtract neutral 0 weightlist wheel_rl | |||
$sequence wheel_rl_suspension { wheel_rl_low wheel_rl_high blend "vehicle_wheel_rl_height" 0 1.0 } weightlist wheel_rl delta autoplay | |||
$weightlist wheel_rl_spin { "<wheel rear left bone>" 1.0 } | |||
$animation wheel_rl_spin0 "<wheelspin animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_rl_spin | |||
$animation wheel_rl_spin120 "<wheelspin animation SMD>" frame 3 3 subtract neutral 0 weightlist wheel_rl_spin | |||
$animation wheel_rl_spin240 "<wheelspin animation SMD>" frame 6 6 subtract neutral 0 weightlist wheel_rl_spin | |||
$sequence wheel_rl_spin { wheel_rl_spin0 wheel_rl_spin120 wheel_rl_spin240 wheel_rl_spin0 blendwidth 4 blend "vehicle_wheel_rl_spin" -180 180 } weightlist wheel_rl_spin delta autoplay | |||
// rear right | // rear right | ||
$weightlist wheel_rr { " | $weightlist wheel_rr { "<suspension rear right bone>" 1.0 "<wheel rear right bone>" 0.0 } | ||
$animation wheel_rr_low " | $animation wheel_rr_low "<suspension animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_rr | ||
$animation wheel_rr_high " | $animation wheel_rr_high "<suspension animation SMD>" frame 2 2 subtract neutral 0 weightlist wheel_rr | ||
$sequence wheel_rr_suspension { wheel_rr_low wheel_rr_high blend "vehicle_wheel_rr_height" 0 1.0 } weightlist wheel_rr delta autoplay | $sequence wheel_rr_suspension { wheel_rr_low wheel_rr_high blend "vehicle_wheel_rr_height" 0 1.0 } weightlist wheel_rr delta autoplay | ||
$weightlist wheel_rr_spin { "<wheel rear right bone>" 1.0 } | |||
$weightlist | $animation wheel_rr_spin0 "<wheelspin animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_rr_spin | ||
$animation | $animation wheel_rr_spin120 "<wheelspin animation SMD>" frame 3 3 subtract neutral 0 weightlist wheel_rr_spin | ||
$animation | $animation wheel_rr_spin240 "<wheelspin animation SMD>" frame 6 6 subtract neutral 0 weightlist wheel_rr_spin | ||
$sequence wheel_rr_spin { wheel_rr_spin0 wheel_rr_spin120 wheel_rr_spin240 wheel_rr_spin0 blendwidth 4 blend "vehicle_wheel_rr_spin" -180 180 } weightlist wheel_rr_spin delta autoplay | |||
$animation | |||
$sequence | |||
</pre> | </pre> | ||
If you don't want an animated steering wheel, simply remove its bone from the <code>front_wheels</code> $weightlist. | |||
You might need to include a basic idle animation, like this: | |||
$sequence "idle" "<reference model SMD>" activity ACT_IDLE -1 loop fps 30 | |||
=Miscellaneous= | |||
==Model origin note== | |||
If your model is pivoted by 90 to 180 degrees relative to the direction it actually drives while its animations are as they should be, to easily fix it, try using an [[$origin]] line like this: | |||
$origin 0 0 0 90 | |||
==Gauge animations== | |||
For either method, use this $poseparameter line: | |||
$poseparameter "vehicle_guage" 0 1 | |||
===Simple=== | |||
For a simple animation with a single gauge needle, like in the Half-Life 2 buggy: | |||
<pre> | <pre> | ||
$weightlist speedo { "<gauge needle bone>" 1.0 } | |||
{ | $animation slow "<gauge animation SMD>" frame 0 0 subtract neutral 0 weightlist speedo | ||
$animation mid "<gauge animation SMD>" frame 1 1 subtract neutral 0 weightlist speedo | |||
$animation fast "<gauge animation SMD>" frame 2 2 subtract neutral 0 weightlist speedo | |||
$sequence speedometer { slow mid fast blend vehicle_guage 0 1 } weightlist speedo delta autoplay | |||
} | |||
</pre> | </pre> | ||
You may need to give the animation a linear curve. | |||
===Advanced=== | |||
For an animation with two gauge needles moving independently, as in a traditional car's gauge cluster: | |||
<pre> | |||
$weightlist speedo { "<gauge needle speedo bone>" 1.0 "<gauge needle tacho bone>" 1.0 } | |||
$animation speedo1 "<gauge animation SMD>" frame 0 0 subtract neutral 0 weightlist speedo | |||
$animation speedo2 "<gauge animation SMD>" frame 1 1 subtract neutral 0 weightlist speedo | |||
$animation speedo3 "<gauge animation SMD>" frame 2 2 subtract neutral 0 weightlist speedo | |||
$animation speedo4 "<gauge animation SMD>" frame 3 3 subtract neutral 0 weightlist speedo | |||
$animation speedo5 "<gauge animation SMD>" frame 4 4 subtract neutral 0 weightlist speedo | |||
$animation speedo6 "<gauge animation SMD>" frame 5 5 subtract neutral 0 weightlist speedo | |||
$animation speedo7 "<gauge animation SMD>" frame 6 6 subtract neutral 0 weightlist speedo | |||
$animation speedo8 "<gauge animation SMD>" frame 7 7 subtract neutral 0 weightlist speedo | |||
$animation speedo9 "<gauge animation SMD>" frame 8 8 subtract neutral 0 weightlist speedo | |||
$animation speedo10 "<gauge animation SMD>" frame 9 9 subtract neutral 0 weightlist speedo | |||
$animation speedo11 "<gauge animation SMD>" frame 10 10 subtract neutral 0 weightlist speedo | |||
$animation speedo12 "<gauge animation SMD>" frame 11 11 subtract neutral 0 weightlist speedo | |||
$animation speedo13 "<gauge animation SMD>" frame 12 12 subtract neutral 0 weightlist speedo | |||
$animation speedo14 "<gauge animation SMD>" frame 13 13 subtract neutral 0 weightlist speedo | |||
$animation speedo15 "<gauge animation SMD>" frame 14 14 subtract neutral 0 weightlist speedo | |||
$animation speedo16 "<gauge animation SMD>" frame 15 15 subtract neutral 0 weightlist speedo | |||
$animation speedo17 "<gauge animation SMD>" frame 16 16 subtract neutral 0 weightlist speedo | |||
$animation speedo18 "<gauge animation SMD>" frame 17 17 subtract neutral 0 weightlist speedo | |||
$animation speedo19 "<gauge animation SMD>" frame 18 18 subtract neutral 0 weightlist speedo | |||
$animation speedo20 "<gauge animation SMD>" frame 19 19 subtract neutral 0 weightlist speedo | |||
$sequence speedometer { speedo1 speedo2 speedo3 speedo4 speedo5 speedo6 speedo7 speedo8 speedo9 speedo10 speedo11 speedo12 speedo13 speedo14 speedo15 speedo16 speedo17 speedo18 speedo19 speedo20 blend vehicle_guage 0 1 } blendwidth 20 weightlist speedo delta autoplay | |||
</pre> | |||
In this example, 20 frames were animated, but you can use as many as you want, as long as you change the code to account for differences in frame amounts. | |||
== Making the steering wheel turn further than 180 degrees == | |||
'' | Because of how animation SMDs work, if a bone rotates over 180 degrees over one frame, its rotation direction will appear to be the opposite of what you might've intended. To avoid this, you can animate in a way so that there's no more than 180 degrees of rotation in individual frames. | ||
This setup allows for about 2.5 proper revolutions of the steering wheel, when turning one way: | |||
<pre> | |||
$weightlist front_wheels { "<steering front left bone>" 1.0 "<steering front right bone>" 1.0 "<steering wheel bone>" 1.0 } | |||
$animation steer1 "<steering animation SMD>" frame 0 0 subtract neutral 0 weightlist front_wheels | |||
$animation steer2 "<steering animation SMD>" frame 1 1 subtract neutral 0 weightlist front_wheels | |||
$animation steer3 "<steering animation SMD>" frame 2 2 subtract neutral 0 weightlist front_wheels | |||
$animation steer4 "<steering animation SMD>" frame 3 3 subtract neutral 0 weightlist front_wheels | |||
$animation steer5 "<steering animation SMD>" frame 4 4 subtract neutral 0 weightlist front_wheels | |||
$animation steer6 "<steering animation SMD>" frame 5 5 subtract neutral 0 weightlist front_wheels // center frame | |||
$animation steer7 "<steering animation SMD>" frame 6 6 subtract neutral 0 weightlist front_wheels | |||
$animation steer8 "<steering animation SMD>" frame 7 7 subtract neutral 0 weightlist front_wheels | |||
$animation steer9 "<steering animation SMD>" frame 8 8 subtract neutral 0 weightlist front_wheels | |||
$animation steer10 "<steering animation SMD>" frame 9 9 subtract neutral 0 weightlist front_wheels | |||
$animation steer11 "<steering animation SMD>" frame 10 10 subtract neutral 0 weightlist front_wheels | |||
$sequence turning { steer1 steer2 steer3 steer4 steer5 steer6 steer7 steer8 steer9 steer10 steer11 blend vehicle_steer -1 1 } blendwidth 11 weightlist front_wheels delta autoplay | |||
</pre> | |||
When creating your own animation for such a setup, make sure to have an even amount of frames for both turning directions, with a center frame in the middle. | |||
As with the above advanced gauge setup, it's possible to have more or less than 10 frames. | |||
=See also= | |||
* [[ | * [[Vehicles (Scripting Parameters)]] | ||
* [[prop_vehicle]] | * [[prop_vehicle]] | ||
* [[.QC | * [[QC|.QC files]] |
Revision as of 14:50, 6 May 2017
This page describes how to set up a model for use as a functional vehicle, with basic animations, and optionally, gauge animations.
SMD prerequisites
Reference model
Your reference model at minimum needs the following bones in order to work:
- suspension front left -> steering front left -> wheel front left
- suspension front right -> steering front right -> wheel front right
- suspension rear left -> wheel rear left
- suspension rear right -> wheel rear right
- view, located where the driver's view should be
Optionally:
- steering wheel
- gauge needle(s)
All of which should be children of a static root bone, and should follow the above hierarchy. You may name them anything, as long as you edit the following code examples accordingly.
Your respective meshes need to be rigged to their respective bones.
Collision model
All vehicles need physical models, so you need to set up a collision model. See $collisionmodel.
To get started, you can simply use a copy of the reference model of your vehicle, but make sure to remove the wheels from the model, as wheel collisions aren't defined in the collision model itself, but at runtime, based on the entire compiled model's wheel attachments. Note that doing this will give your model a convex collision model.
If you have the time for it, modelling a low-poly version of the vehicle specifically for use as a collision model can be useful, both for optimization, and because it can be concave. See Collision mesh.
Basic animations
Vehicles require a few basic animations in order to work properly.
- An animation SMD with only the suspension bones animated. This may be 2 frames (fully compressed, fully extended). This sequence determines the suspension travel each wheel has.
- An animation SMD with only the wheel bones individually spinning one full revolution. This may be 9 frames, and may need a linear animation curve, defined before the animation is exported in the model editor you use.
- An animation SMD with the steering of the wheels, with only the steering bones (and the steering wheel bone if it exists) and not the wheel bones animated. This may be just 3 frames (left, centered, right). Be sure to note the exact angle that the wheels turn to and make it consistent. You’ll need to put that angle into the vehicle’s script file so that the physics will match the animation.
Note that with just 3 frames, if you animate a steering wheel, it can't turn further than 90 degrees one way without breaking the centered position, which might be unsuitable for some models. See Making the steering wheel turn further than 180 degrees.
QC setup
Attachments
Wheels
You need to set up attachments for all four wheels, to define where they are located in the model.
$attachment "wheel_fl" "<wheel front left bone>" 0 0 8 $attachment "wheel_fr" "<wheel front right bone>" 0 0 -8 $attachment "wheel_rl" "<wheel rear left bone>" 0 0 8 $attachment "wheel_rr" "<wheel rear right bone>" 0 0 –8
You must name the attachments as above. You may however name their respective bones anything, and you may place the $attachment lines anywhere in your .QC.
Only four wheels may be simulated in one vehicle. Their attachments are named with two letter codes:
fl
"front left"fr
"front right"rl
"rear left"rr
"rear right"
One important detail is that the wheels are simulated as spheres. For this reason, you may want to pull the attachments slightly inwards. The origin of the wheel bones is actually the center of the wheel graphically, but in order to avoid having the spherical wheel collisions poke out from the sides of the vehicle (thus brushing against things next to it), you might want to pull the attachments in by a bit.
For example, this would place the wheel sphere exactly over its graphical representation:
$attachment "wheel_fl" "<wheel front left bone>" 0 0 0
While this adjusts it inwards by 8 inches:
$attachment "wheel_fl" "<wheel front left bone>" 0 0 8
The amount to pull them in depends on the size of the wheels and the collision model of the vehicle. In this case, the wheels have a radius of about 22.5 inches and I’ve pulled them in by 8 inches. Using this ratio is a good starting point.
Driver's view
This line defines where your view is going to be when driving.
$attachment "vehicle_driver_eyes" "<view bone>" 0 0 0
As with the wheel attachments, this attachment must be named vehicle_driver_eyes
.
Miscellaneous attachments
These are some miscellaneous attachments that might be required, with approximate positions that you might have to tweak.
$attachment "vehicle_feet_passenger0" "<view bone>" 0 0.00 -27.00 $attachment "vehicle_engine" "<root bone>" 40.00 0.00 17.00
The vehicle_feet_passenger0
attachment determines where the driver's third person player model is located. It doesn't need to be based on the view bone - you can instead set up an individual bone for it.
Pose parameters
You need the following $poseparameter lines to allow the physics to interact with your model.
This line is for the steering. –1 is left, +1 is right.
$poseparameter "vehicle_steer" -1 1
These lines are for the suspension states of each wheel. 0 is compressed, 1 is extended.
$poseparameter "vehicle_wheel_fl_height" 0 1 $poseparameter "vehicle_wheel_fr_height" 0 1 $poseparameter "vehicle_wheel_rl_height" 0 1 $poseparameter "vehicle_wheel_rr_height" 0 1
These lines are for the rotation of each wheel. +/- 180 degrees from base rotation.
$poseparameter "vehicle_wheel_fl_spin" -180 180 wrap $poseparameter "vehicle_wheel_fr_spin" -180 180 wrap $poseparameter "vehicle_wheel_rl_spin" -180 180 wrap $poseparameter "vehicle_wheel_rr_spin" -180 180 wrap
All of the above should not be renamed.
Animations
Here’s an example .QC snippet that sets up animations for the pose parameters, including a steering wheel in the steering animation.
$animation neutral "<reference model SMD>" frames 0 0 // steering $weightlist front_wheels { "<steering front left bone>" 1.0 "<steering front right bone>" 1.0 "<steering wheel bone>" 1.0 } $animation turn_left "<steering animation SMD>" frame 0 0 subtract neutral 0 weightlist front_wheels $animation turn_right "<steering animation SMD>" frame 2 2 subtract neutral 0 weightlist front_wheels $sequence turning { turn_left turn_right blend vehicle_steer -1 1 } weightlist front_wheels delta autoplay // front left $weightlist wheel_fl { "<steering front left bone>" 1.0 "<suspension front left bone>" 1.0 "<wheel front left bone>" 0.0 } $animation wheel_fl_low "<suspension animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_fl $animation wheel_fl_high "<suspension animation SMD>" frame 2 2 subtract neutral 0 weightlist wheel_fl $sequence wheel_fl_suspension { wheel_fl_low wheel_fl_high blend "vehicle_wheel_fl_height" 0 1.0 } weightlist wheel_fl delta autoplay $weightlist wheel_fl_spin { "<wheel front left bone>" 1.0 } $animation wheel_fl_spin0 "<wheelspin animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_fl_spin $animation wheel_fl_spin120 "<wheelspin animation SMD>" frame 3 3 subtract neutral 0 weightlist wheel_fl_spin $animation wheel_fl_spin240 "<wheelspin animation SMD>" frame 6 6 subtract neutral 0 weightlist wheel_fl_spin $sequence wheel_fl_spin { wheel_fl_spin0 wheel_fl_spin120 wheel_fl_spin240 wheel_fl_spin0 blendwidth 4 blend "vehicle_wheel_fl_spin" -180 180 } weightlist wheel_fl_spin delta autoplay // front right $weightlist wheel_fr { "<steering front right bone>" 1.0 "<suspension front right bone>" 1.0 "<wheel front right bone>" 0.0 } $animation wheel_fr_low "<suspension animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_fr $animation wheel_fr_high "<suspension animation SMD>" frame 2 2 subtract neutral 0 weightlist wheel_fr $sequence wheel_fr_suspension { wheel_fr_low wheel_fr_high blend "vehicle_wheel_fr_height" 0 1.0 } weightlist wheel_fr delta autoplay $weightlist wheel_fr_spin { "<wheel front right bone>" 1.0 } $animation wheel_fr_spin0 "<wheelspin animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_fr_spin $animation wheel_fr_spin120 "<wheelspin animation SMD>" frame 3 3 subtract neutral 0 weightlist wheel_fr_spin $animation wheel_fr_spin240 "<wheelspin animation SMD>" frame 6 6 subtract neutral 0 weightlist wheel_fr_spin $sequence wheel_fr_spin { wheel_fr_spin0 wheel_fr_spin120 wheel_fr_spin240 wheel_fr_spin0 blendwidth 4 blend "vehicle_wheel_fr_spin" -180 180 } weightlist wheel_fr_spin delta autoplay // rear left $weightlist wheel_rl { "<suspension rear left bone>" 1.0 "<wheel rear left bone>" 0.0 } $animation wheel_rl_low "<suspension animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_rl $animation wheel_rl_high "<suspension animation SMD>" frame 2 2 subtract neutral 0 weightlist wheel_rl $sequence wheel_rl_suspension { wheel_rl_low wheel_rl_high blend "vehicle_wheel_rl_height" 0 1.0 } weightlist wheel_rl delta autoplay $weightlist wheel_rl_spin { "<wheel rear left bone>" 1.0 } $animation wheel_rl_spin0 "<wheelspin animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_rl_spin $animation wheel_rl_spin120 "<wheelspin animation SMD>" frame 3 3 subtract neutral 0 weightlist wheel_rl_spin $animation wheel_rl_spin240 "<wheelspin animation SMD>" frame 6 6 subtract neutral 0 weightlist wheel_rl_spin $sequence wheel_rl_spin { wheel_rl_spin0 wheel_rl_spin120 wheel_rl_spin240 wheel_rl_spin0 blendwidth 4 blend "vehicle_wheel_rl_spin" -180 180 } weightlist wheel_rl_spin delta autoplay // rear right $weightlist wheel_rr { "<suspension rear right bone>" 1.0 "<wheel rear right bone>" 0.0 } $animation wheel_rr_low "<suspension animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_rr $animation wheel_rr_high "<suspension animation SMD>" frame 2 2 subtract neutral 0 weightlist wheel_rr $sequence wheel_rr_suspension { wheel_rr_low wheel_rr_high blend "vehicle_wheel_rr_height" 0 1.0 } weightlist wheel_rr delta autoplay $weightlist wheel_rr_spin { "<wheel rear right bone>" 1.0 } $animation wheel_rr_spin0 "<wheelspin animation SMD>" frame 0 0 subtract neutral 0 weightlist wheel_rr_spin $animation wheel_rr_spin120 "<wheelspin animation SMD>" frame 3 3 subtract neutral 0 weightlist wheel_rr_spin $animation wheel_rr_spin240 "<wheelspin animation SMD>" frame 6 6 subtract neutral 0 weightlist wheel_rr_spin $sequence wheel_rr_spin { wheel_rr_spin0 wheel_rr_spin120 wheel_rr_spin240 wheel_rr_spin0 blendwidth 4 blend "vehicle_wheel_rr_spin" -180 180 } weightlist wheel_rr_spin delta autoplay
If you don't want an animated steering wheel, simply remove its bone from the front_wheels
$weightlist.
You might need to include a basic idle animation, like this:
$sequence "idle" "<reference model SMD>" activity ACT_IDLE -1 loop fps 30
Miscellaneous
Model origin note
If your model is pivoted by 90 to 180 degrees relative to the direction it actually drives while its animations are as they should be, to easily fix it, try using an $origin line like this:
$origin 0 0 0 90
Gauge animations
For either method, use this $poseparameter line:
$poseparameter "vehicle_guage" 0 1
Simple
For a simple animation with a single gauge needle, like in the Half-Life 2 buggy:
$weightlist speedo { "<gauge needle bone>" 1.0 } $animation slow "<gauge animation SMD>" frame 0 0 subtract neutral 0 weightlist speedo $animation mid "<gauge animation SMD>" frame 1 1 subtract neutral 0 weightlist speedo $animation fast "<gauge animation SMD>" frame 2 2 subtract neutral 0 weightlist speedo $sequence speedometer { slow mid fast blend vehicle_guage 0 1 } weightlist speedo delta autoplay
You may need to give the animation a linear curve.
Advanced
For an animation with two gauge needles moving independently, as in a traditional car's gauge cluster:
$weightlist speedo { "<gauge needle speedo bone>" 1.0 "<gauge needle tacho bone>" 1.0 } $animation speedo1 "<gauge animation SMD>" frame 0 0 subtract neutral 0 weightlist speedo $animation speedo2 "<gauge animation SMD>" frame 1 1 subtract neutral 0 weightlist speedo $animation speedo3 "<gauge animation SMD>" frame 2 2 subtract neutral 0 weightlist speedo $animation speedo4 "<gauge animation SMD>" frame 3 3 subtract neutral 0 weightlist speedo $animation speedo5 "<gauge animation SMD>" frame 4 4 subtract neutral 0 weightlist speedo $animation speedo6 "<gauge animation SMD>" frame 5 5 subtract neutral 0 weightlist speedo $animation speedo7 "<gauge animation SMD>" frame 6 6 subtract neutral 0 weightlist speedo $animation speedo8 "<gauge animation SMD>" frame 7 7 subtract neutral 0 weightlist speedo $animation speedo9 "<gauge animation SMD>" frame 8 8 subtract neutral 0 weightlist speedo $animation speedo10 "<gauge animation SMD>" frame 9 9 subtract neutral 0 weightlist speedo $animation speedo11 "<gauge animation SMD>" frame 10 10 subtract neutral 0 weightlist speedo $animation speedo12 "<gauge animation SMD>" frame 11 11 subtract neutral 0 weightlist speedo $animation speedo13 "<gauge animation SMD>" frame 12 12 subtract neutral 0 weightlist speedo $animation speedo14 "<gauge animation SMD>" frame 13 13 subtract neutral 0 weightlist speedo $animation speedo15 "<gauge animation SMD>" frame 14 14 subtract neutral 0 weightlist speedo $animation speedo16 "<gauge animation SMD>" frame 15 15 subtract neutral 0 weightlist speedo $animation speedo17 "<gauge animation SMD>" frame 16 16 subtract neutral 0 weightlist speedo $animation speedo18 "<gauge animation SMD>" frame 17 17 subtract neutral 0 weightlist speedo $animation speedo19 "<gauge animation SMD>" frame 18 18 subtract neutral 0 weightlist speedo $animation speedo20 "<gauge animation SMD>" frame 19 19 subtract neutral 0 weightlist speedo $sequence speedometer { speedo1 speedo2 speedo3 speedo4 speedo5 speedo6 speedo7 speedo8 speedo9 speedo10 speedo11 speedo12 speedo13 speedo14 speedo15 speedo16 speedo17 speedo18 speedo19 speedo20 blend vehicle_guage 0 1 } blendwidth 20 weightlist speedo delta autoplay
In this example, 20 frames were animated, but you can use as many as you want, as long as you change the code to account for differences in frame amounts.
Making the steering wheel turn further than 180 degrees
Because of how animation SMDs work, if a bone rotates over 180 degrees over one frame, its rotation direction will appear to be the opposite of what you might've intended. To avoid this, you can animate in a way so that there's no more than 180 degrees of rotation in individual frames.
This setup allows for about 2.5 proper revolutions of the steering wheel, when turning one way:
$weightlist front_wheels { "<steering front left bone>" 1.0 "<steering front right bone>" 1.0 "<steering wheel bone>" 1.0 } $animation steer1 "<steering animation SMD>" frame 0 0 subtract neutral 0 weightlist front_wheels $animation steer2 "<steering animation SMD>" frame 1 1 subtract neutral 0 weightlist front_wheels $animation steer3 "<steering animation SMD>" frame 2 2 subtract neutral 0 weightlist front_wheels $animation steer4 "<steering animation SMD>" frame 3 3 subtract neutral 0 weightlist front_wheels $animation steer5 "<steering animation SMD>" frame 4 4 subtract neutral 0 weightlist front_wheels $animation steer6 "<steering animation SMD>" frame 5 5 subtract neutral 0 weightlist front_wheels // center frame $animation steer7 "<steering animation SMD>" frame 6 6 subtract neutral 0 weightlist front_wheels $animation steer8 "<steering animation SMD>" frame 7 7 subtract neutral 0 weightlist front_wheels $animation steer9 "<steering animation SMD>" frame 8 8 subtract neutral 0 weightlist front_wheels $animation steer10 "<steering animation SMD>" frame 9 9 subtract neutral 0 weightlist front_wheels $animation steer11 "<steering animation SMD>" frame 10 10 subtract neutral 0 weightlist front_wheels $sequence turning { steer1 steer2 steer3 steer4 steer5 steer6 steer7 steer8 steer9 steer10 steer11 blend vehicle_steer -1 1 } blendwidth 11 weightlist front_wheels delta autoplay
When creating your own animation for such a setup, make sure to have an even amount of frames for both turning directions, with a center frame in the middle.
As with the above advanced gauge setup, it's possible to have more or less than 10 frames.