Player Models

From Valve Developer Community
Jump to navigation Jump to search
CT GIGN Variant A Player Model from CS:GO with weapon_ak47.

A player model is the collection of a mesh, animations, and physics model that makes up a character in Valve games. This page intends to be an overview of everything you need to do to make a player model, and a collection of links to more in-depth tutorials regarding specific components of player model creation. Everything here has an emphasis on Source Engine games.

Mesh and Skeleton

Player Model loaded in MilkShape 3D showing the mesh and its skeleton.

The mesh is the body of the player model. For Valve: Source games this will take the form of a .smd file. It is composed of UV-mapped faces whose vertices are assigned (weighted) to joints on the model's skeleton. For Source games a vertex can be assigned to multiple joints at the same time, for example a joint in a model's shoulder might be assigned at 60% to Spine 3, 30% to R Clavicle, and 10% to R UpperArm.

Basic information about .smds and modeling in general can be found here. For how to properly rig a player model in XSI, read this tutorial.

Hitboxes

Hitboxes on a CS:GO version of Zoey

When a player is alive in CS:S, Garry's Mod, or CS:GO, their physics model is not being used. Instead, to determine whether or not a player gets shot, and where they got shot, the games use hitboxes. Hitbox dimensions are defined in a model's .qc file and are parented to bones.

Example Hitbox code for a .qc file:

$hboxset "cstrike"
$hbox 3 "ValveBiped.Bip01_Pelvis" -6.420  -5.746  -6.859  4.580  4.580  6.837
$hbox 6 "ValveBiped.Bip01_L_Thigh" 1.819  -3.959  -2.140  22.149  3.424  4.580
$hbox 6 "ValveBiped.Bip01_L_Calf" 2.076  -3.210  -2.151  19.260  2.675  3.049
$hbox 6 "ValveBiped.Bip01_L_Foot" 1.872  -2.675  -2.408  5.617  9.694  2.408
$hbox 7 "ValveBiped.Bip01_R_Thigh" 1.819  -3.756  -4.580  22.149  3.424  2.140
$hbox 7 "ValveBiped.Bip01_R_Calf" 2.076  -3.210  -2.846  19.260  2.675  2.247
$hbox 7 "ValveBiped.Bip01_R_Foot" 1.872  -2.675  -2.408  5.617  9.694  2.408
$hbox 3 "ValveBiped.Bip01_Spine1" -4.280  -4.580  -6.388  3.210  5.885  6.281
$hbox 2 "ValveBiped.Bip01_Spine2" -4.280  -5.029  -6.088  3.210  5.885  5.981
$hbox 2 "ValveBiped.Bip01_Spine3" -4.280  -5.350  -5.885  2.921  5.147  5.885
$hbox 1 "ValveBiped.Bip01_Neck" 0.332  -3.017  -2.450  3.403  2.418  2.354
$hbox 1 "ValveBiped.Bip01_Head" -2.771  -2.878  -3.103  6.955  3.520  3.007
$hbox 4 "ValveBiped.Bip01_L_UpperArm" -2.675  -3.210  -2.140  12.840  3.210  2.140
$hbox 4 "ValveBiped.Bip01_L_Forearm" 0.000  -2.140  -2.140  9.630  2.140  2.140
$hbox 4 "ValveBiped.Bip01_L_Hand" -1.723  -1.220  -1.380  4.473  1.220  1.380
$hbox 5 "ValveBiped.Bip01_R_UpperArm" -2.675  -3.210  -2.140  12.840  3.210  2.140
$hbox 5 "ValveBiped.Bip01_R_Forearm" 0.000  -2.140  -2.140  9.630  2.140  2.140
$hbox 5 "ValveBiped.Bip01_R_Hand" -1.723  -1.220  -1.380  4.473  1.220  1.380
$hbox 4 "ValveBiped.Bip01_L_Clavicle" 0.000  -3.210  -5.350  7.490  4.280  3.210
$hbox 5 "ValveBiped.Bip01_R_Clavicle" 0.000  -3.210  -3.210  7.490  4.280  5.350
$hbox 1 "ValveBiped.Bip01_Head" -2.504  2.001  -1.102  6.302  5.297  0.995
$hbox 2 "ValveBiped.Bip01_Spine3" -0.300  -6.003  -4.997  5.500  2.504  5.104

