This article's documentation is for anything that uses the Source engine. Click here for more information.

$ikchain

From Valve Developer Community
Jump to navigation Jump to search
All three of the Hunter's feet touch the ground thanks to IK.

$ikchain is a QC command available in all Source Source games. Source's inverse kinematics system allows characters' feet to connect accurately with uneven ground surfaces.

IK calculates the position of a middle_joint based on fixed distances from the positions of a top_joint and an end_joint. A good example is an ankle-knee-hip IK chain, where the ankle (end_joint) is positioned relative to the ground, the hip (top_joint) is locked in place, and the knee (middle_joint) is moved to a position such that the shin and thigh bones maintain their original length. Depending in the specific ikrule used, when the end_joint is moved into the needed position, the top_joint's position is assumed to be fixed, and the IK system positions the middle_joint so that the distances between the joints (ie the bone lengths) remain constant.

Tip.pngTip:A joint is where a bone attaches to its parent bone. All bones (except the root bone) must have only one joint, so the "bonename" is also used to specify its joint.
Tip.pngTip:HLMV can preview IK using the "Enable IK" option in the "Render" tab.
Icon-Bug.pngBug:HLMV will not display IK rules from sequences with blendlayer.  [todo tested in?]

Syntax

$ikchain (name) (end_bone) [(axis) (value)] [height (units)] [pad (units)] [floor (units)] [knee (X) (Y) (Z)] [center (X) (Y) (Z)]
  • name : defines the "ikchainname" for this IK chain.
  • end_bone : The three bones affected by this IK chain are defined by specifying the bone farthest down in the chain. The next two bones are automatically found by climbing the Bone hierarchy. An IK chain may only have three bones.
  • axis should be one of these X,Y,Z,XR,YR,ZR,LX,LY,LZ,LXR,LYR,LZR,LM,LQ. value is a float.
    Todo: what does it do?
  • height :
    Todo: ?
  • pad :
    Todo: ?
  • floor :
    Todo: ?
  • knee : Doesn't actually mean it's a knee. It could be a hip, ankle, toes...
    Todo: confirm: This vector specifies the direction of the joint
  • center :
    Todo: confirm: vector for center
  • QC example :
$ikchain rhand ValveBiped.Bip01_R_Hand knee  0.707 0.707 0.000
$ikchain lhand ValveBiped.Bip01_L_Hand Z 0
$ikchain rfoot ValveBiped.Bip01_R_Foot height 10 floor 5
$ikchain lfoot ValveBiped.Bip01_L_Foot pad 5 center 0 1 0

$ikchain rules

iklock

iklock (ikchainname) (lock_position) (maintain local rotation)

iklock keeps track of the position/orientation of the specific chain before the sequence is applied, then after it’s applied, does a local IK rule to move it back into position/orientation. This is used to keep the specified IK chains from moving during this sequence, which can be useful when applying pelvis or body motion to a model but you want the hands or feet to remain in place.

  • ikchainname : The name of the $ikchain that the rule will apply to.
  • lock_position : the weight of the lock is a floating point value from 0.0 to 1.0.
  • maintain local rotation : the weight of rotation lock is a floating point value from 0.0 to 1.0.
Note.pngNote:The value for rotation is backwards from the position. To lock both of them, set the lock weights to "1 0"; to let both of them freely move, set them to "0 1" (which is pointless, don’t do the iklock in this case, but you get the idea).

ikrule

ikrule (ikchainname) [type] [options...]
  • ikchainname : The name of the $ikchain that the rule will apply to.
  • type : See "ikrule types" for valid types.
  • options : See "ikrule options" for valid options.

ikrule types

footstep <slot #>
Adds an IK rule where a subsequent body part (such as a foot) needs to be moved relative to the ground.
touch <bone name>
Adds an IK rule where a bone needs to be positioned relative to another part of the body. This is useful when the hand needs to touch some other part of the model, such as the face, hip, other hand, etc., and that other body part may be not in the original animated location due to additional animation layers, bone controllers, or other IK rules.
Tip.pngTip:Specify a bonename of "" to get the chain to move relative to the models origin instead of an animated bone.
release
Releases the IK rules of animations below a delta. This is useful for reloading animations that use their own IK rules applied over a base animation.
unlatch
[Todo]
attachment <attachment name>
Sets the IK goal to the specified external attachment. Rather than targeting a specific entity, the client code will search for an entity with this attachment near the chain's position and stick to it.
Note.pngNote:The code looks for an entity within 64 units and then requires the attachment to be within the units given in the radius option.
Tip.pngTip:Half-Life 2 Used to move NPCs' hands to the handles on func_tank turret models.

ikrule options

range <start> <peak> <tail> <end>
Sets the fade-in, hold, and fade-out frame numbers for the ikrule. A period . can be placed in any of the parameters to leave the default value.
height <units>
Used by footstep rules, specifies how high to start the search above the desired ground height. The default is the height of the ikchain.
floor <units>
Used by footstep rules, specifies where the actual ground is ground height. The default is the floor of the ikchain.
radius <units>
Used by footstep rules, specifies how big the ground contact check should be. The default is the radius of the ikchain.
pad <units>
same as radius but divides units by 2. radius = pad / 2;
contact <frame>
Used by footstep rules, specifies what frame to use when checking for ground position.
usesource
Use the original animation source to determine the IK goals. This is use useful if the current sequence is a composite that is different from the source animation and you want to get the movement back to its original form.
usesequence
Run all the sequence rules, including blendlayer and addlayer rules to determine the IK goals.
fakeorigin <x> <y> <z>
Sets a fake origin for the IK rule detached from any previously specified bones.
fakerotation <pitch> <yaw> <roll>
Sets a fake rotation for the IK rule detached from any previously specified bones.

Example

$sequence foo {
  ikrule lfoot footstep 0 range  4 10 19 25
  ikrule rfoot footstep 1 range 18 26 3 10
  iklock rfoot 1 0 iklock lfoot 1 0
}

Enabling IK in your mod

Unless your mod has been compiled with HL2_CLIENT_DLL and HL2_DLL, IK code is excluded from:

  • CPlayerMove::StartCommand (server)
  • CInput::CreateMove (client)

You can remove the surrounding #ifdef statements to enable it (or compile as HL2, but that may have unforeseen consequences).

IK in multiplayer

Ken Birdwell, who wrote the IK system, has said:

It's currently only enabled for HL2, and only for npcs. We've not done it for multiplayer.

As it's currently written, the server doesn't do IK, only the clients. The main issue is that the client can't do the drop all on its own, the server needs to do the adjustment so that it can do accurate collision detection for bullets. In order for the model to drop enough below the AABB for the feet to touch the ground, there's backchannel in the client->server networking for when the IK fails. All it really is is if the npc is too high, it tells the server how much it needs to drop so that the feet will hit the ground. See CBaseAnimating::SetIKGroundContactInfo() and related code. The funky cycling you're seeing is the IK enabling and disabling itself on the client after failure.

For players, you can probably go ahead and do it all on the server, just be prepared to eat the extra per-frame animation cost. Normally animations are only calculated if a traceline intersects the AABB, or on the client if they're in the FOV, which is usally only a tiny fraction of the possible set. For NPC's, on the server their animation is only calculated to about 10hz, way too slow to catch them running up stairs. In any case, to get it to always work you'll need to calculate every player every frame to see how much they'll need to drop. On top of that, you'll need to synchronize the feet on the client and server, something we've never done. All of that might not be a issue for your game, but we couldn't afford it during HL2.
— Ken Birdwell Valve, hlcoders mailing list