Skeleton
A model's Skeleton is a hierarchy of one or more bones. It is analogous the real skeletons inside of humans and animals, providing models with a framework for posing, animation, and physics interactions.
Model skeletons enable artists and animators to design and animate characters in a way that is both familiar and realistic. In the same way that our skin is attached to our bones and bends & stretches as our bones move, the vertex geometry of a character is attached to its skeleton and bends & stretches as its bones move. The process of associating each vertex to one or more bones in the skeleton is known as skinning, which controls how the model's visible surfaces deform when its bones are moved.
Sometimes, a model's skeleton is referred to and/or acts as its rig, blurring the line between the actual skeleton and a separate animation rig that might exist on top of it.
Hierarchy Basics
In Source, every model has a hidden, implicit root bone, which positions and orients the model relative to its Model Entity. This special bone is created by studiomdl during MDL compilation and serves as the boundary between the model's internal structure and its location in the world. The model is not aware of its implicit root bone; ergo, this bone cannot be animated by a model's $sequences.
All other bone chains - those defined in the model's SMD/DMX file(s) or with $definebone
in its QC - become children of the implicit root bone. These user-defined bones constitute the model's actual skeleton. Since a model cannot animate its implicit root bone, it is common practice to create a user-defined "root' bone in the character's skeleton, which actually becomes an immediate child of the implicit root bone. In typical Valve biped skeletons, this would be ValveBiped.Bip01_Pelvis
. If the model's SMD/DMX contains no bones, then the output MDL's skeleton will only have the implicit root bone. This is often the case for static props, such as boxes or tables.
Bone count limit
Each Source engine branch and game specifies a limit on the number of bones that a model can have. This limit includes the implicit root bone, effectively limiting the number of user-defined bones to MAXSTUDIOBONES - 1
.
- Source 2013
MAXSTUDIOBONES = 128
- Garry's Mod:
MAXSTUDIOBONES = 256
- Garry's Mod is based on , but has several key modifications including overall increased engine limits
- Left 4 Dead and Left 4 Dead 2:
MAXSTUDIOBONES = 128
- Source Filmmaker:
MAXSTUDIOBONES = 256
- Counter-Strike: Global Offensive:
MAXSTUDIOBONES = 256
Skeleton Articulation
Articulation is the process by which is a skeleton's bones move, pulling the model's skinned meshes along with them.
Rigid skeletons
Models which only possess the implicit root bone are said to be rigid "skeletons". There is only one bone; therefore, the entire model follows that single bone. This is most appropriate for rigid objects that are constructed of solid materials, like wood or metal.
Jointed skeletons
The typical parent-child bone pair in a skeleton forms a joint that can bend. For example, consider a human elbow. There is no "elbow" bone; rather, the "elbow" is the joint that exists between the humerus bone and the ulna & radius bones. Most characters have skeletons that are based on this ball-and-socket relationship between child-parent bone pairs. The bending (and sometimes stretching) of joints provides the fundamental backbone (no pun intended) of character animation and ragdoll physics.
Jointed skeletons can be as simple as the handle on a door, as complex as an entire human body, or somewhere in between. Additionally, since skeletal animation is by far the cheapest of all deformation techniques, it is commonplace to approximate complex motion, such as that of cloth, with specially-designed skeletons instead of simulating prohibitively expensive accurate physics. The Half-Life 2 mattress ragdoll is a prime example of this.
Movement hierarchy
Source's movement hierarchy system is used to attach different entities to one another, but the same logic can be used to understand how Skeletal bones are linked together.
By default, each object constrained in a movement hierarchy inherits its position and orientation from the position and orientation of its parent's attachment point. The $attachment point is part of the parent's geometry, but has its own offset properties, i.e. its own position and orientation relative to its Origin's position and orientation. When the child-object attaches, its Origin and Angles are aligned to the position and orientation defined by the $attachment point.
If the parent-object moves the attached child-object moves (parallel) with it. If the parent object rotates (about its own origin), the child-object will orbit the parent's origin.
- WorldOrigin [worldspawn]
- (Vehicle) WorldPosition : all entities' position and orientation are relative to WorldOrigin.
- (Seat) Parent Entity Attachment point is offset from its WorldPosition
- (NPC) Child Entity Model offset [$origin]
- (Pelvis) Skeleton Root_bone_end offset
- (Chest) Joint_bone1_end offset
- (Torch) Attachment point offset
- (Torchbeam) Sprite
- (Arm) Joint_bone2_end offset
- (Sleeve) Mesh vertex offset
- (Muscle) Physbox vertex offset
- (Hand) Attachment point offset
- (Shotgun) Sub-model Root_bone_end offset
- (Muzzleflash) Sprite
- (Shotgun) Sub-model Root_bone_end offset
- (Torch) Attachment point offset
- (Chest) Joint_bone1_end offset
- (Pelvis) Skeleton Root_bone_end offset
- (NPC) Child Entity Model offset [$origin]
- (Seat) Parent Entity Attachment point is offset from its WorldPosition
- (Vehicle) WorldPosition : all entities' position and orientation are relative to WorldOrigin.
- Entity : the entity's position and orientation in the World are "inherited" by the
- Model Origin : is the reference point for ... offset with $origin ...?
- rootbone : is any bone "parented" (directly) to the Origin. Usually only one root bone per model... offset with $root
- bone_joint : where this bone connects to its parentbone
- bone_name (See also SMD#nodes)
- bone_attach : Has position and orientation properties, = the "origin" for this bone's children :
- mesh : Render model vertices are enveloped to one or (weightmapped to) more than one bone.
- physbox : Collision model vertices are enveloped to one bone.
- attachment : Hooks where another entity's model (e.g. w_weapons) may attach to this model.
- childbone : the next named bone in the skeleton hierarchy
- rootbone : is any bone "parented" (directly) to the Origin. Usually only one root bone per model... offset with $root
- Model Origin : is the reference point for ... offset with $origin ...?
- nb sub-models include "rigged" weapons (w_weapon, $bonemerge) and movement hierarchy children ...
- LOD skeleton : bonetreecollapse, replacebone,
- IK chains
Joints, bones & attachments
- Bones & Joints
- If we think of each named bone as having a ball-end and a socket-end, the ball-end of the bone is called its joint - and is always connected to this bone's parentbone. When this bone moves, it pivots about its joint, so the joint could also be called the bone's local Origin. The socket-end of the bone, which orbits at a fixed distance around the joint, seems to be called the bone. Any childbones, attachments, and/or vertex envelopes "parented" to this bone use the bone (rather than the joint) location and orientation as their origin position. Note that a childbone is "parented" to a parentbone, not a joint.
- Bone_names
- Joints are referred to by their bone_name, not their parentbone_name; e.g. ankle = foot_bone, knee = shin_bone, etc. Sometimes bones are named after the joint, e.g. foot = ankle_bone, shin = knee_bone. However this can cause confusion: something attached to the knee_bone will be offset from the ankle joint rather than the knee joint.
- Difference between Attachments and Joints
- A bone is linked to its parentbone via a joint. The joint properties (angles etc.) are defined by the bone, not the parent; the child attaches itself to the parent. By contrast, an attachment point is part of the parent's skeleton, and when it connects to an object (e.g. a weapon), the attachment point defines the (rigid) joint properties (angles, etc.); the parent attaches to the child. An attachment point should really be called a constraint. This is why w_weapons are rigged with $bonemerge rather than attachment points ... ?
A skeleton is comprised of "chains" of bones, joints, effectors, and a root. Some good things to know:
- Root: Where your skeleton starts. Moving the root moves the skeleton as one unit. Apex of the skeletal movement hierarchy.
- Joint: Joins two bones, and is where bending and IK occur.
- Bone: This is the principle object in the skeleton and is what the mesh will be attached to.
- Effector: These move a bone system around. The end point of a bone chain.
Root
Root or rootbone is a special kind of bone. It is parented to the EntityOrigin, and therefore aligns all of the skelton's geometry to the Entity's World position and orientation.
A "default" skeleton has nothing but a rootbone, with zero length, all vertices enveloped to it are aligned to the Origin.
// e.g.: a "default" SMD skeleton : version 1 nodes 0 "root_bone" -1 end skeleton time 0 0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 end
Rigging
- Todo: clarify:rigged, rigging, rig ... if "rig" = the whole skinned, enveloped, jointed, etc. model, ready and waiting for animations to be applied, then "rigged" means animation-ready or complete, and "rigging" is the process of attaching & tweaking the relationships (uvmap, weightmap, jointconstraints, etc.) between all the elements. On the other hand, "rigging" might refer specifically to configuring all the bone properties for a given skeleton - jointconstraints, attachments, IKrules, etc. - so "rig" = a NotRigid skeleton, and "rigged" still means "animation-ready".
- Todo: clarify:deformer = a bone, deforms the mesh, so the "deformation" would be applied to the mesh & skin, ... however if deformation = a bone movement, either animation or (ragdoll) vphysics applied to the bone, then bone = "deformee" !
- $weightlist defines the skeleton's bone weights, used for "cross-fading" when blend animations are combined.
- $jointconstraints are local vphysics forces used only for ragdolls. They have no effect in sequence animation.
- $ikchains are
- Sub-models (e.g. w_weapons) and Sub-meshes (e.g. optional clothing) use $bonemerges to align with their parent model, whereas entities are parented to the model's $attachment point.
- See Rigging a weapon model and Attachments for attaching detachable sub-models to the Skeleton.
- See Bodygroups for attaching additional sub-meshes to the Skeleton.
- See Enveloping and Weightmapping for attaching a deformable Mesh to the skeleton.
- See Skinning and UV mapping for attaching a Skin to the Mesh.
- See Enveloping and Weightmapping for attaching a deformable Mesh to the skeleton.
Surface geometry
An object's surface geometry (also known as its envelope or body or hull or skin or mesh or vertex geometry or model geometry) defines the exact shape and size of the spatial volumes that are each completely enclosed by a continuous surface.
- Two main types of surface geometry with distinctive properties:
- Rendering geometry ... at the end of the day only the Skin texels are rendered, but the skin hangs on a 3D mesh which is deformed by skeletal animation.
- Collision geometry ... is invisible in game but defines this object's Solidity to other objects.
- bbox (bounding box, surrounding bounds, == cbox?, collision hull, movement hull, player hull, npc hull)
- hbox (hit box) used for bullet hit tests (and local damage modifiers ... crowbar, crossbow, phys-object hit locations?)
- physbox (physmodel, collisionmodel, ragdoll) is used only for vphysics reactions, including ragdoll motion/animation.
In Source, Surface Geometry data is always defined as a system of Vertices in 3D space.
- Vertex Location data : (X Y Z) coordintates relative to its parent Origin within the movement hierarchy.
- Vertex Orientation data : (vertex normalvector) defines its Orientation relative to its adjacent vertices ? ... see Vertex smoothing.
- Vertex Skin data (UV) coordinates and name of skin.vmt ... see UV map (only used on Rendered surfaces)
- Vertex Weight data : (float value defaulting to 1.0) ... : see Weightmap (only used on Deformable Rendered surfaces)
- Todo: a rectangular box is defined by a pair of ("min" and "max") coordinates relative to the origin which represent opposing corners; the other 6 vertex coords are deduced as necessary. A non-rectangular polygonal mesh is a network of triangles connected by their vertices. Because GPU pipelines are optimised to process triangles, rectangular (brush) surfaces are split into two triangles for Rendering.
Non-surface geometry
- Silhouette geometry (outline or profile)... non-collision raytrace tests; i.e. Shadows & LOS. Usually derived automatically from Render model at runtime, but can use other geometry for greater efficiency. ($shadowlod, etc.?) (See also sprite)
- Skeletal geometry ... kinematic movement hierarchies ... attachment is offset from parent's origin & angles. (Rigid / NotRigid)
- Spatial geometry ... Some Entity Properties use non-vertex geometry:
- sphere : e.g. light - radius (Range or Falloff) relative to the EntityOrigin.
- cone : e.g. light_spot - direction (angles), cone arc (FOV), distance (Range or Falloff) relative to the EntityOrigin.
- NPC viewcone (FOV & default distance = 2048 units) relative to the EntityOrigin.
- PVS : potentially visible set (visleafs) relative to the Entity's current visleaf.
- PAS : potentially audible set (visleafs?) relative to the Entity's current visleaf.
Vertex Editors
- Brush Vertices : Hammer Vertex Tool
- Mesh Vertices : (SMD#triangles), model editor
- Skin Vertices : see UV map
- Hull Vertices : C++ NPC Hull, Player Hull
- Hitbox Vertices : QC $hbox
- Bounding box Vertices : QC $bbox
- Sprite Verticies : env_sprite properties (sprites may use trickery and 2D graphics, but they do represent 3D objects.)