To get default hitboxes you can decompile a default model for the game you're working with and copy the code from the mdldecompiler.qc file. However, if you aren't doing a simple re-skin you probably need to edit the hitboxes so that they match the new model's geometry more accurately.

Physics Model

When a player dies, the hitboxes are no longer used, and the dead player model falls to the ground as a ragdoll. The physics of the ragdoll are handled by a collision mesh. When you make a model you have a weighted and textured reference.smd for the actual model, and then you also have a phymodel.smd for the collisions. You can usually get a physics model by decompiling a default model, but if you have to make your own you need to make it out of convex shapes and have them attached to the exact same skeleton that your reference model uses.

Warning.pngWarning:If you don't use the same skeleton then you can end up with the floppy body glitch, where a dead ragdoll will spasm on the ground until it eventually comes to a rest.

Compiling

Custom player model in CS:GO after compiling with the example .qc file seen here.

With everything brought together, you can compile the model. To do that you need a good .qc file. You can get a decent .qc from decompiling a default model, but they're usually incomplete because the decompiler is making inferences instead of actually extracting the original .qc which was used to compile the model.

Below is a good and complete .qc file which was used to compile a player model for CS:GO and resulted in no errors or other problems:

$cd "C:\Source Stuff\Modeling\Player Models\Evangelion\asuka"
$modelname "player\natalya\evangelion\asuka\asuka-dress.mdl"
$model "body" "asuka-dress.smd"
$poseparameter move_yaw -180.00 180.00 360.00
$poseparameter body_pitch -90.00 90.00 360.00
$poseparameter body_yaw -90.00 90.00 360.00
$opaque
$cdmaterials "models\player\natalya\evangelion\asuka\"

$hbox 3 "ValveBiped.Bip01_Pelvis" -3.000 -7.000  -7.000  5.000  2.000  7.000
$hbox 6 "ValveBiped.Bip01_L_Thigh" 1.000  -6.200  -3.000  20.000  1.400  4.000
$hbox 6 "ValveBiped.Bip01_L_Calf" -0.00  -5.000  -1.800  18.000  1.200  3.400
$hbox 6 "ValveBiped.Bip01_L_Foot" 1.000  -3.000  -1.800  6.000  8.000  2.800
$hbox 7 "ValveBiped.Bip01_R_Thigh" 1.000  -6.200  -4.000  20.000  1.400  3.000
$hbox 7 "ValveBiped.Bip01_R_Calf" -0.00  -5.000  -3.400  18.000  1.200  1.800
$hbox 7 "ValveBiped.Bip01_R_Foot" 1.000  -3.000  -2.800  6.000  8.000  1.800
$hbox 3 "ValveBiped.Bip01_Spine1" -3.000  -4.600 -5.600  7.000  3.000  5.600
$hbox 2 "ValveBiped.Bip01_Spine2" 2.000  -6.400  -6.000  10.000  4.600  6.000
$hbox 1 "ValveBiped.Bip01_Neck" 0.000  -2.000  -2.400  5.000 3.000  2.400
$hbox 1 "ValveBiped.Bip01_Head" -1.250  -4.500  -3.400  7.750  3.900  3.400
$hbox 4 "ValveBiped.Bip01_L_UpperArm" -3.000  -2.000  -2.000  12.000  2.000  2.000
$hbox 4 "ValveBiped.Bip01_L_Forearm" -1.600  -1.600  -1.800  12.000  1.600  1.600
$hbox 4 "ValveBiped.Bip01_L_Hand" 0.000  -1.000  -1.600  5.000  1.500  1.000
$hbox 5 "ValveBiped.Bip01_R_UpperArm" -3.000  -2.000  -2.000  12.000  2.000  2.000
$hbox 5 "ValveBiped.Bip01_R_Forearm" -1.600  -1.600  -1.600  12.000  1.600  1.800
$hbox 5 "ValveBiped.Bip01_R_Hand" 0.000  -1.000  -1.600  5.000  1.500  1.000
$skipboneinbbox

