Player Models
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
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
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.
Compiling
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.