$proceduralbones
$proceduralbones
is a QC command available in all Source games. It uses a special definition file (VRD) to tell the engine to automatically animate certain bones at runtime.
Contents
- 1 Concept
- 2 Common applications of procedural bones
- 3 Syntax
- 4 VRD files
- 5 Building a Definition Block
- 6 Guides
- 7 Driving Flexes with Procedural Bones
Concept
Procedural bones, elsewhere known as bone "drivers" (Blender) or "driven keys" (Maya), use the rotation of one bone to drive the rotation and translation of another bone. The first bone - called the driver or control bone - is typically animated by a human, while the second bone - called the procedural or helper bone - automatically rotates and/or translates itself, according to the rotation of the driver bone. Special rotation keyframes, called "triggers" in the VRD, are used to map a range of motion in the driver bone to a range of motion in the procedural bone.
The human forearm, skinned with along-axis twist bones, is the poster child of procedural bones in Source. When the hand bone rotates clockwise, the twist bone in the forearm automatically rotates clockwise as well. When the hand bone rotate counterclockwise, the twist bone also rotates counterclockwise. The extents of both rotations can be easily controlled in the VRD file.
Common applications of procedural bones
- Reduce the time required to complete a pose or animation, since fewer bones need to be manipulated by the artist.
- Improve the appearance of a model when it imports an animation at runtime (i.e. via $includemodel) which does not animate all of the model's bones (notably, twist bones).
- Apply corrective skinning to the mesh, mitigating deformities caused by Source's linear skinning model and animation rules.
Twist bones
The most common use-case of procedural bones in Source is to apply the first two principles to twist bones, such as in the forearms, upper arms, thighs, and shins of human models. In the diagram at the right, a twist bone is placed in the middle of the forearm (ValveBiped.Bip01_L_Ulna), another twist bone is located on the wrist (ValveBiped.Bip01_L_Wrist), and the mesh is skinned accordingly. Rather than require the animator to pose the hand, wrist, and ulna all together, $proceduralbones
can be used to automatically rotate the ulna and wrist bones when the animator rotates only the hand bone. This saves time and effort not just when creating new poses, but also when importing poses and animations that were created on a simpler skeleton which might not include any twist bones.
Corrective Deformations
Working around Source's archaic limit of three bone influences per skinned vertex can be difficult, especially in regions such as the chest or pelvis of a biped or quadruped. There are two major ways that procedural bones can be used to improve the quality of mesh deformation in these problematic areas.
Leaf Bones
In areas where Source's linear skinning model causes loss of mesh volume, such as the elbows or knees, procedural bones can be used to counteract the undesirable pinching or stretching of the mesh. Introduce one or more leaf bones in the problematic area, and skin the mesh accordingly. Then, using $proceduralbones
, the rotation and translation of the leaf bones can be driven by the rotation the elbow or knee bone.
Corrective Flexes
In some engine branches† that support $boneflexdriver
, it is possible to use procedural bones to automatically fade in and fade out flexes‡. This technique lends itself most to applying local corrective or limited delta mush shapes to parts of a mesh that experience low-quality deformations, typically when put into extreme poses. Care must be taken when using this technique, since each corrective flex takes up a flexcontroller slot and requires a corresponding bone in the model's skeleton to drive it. This can quickly add up, counting against the MDL flexcontroller limit (usually 96 or 128) and bone limit (usually 128) and reducing the number of normal flexes and bones available to the model.
Self-collision Approximation
Procedural bones can simulate a quick and dirty approximation of collision between a model's parts. For example, consider a human model wearing a suit jacket. The hem of the jacket could be simply skinned to the thigh bones, such that the hem bends when the model lifts its knee. Alternatively, the hem could be skinned to a separate bone, and $proceduralbones
could be used to tell the hem bone to rotate when the thigh bone rotates. In the latter scenario, the hem still bends when the model lifts its knee, but the animator can now pose the thigh and hem independently, improving the model's versatility. Going a step further, several hem bones can be created on the front, sides, and back of the suit jacket, and $proceduralbones
can be used to only move the correct hem bone when the model's thigh moves. This way, when the model lifts its knee, the back hem of the jacket remains stationary, with only the front hem bending. This concept can also be applied to rigid accessories on a deforming model, especially in areas where multiple bones exert influence over the deforming mesh.
Syntax
$proceduralbones <configuration file>
The only valid argument to $proceduralbones
is the name of a special VRD (Valve rig data (?)) configuration file, which specifies which bones are procedural and their behavior. The format of this file is described in the sections below.
VRD files
VRD files work similarly to driven keys in Maya. The important hierarchy of the driver bone and procedural bone are defined, then two or more "triggers" are specified. Each trigger maps a discrete rotation of the driver bone to a discrete rotation and/or translation of the procedural bone. At runtime, the engine automatically interpolates the pose of the procedural bone between all of the defined triggers, biasing most towards whichever trigger the driver bone is closest to.
The Definition Block
Since $proceduralbones
can only be used once in your QC file, a single VRD file can define multiple procedural bones. Each definition block starts with a <helper>
line, a <basepos>
line, and is finished by one or more <trigger>
lines. To start a new definition block and define another procedural bone, simply start with a new <helper>
line after the last <trigger>
line.
Example: Hand-made VRD file for HWM Femscout model
Source Filmmaker was used to set up this VRD file, but you can use any modeling software that supports Source models.
<helper> hlp_forearm_L bip_lowerArm_L bip_lowerArm_L bip_hand_L
<basepos> -0.0003 -4.7578 -0.000685692
<trigger> 90 -0.140879 -7.0729 0.923253 2.05439e-06 -0.00011566 -0.0109454 0 0 0
<trigger> 90 -157.919 -89.6281 158.827 0.101044 -61.3622 -0.505184 0 0 0
<trigger> 90 -0.905463 81.1157 0.0128013 -1.79037e-05 49.6029 -0.0109647 0 0 0
<helper> hlp_forearm_R bip_lowerArm_R bip_lowerArm_R bip_hand_R
<basepos> -0.0502548 4.76207 -0.0109539
<trigger> 90 -0.116485 -7.07782 0.923253 -26.1455 -71.739 -60.6497 0 0 0
<trigger> 90 -0.288436 72.9621 0.610626 -72.1773 -44.2586 -20.2743 0 0 0
<trigger> 90 -179.149 -81.8242 -179.905 81.3212 -37.0352 -157.273 0 0 0
This model with source files is available here on MaxOfS2D's website.
Building a Definition Block
Step 1: <helper>
Every definition block starts with a <helper>
line. It specifies the driver bone, the procedural bone, and their parents.
<helper> ProceduralBone ParentOfProceduralBone ParentOfDriverBone DriverBone
ProceduralBone
is the name of the bone which will be procedurally animated. In a typical human forearm setup, this would be the ulna twist bone.ParentOfProceduralBone
must be the parent ofProceduralBone
.ParentOfDriverBone
must be the parent ofDriverBone
.DriverBone
is the name of the bone whose rotation will causeProceduralBone
to animate. In a typical human forearm setup, this would be the hand bone.
Example: <helper> hlp_forearm_L bip_lowerArm_L bip_lowerArm_L bip_hand_L
.
period character, which is commonly used in Valve's skeletons. To work around this, simply strip everything up to and including the period when you enter your bone names into the VRD file. For example, instead of writing ValveBiped.Bip01_L_Hand
, type out Bip01_L_Hand
. Notes on Bone Hierarchy
If ProceduralBone
and DriverBone
are siblings, then ParentOfProceduralBone
and ParentOfDriverBone
will be the same bone. This is often the case for twist bone setups in arms and legs.
Alternatively, it is possible to define a procedural rule wherein the procedural bone and driver bone are not siblings. Accordingly, ParentOfProceduralBone
and ParentOfDriverBone
will be different bones. In this case, however, there must be a clear path in the skeleton's hierachy between ParentOfProceduralBone
and ParentOfDriverBone
. Three scenarios are possible: 1) ParentOfProceduralBone
and ParentOfDriverBone
share a common ancestor bone; 2) ParentOfProceduralBone
is the immediate parent of ParentOfDriverBone
; or 3) ParentOfDriverBone
is the immediate parent of ParentOfProceduralBone
. Lastly, it is also possible for the procedural bone to be a direct child of the driver bone, in which case ParentOfProceduralBone
and DriverBone
will be the same.
Step 2: <basepos>
This is the reference translation of the procedural bone in the local coordinate system of its parent bone.
<basepos> X Y Z
Example: <basepos> -0.0003 -4.7578 -0.000685692
Find or create a script to calculate this value in your modeling software.
Alternatively, you can use Crowbar to get this value without needing modeling software. Decompile your model, then find the $definebone
line for the procedural bone. The first 3 numbers are the bone's reference position in parent-bone-space.
Step 3: The Reference <trigger>
Each <trigger>
is a keyframe that maps a watched rotation of the driver bone to a desired rotation of the procedural bone. While not strictly necessary, the first <trigger>
should specify the reference pose rotations of the driver bone and the procedural bone.
<trigger> AngleOfInfluence Vec3_WatchedDriverBoneRotation Vec3_DesiredProceduralBoneRotation Vec3_DesiredProceduralBoneTranslation
AngleOfInfluence
is in degrees and specifies how far the driver bone must rotate in order for the procedural bone to reach the full extent of its rotation & translation.
- Visualize the
AngleOfInfluence
as a cone; the procedural bone reaches the full extent of its desired rotation & translation when the watched driver bone's rotation reaches or exceeds the bounds of the cone. With a larger angle, like 90 degrees, the driver bone must rotate a great deal before the procedural bone reaches its full desired rotation & translation. With a smaller angle, like 30 degrees, the driver bone does not need to rotate very far in order for the procedural bone to reach its full desired rotation & translation.
Vec3_WatchedDriverBoneRotation
is the input rotation of the driver bone, specified in degrees as X Y Z Euler angles.Vec3_DesiredProceduralBoneRotation
is the output rotation of the procedural bone, specified in degrees as X Y Z Euler angles.Vec3_DesiredProceduralBoneTranslation
is the translation of the procedural bone, in the local coordinate system of its parent bone. This value is relative to the<basepos>
defined earlier!
Place your model in its reference pose, then gather the parent-bone-space rotations for Vec3_WatchedDriverBoneRotation
and Vec3_DesiredProceduralBoneRotation
. Vec3_DesiredProceduralBoneTranslation
will be 0 0 0
. Type out the new <trigger>
line in your VRD file.
Example:
// AoI Vec3_WatchedDriverBoneRotation Vec3_DesiredProceduralBoneRotation Vec3_DesiredProceduralBoneTranslation
<trigger> 90 -0.140879 -7.0729 0.923253 2.05439e-06 -0.00011566 -0.0109454 0 0 0
Choosing an Angle of Influence
Each <trigger>
can have a different AngleOfInfluence
. The reference <trigger>
's AngleOfInfluence
should typically be the maximum angular deflection that the driver bone can possibly experience. The best way to determine this is to first determine the AngleOfInfluence
for every extreme <trigger>
(see the upcoming section). Then, identify the extreme <trigger>
with the largest AngleOfInfluence
, and simply copy that value to the reference <trigger>
's AngleOfInfluence
.
Step 4: The Extreme <trigger>s
There is where the procedural animation of your procedural bone is finally defined.
- First, determine the extreme(s) of your driver bone's range of motion, which will vary for each part of your model. In the case of the hand driver bone for a human forearm, this will typically be about 100 degrees clockwise and counterclockwise.
- In your modeling software, rotate the driver bone to the first extreme. This is the watched driver bone rotation.
- Pose the procedural bone accordingly, so that the model "looks good". This is the desired procedural bone rotation and/or translation.
Gather the parent-bone-space rotations for Vec3_WatchedDriverBoneRotation
and Vec3_DesiredProceduralBoneRotation
. If you did not translate the procedural bone, then Vec3_DesiredProceduralBoneTranslation
will be 0 0 0
; otherwise, also gather the parent-bone-space translation of the procedural bone. Lastly, determine a suitable AngleOfInfluence
; in most cases, this can simply be the angle between the drivers bone's new rotation and its old rotation. Type out the new <trigger>
line in your VRD file.
Example:
// AoI Vec3_WatchedDriverBoneRotation Vec3_DesiredProceduralBoneRotation Vec3_DesiredProceduralBoneTranslation
<trigger> 90 -157.919 -89.6281 158.827 0.101044 -61.3622 -0.505184 0 0 0
Repeat this process and create a new <trigger>
for each extreme pose of the driver bone. When you are done, you should have at least two <trigger>
s in your definition block. The first is the reference <trigger>
, the subsequent ones are the extremes.
Example:
<helper> hlp_forearm_L bip_lowerArm_L bip_lowerArm_L bip_hand_L
<basepos> -0.0003 -4.7578 -0.000685692
<trigger> 90 -0.140879 -7.0729 0.923253 2.05439e-06 -0.00011566 -0.0109454 0 0 0
<trigger> 90 -157.919 -89.6281 158.827 0.101044 -61.3622 -0.505184 0 0 0
<trigger> 90 -0.905463 81.1157 0.0128013 -1.79037e-05 49.6029 -0.0109647 0 0 0
<trigger>
s for them is a subjective process! It will vary between different characters and different parts of the same character.Example process with a human forearm
Three <trigger>
s are required in total: 1) the reference pose, 2) one pose where the driver bone (the hand) is rotated clockwise as far as it should go, and 3) one pose where the driver bone is rotated counterclockwise as far as it should go. Determining how far the hand should rotate both ways is subjective and depends on your model. Ultimately, you are creating procedural bones to improve your model's appearance, so pick what looks best.
- Create the
<trigger>
for the reference pose, as detailed above. - Create the
<trigger>
for the clockwise extreme.
- Rotate the hand bone clockwise along the forearm's axis, as far as it is supposed to go.
- Rotate the ulna twist bone clockwise along the forearm's axis until the mesh's deformation looks acceptable.
- Type out a
<trigger>
for this pose.
- Return your model to its reference pose.
- Create the
<trigger>
for the counterclockwise extreme.
- Rotate the hand bone counterclockwise along the forearm's axis, as far as it is supposed to go.
- Rotate the ulna twist bone counterclockwise along the forearm's axis until the mesh's deformation looks acceptable.
- Type out a
<trigger>
for this pose.
Wrapping Up and Idiosyncrasies
For symmetrical models, such as humans, you will want to repeat the above process to create the same procedural bone layout on the mirrored side of your character. Unless you know exactly what you are doing, do not simply copy and paste all of the numbers from the left side bones to the right side bones, or vice versa. Go through every step of the entire process and create a new definition block for every procedural bone you need to define.
A procedural bone cannot be controlled by two or more driver bones. The reverse, however, is possible: one driver bone can be re-used multiple times to control more than one procedural bone.
Miscellaneous
You can specify a useless name for a trigger:
<trigger> 90 -6.75868e-015 1.59028e-015 3.18055e-015 0 0 0 0 0 0 UselessTriggerName
This name has no functional bearing and is ignored.
Other Valid Keywords
Aside from <helper>
, <basepos>
, and <trigger>
, studiomdl accepts a few other keywords in VRD files.
<display>
The <display>
keyword is used by Softimage Mod Tool to store the attributes for procedural bone's appearance in Mod Tool's viewport. Useless to anyone who doesn't use Softimage.
<rotateaxis> X Y Z
Specified as an X Y Z Euler angle. The Vec3_DesiredProceduralBoneRotation
angle in all subsequent <trigger>
lines is pre-multiplied by this angle.
<jointorient> X Y Z
Specified as an X Y Z Euler angle. The Vec3_DesiredProceduralBoneRotation
angle in all subsequent <trigger>
lines is post-multiplied by this angle.
<aimconstraint>
<aimconstraint> ProceduralBone ParentOfProceduralBone TargetBoneOrAttachment
Works with other keywords <aimvector>
and <upvector>
. Presumably creates a procedural bone that functions like an aim constraint in Maya.
Guides
- This Facepunch guide (backed up on steam) describes the process of crafting a VRD file, using Source Filmmaker.
- This Steam Guide shows how to do this in entirely in Blender, with the help of an addon.
Driving Flexes with Procedural Bones
As noted earlier, using $proceduralbones
to automatically drive a $boneflexdriver
allows for advanced deformation techniques, such as automatic corrective shapes. Two extra steps are required when compiling your model to achieve this technique in most Source games and engine branches.
Step 1: Modifying studiomdl
Retail releases of studiomdl refuse to compile models that use $boneflexdriver
on any bone which is marked as the ProceduralBone
in $proceduralbones
's VRD file. Extra effort is required to modify either the output MDL file or studiomdl itself into allowing this combination. The latter is typically the path of least resistance.
Using the hex editor of your choice, studiomdl can be patched into skipping the early exit and successfully compiling your model. Be aware that modified studiomdls might produce MDLs which deviate from the specification expected by the engine, and these MDLs may or may not work in any given game or engine branch.
- Source 2013 branch studiomdls
- Aka most IDST0 games, including Half-Life 2, Counter-Strike: Source, Portal, Team Fortress 2, and Garry's Mod.
- Search for the unique byte sequence
04 74 25 8D 4F
, then change the byte74
toEB
.
- Alien Swarm's studiomdl
- Search for the unique byte sequence
04 74 25 8B
, then change the byte74
toEB
.
- Source Filmmaker's studiomdl
- Search for the unique byte sequence
04 74 1C 8B 56 5C
, then change the byte74
toEB
.
- Portal 2's studiomdl
- Search for the unique byte sequence
04 74 28 8B
, then change the byte74
toEB
.
Step 2: $bonemerge
In your model's QC file, you must specify $bonemerge
on every bone that you make procedural. Refer to your VRD file, and add $bonemerge
line(s) to your QC for the ProceduralBone
of every <helper>
line. The DriverBone
s do not need $bonemerge
.
The reasoning behind the requirement of the seemingly unrelated $bonemerge
flag is not yet fully understood.
Step 3: Compile your model
With studiomdl modified, and $bonemerge
specified for all procedural bones, you can now compile your model. Test it in HLMV and verify that everything works as intended. The animation of the skeleton drives the procedural bone(s), which in turn drive the flexcontroller(s).