$attachment "forward" "ValveBiped.forward" 0.00 0.00 0.00 rotate -0.00 0.00 0.00
$attachment "mag_eject" "ValveBiped.weapon_bone_Clip" 0.00 0.00 0.00 rotate -90.00 -90.00 0.00
$attachment "mag_eject2" "ValveBiped.weapon_bone_Clip2" 0.00 0.00 0.00 rotate -90.00 -90.00 0.00
$attachment "weapon_hand_R" "weapon_hand_R" 0 0 0 rotate 0 0 0
$attachment "weapon_hand_L" "weapon_hand_L" 0 0 0 rotate 0 0 0
$attachment "grenade0" "ValveBiped.Bip01_Pelvis" 1.51 -2.40 9.00 rotate 83.01 89.38 83.96
$attachment "grenade1" "ValveBiped.Bip01_Pelvis" 1.78 -4.63 8.06 rotate 62.97 93.28 87.46
$attachment "grenade2" "ValveBiped.Bip01_Pelvis" 1.31 0.76 -9.54 rotate -84.58 -137.38 -39.32
$attachment "grenade3" "ValveBiped.Bip01_Pelvis" 0.63 3.41 8.63 rotate 66.17 -98.20 -100.52
$attachment "grenade4" "ValveBiped.Bip01_Pelvis" 1.30 -2.67 -9.10 rotate -62.12 106.22 74.68
$attachment "pistol" "ValveBiped.Bip01_R_Thigh" 9.00 -2.50 3.00  rotate 1.28 -0.21 -92.81
$attachment "primary" "ValveBiped.Bip01_Spine2" 5.26 8.84 -5.09 rotate -28.31 167.65 7.15
$attachment "primary_rifle" "ValveBiped.Bip01_Spine3" -4.00 -7.30 -1.77 rotate 2.64 179.10 170.54
$attachment "primary_sniper" "ValveBiped.Bip01_Spine3" -4.00 -7.30 -1.77 rotate 2.64 179.10 170.54
$attachment "primary_smg" "ValveBiped.Bip01_Spine3" -4.00 -7.30 -1.77 rotate 2.64 179.10 170.54
$attachment "primary_shotgun" "ValveBiped.Bip01_Spine2" 5.96 -7.77 -2.43 rotate 0.79 -179.38 165.48
$attachment "primary_mg" "ValveBiped.Bip01_Spine2" 5.96 -7.77 -2.43 rotate 0.79 -179.38 165.48
$attachment "eholster" "ValveBiped.Bip01_L_Thigh" 9.00 -1.50 -3.00 rotate 1.23 89.28 -88.44
$attachment "defusekit" "ValveBiped.Bip01_Pelvis" 1.06 -6.66 0.00 rotate 0.27 88.06 90.64
$attachment "lfoot" "ValveBiped.Bip01_L_Foot" -0.00 5.35 0.00 rotate 0.00 -0.00 0.00
$attachment "rfoot" "ValveBiped.Bip01_R_Foot" 0.00 5.35 0.00 rotate -0.00 -0.00 0.00
$attachment "muzzle_flash" "ValveBiped.Bip01_L_Hand" 0.00 0.00 0.00 rotate 0.00 0.00 -0.00
$attachment "weapon_bone" "ValveBiped.weapon_bone" 0.00 0.00 0.00 rotate -0.00 0.00 0.00
$attachment "knife" "ValveBiped.Bip01_L_Thigh" 7.90 4.80 -2.50 rotate -1.94 -60.00 -90.40
$attachment "facemask" "ValveBiped.Bip01_Head" 3.17 3.98 -0.00 rotate -0.00 74.00 90.00
$includemodel "player/ct_animations.mdl"
$includemodel "player/taunt_animations.mdl"
$surfaceprop "flesh"
$contents "solid"
$eyeposition -0.000 0.000 73.000

$sectionframes 30 29

$sequence "ragdoll" "ragdoll.smd" {
        fps 30
        activity "ACT_DIERAGDOLL" 1
}

$ikchain rhand ValveBiped.Bip01_R_Hand knee  0.753 0.658 -0.000
$ikchain lhand ValveBiped.Bip01_L_Hand knee  0.695 0.719 -0.000
$ikchain rfoot ValveBiped.Bip01_R_Foot knee  0.707 0.707 0.000
$ikchain lfoot ValveBiped.Bip01_L_Foot knee  0.707 0.707 0.000

$ikautoplaylock "rfoot" 1 0.1
$ikautoplaylock "lfoot" 1 0.1

$collisionjoints "phymodel.smd" {
        $mass 250
        $inertia 10
        $damping 0.01
        $rotdamping 4
        $rootbone "valvebiped.bip01_pelvis"
 
        $jointrotdamping "ValveBiped.Bip01_Pelvis" 10
 
        $jointmassbias "ValveBiped.Bip01_R_Thigh" 0.8
        $jointconstrain "ValveBiped.Bip01_R_Thigh" x limit -12 12 0
        $jointconstrain "ValveBiped.Bip01_R_Thigh" y limit -28 8 0
        $jointconstrain "ValveBiped.Bip01_R_Thigh" z limit -24 60 0
 
        $jointmassbias "ValveBiped.Bip01_R_Calf" 1.2
        $jointrotdamping "ValveBiped.Bip01_R_Calf" 3
        $jointconstrain "ValveBiped.Bip01_R_Calf" x limit 0 0 0
        $jointconstrain "ValveBiped.Bip01_R_Calf" y limit 0 0 0
        $jointconstrain "ValveBiped.Bip01_R_Calf" z limit -90 -15 0
 
        $jointmassbias "ValveBiped.Bip01_L_Thigh" 0.8
        $jointconstrain "ValveBiped.Bip01_L_Thigh" x limit -12 12 0
        $jointconstrain "ValveBiped.Bip01_L_Thigh" y limit -28 8 0
        $jointconstrain "ValveBiped.Bip01_L_Thigh" z limit -24 60 0
 
        $jointmassbias "ValveBiped.Bip01_L_Calf" 1.2
        $jointrotdamping "ValveBiped.Bip01_L_Calf" 3
        $jointconstrain "ValveBiped.Bip01_L_Calf" x limit 0 0 0
        $jointconstrain "ValveBiped.Bip01_L_Calf" y limit 0 0 0
        $jointconstrain "ValveBiped.Bip01_L_Calf" z limit -90 -15 0
 
        $jointmassbias "ValveBiped.Bip01_L_Foot" 0.75
        $jointrotdamping "ValveBiped.Bip01_L_Foot" 7
        $jointconstrain "ValveBiped.Bip01_L_Foot" x limit -10 22 0
        $jointconstrain "ValveBiped.Bip01_L_Foot" y limit -15 15 0
        $jointconstrain "ValveBiped.Bip01_L_Foot" z limit -17 24 0
 
        $jointrotdamping "ValveBiped.Bip01_Spine1" 18
        $jointconstrain "ValveBiped.Bip01_Spine1" x limit -20 20 0
        $jointconstrain "ValveBiped.Bip01_Spine1" y limit -10 10 0
        $jointconstrain "ValveBiped.Bip01_Spine1" z limit -15 30 0
 
        $jointmassbias "ValveBiped.Bip01_Spine2" 1.6
        $jointrotdamping "ValveBiped.Bip01_Spine2" 12
        $jointconstrain "ValveBiped.Bip01_Spine2" x limit -30 30 0
        $jointconstrain "ValveBiped.Bip01_Spine2" y limit -16 16 0
        $jointconstrain "ValveBiped.Bip01_Spine2" z limit -15 20 0
 
        $jointmassbias "ValveBiped.Bip01_R_UpperArm" 0.8
        $jointrotdamping "ValveBiped.Bip01_R_UpperArm" 16
        $jointconstrain "ValveBiped.Bip01_R_UpperArm" x limit -50 40 0
        $jointconstrain "ValveBiped.Bip01_R_UpperArm" y limit -26 26 0
        $jointconstrain "ValveBiped.Bip01_R_UpperArm" z limit -45 15 0
 
        $jointmassbias "ValveBiped.Bip01_R_Forearm" 1.8
        $jointconstrain "ValveBiped.Bip01_R_Forearm" x limit -45 45 0
        $jointconstrain "ValveBiped.Bip01_R_Forearm" y limit 0 0 0
        $jointconstrain "ValveBiped.Bip01_R_Forearm" z limit -120 -45 0
 
        $jointmassbias "ValveBiped.Bip01_L_UpperArm" 0.8
        $jointrotdamping "ValveBiped.Bip01_L_UpperArm" 16
        $jointconstrain "ValveBiped.Bip01_L_UpperArm" x limit -40 50 0
        $jointconstrain "ValveBiped.Bip01_L_UpperArm" y limit -26 26 0
        $jointconstrain "ValveBiped.Bip01_L_UpperArm" z limit -40 15 0
 
        $jointmassbias "ValveBiped.Bip01_L_Forearm" 1.8
        $jointconstrain "ValveBiped.Bip01_L_Forearm" x limit -45 45 0
        $jointconstrain "ValveBiped.Bip01_L_Forearm" y limit 0 0 0
        $jointconstrain "ValveBiped.Bip01_L_Forearm" z limit -120 -45 0
 
        $jointmassbias "ValveBiped.Bip01_L_Hand" 0.6
        $jointrotdamping "ValveBiped.Bip01_L_Hand" 8
        $jointconstrain "ValveBiped.Bip01_L_Hand" x limit -30 37 0
        $jointconstrain "ValveBiped.Bip01_L_Hand" y limit 0 0 0
        $jointconstrain "ValveBiped.Bip01_L_Hand" z limit -20 35 0
 
        $jointmassbias "ValveBiped.Bip01_R_Hand" 0.6
        $jointrotdamping "ValveBiped.Bip01_R_Hand" 8
        $jointconstrain "ValveBiped.Bip01_R_Hand" x limit -37 30 0
        $jointconstrain "ValveBiped.Bip01_R_Hand" y limit 0 0 0
        $jointconstrain "ValveBiped.Bip01_R_Hand" z limit -35 20 0
 
        $jointmassbias "ValveBiped.Bip01_Head" 1.5
        $jointrotdamping "ValveBiped.Bip01_Head" 10
        $jointconstrain "ValveBiped.Bip01_Head" x limit -45 45 0
        $jointconstrain "ValveBiped.Bip01_Head" y limit -30 30 0
        $jointconstrain "ValveBiped.Bip01_Head" z limit -40 20 0
 
        $jointmassbias "ValveBiped.Bip01_R_Foot" 0.75
        $jointrotdamping "ValveBiped.Bip01_R_Foot" 7
        $jointconstrain "ValveBiped.Bip01_R_Foot" x limit -10 22 0
        $jointconstrain "ValveBiped.Bip01_R_Foot" y limit -19 25 0
        $jointconstrain "ValveBiped.Bip01_R_Foot" z limit -17 24 0
}


$bonemerge "ValveBiped.Bip01_Pelvis"
$bonemerge "ValveBiped.Bip01_Spine"
$bonemerge "ValveBiped.Bip01_Spine1"
$bonemerge "ValveBiped.Bip01_Spine2"
$bonemerge "ValveBiped.Bip01_Spine3"
$bonemerge "ValveBiped.Bip01_Neck"
$bonemerge "ValveBiped.Bip01_L_Clavicle"
$bonemerge "ValveBiped.Bip01_L_UpperArm"
$bonemerge "ValveBiped.Bip01_L_Forearm"
$bonemerge "ValveBiped.Bip01_L_Hand"
$bonemerge "ValveBiped.Bip01_R_Clavicle"
$bonemerge "ValveBiped.Bip01_R_UpperArm"
$bonemerge "ValveBiped.Bip01_R_Forearm"
$bonemerge "ValveBiped.Bip01_R_Hand"
$bonemerge "ValveBiped.weapon_bone"
$bonemerge "ValveBiped.weapon_bone_Slide"
$bonemerge "ValveBiped.weapon_bone_Clip"
$bonemerge "ValveBiped.weapon_bone_Clip2"
$bonemerge "ValveBiped.silencer"

Many of the items in this .qc including hotboxes and attachments have been modified to suit the model which was generated by it, so you should not copy those sections exactly, but you can use this as a reference to determine if some of the commands it has are missing from your model's .qc file. This wiki also has a list of QC Commands with descriptions of each command. Improper .qc files can cause glitches so care must be taken to ensure that your .qc has no errors in it. A simple syntax error in the attachments section for example can break CS:GO's freezecam when you die, sending the camera to the map origin instead of near your body.