Skip to content

[OUTDATED] SKM, skeletal models

Victor Luchits edited this page Nov 7, 2016 · 1 revision

SKM is a skeletal model format designed for QFusion engine integration. A SKM model is composed of two archives, the model.skm and the model.skp. The .skm archive contains the model information and bones references, while the .skp archive contains the frames bones poses.

SKM models can be composed of a maximun of 32 different meshes, with each mesh being able of using a different texture name. When using QFusion, it's also possible to create .skin files, matching Quake 3 skinfile format, for them, so the SKM models are capable of using custom textures on all their meshes.

The SKM model, or the .skp file if you prefer, can contain up to a maximum of 65536 frames, each frame containing up to a maximum of 256 bone poses, since 256 is the maximum number of bones of SKM models. Another limit is that animation names can't be superior to 64 characters lenght. Maximum vertex count is also 65536, which means a limit of 21845 triangles. Obviously that's a triangle count absollutely not recommended to use.

The .skp files contain frame based skeleton poses, to transform the model meshes by them. This skp files can be used with different .skm files, as long as the different skm models were originally binded (or skinned, depending on your favourite modelling tool) to exactly the same skeleton. This means, a skeleton with the same bones, having the same bone names.

SKM models actually don't contain any collision information.

SKM, compiling a simple model

SKM models are compiled from SMD models using the command line program of name skmodel. The next paragraphs explain how a SMD model is converted into any generic (not player model) SKM.

SMD is the ascii model format used by Half Life and Half Life 2 as source to compile their ingame MDL models. There are 2 types of SMD models: the reference SMD and the animation SMD. The reference model contains the model meshes and skeleton information in the bind pose, each other smd model will contain a single animation. A group composed of the reference SMD + as many animation SMDs as wanted is parsed into the skmodel converter, so it compiles a unified SKM (the same process as it's done for HL/HL2 models).

Since SMD models are the official Half Life 2 source model format there are many exporters available in the net. It's important to know if the exporter you are going to use was made for HL or HL2, though. Both HL and HL2 smd exporters will work, but smd exporters created for Half Life (1) only export a single bone influence per vertex, while the exporters for Half Life 2 write several influences, and SKM is capable of making use of those multiple influences. This doesn't only help achieving a smoother animation, but also makes skin binding much easier. For more information about SMDs, and how to export them from each different 3D modelling program, just google for Half Life 2 and SMD.

Using skmodel

skmodel is a command line tool. It requires to receive the name of a text file containing the parsing commands. It's run like this:

skmodel model_definition.txt

The model definition text file can contain the following commands:

outputdir <path> The output path. .\ for the program folder

model <name> Name of the .skm and .skin files to be generated

origin <value> <value> <value> Offset the model origin

rotatepicth <value> rotates along the z axis by the given angle

rotateyaw <value> rotates along the z axis by the given angle

rotateroll <value> rotates along the z axis by the given angle

export <name> Name of the .skp file to be generated

cleanbones Removes bones without any vertex link from the final model

scale <value> Scale up or down the model

scene <name.smd> SMD models. Once for the reference model, and repeated for each animation. There are as many 'scene' commands as SMD sources used.

Note: Since the SMD models don't contain meshes names, skmodel will generate the meshes names by their numbers in the meshes array. In short, meshes names in the skin file will be a number.

SKM, creating player models for QFusion's Skelmod

Skelmod is a QFusion mod which adds animation blending for SKM player models. Animation blending is made by the game code, and it's, in short, the code selecting into what bones it will use what animation. For this reason, it requires information of what animations to play, and what bones are part of each group inside the skeleton. This information is provided by the animation.cfg.

Skelmod accepts up to 3 animations for the player model, but we are, by now, only using 2, upper and lower, since head animation is always at frame 0. For defining what bone belongs to each group, Skelmod uses rootAnims, this is just a name as any other, and it refers to a bone which will mark the starting point in the skeleton tree for an animation to be played. As example, marking as rootanim bone a bone in the elbow of a model will make play that animation at the elbow and all the following bones in the arm (hand, fingers...). There are currently 3 animation-channels to be blended: "lower", "upper" and "head". The bones not belong to any rootanim group will be assigned to "lower" group.

This is the list of available commands to be used in the animation.cfg:

rootanim <animation-channel> <bone name> Sets the animation to the played in this bone and its childs in the skeleton tree.

sex <m or f> Sets player model sex.

fps <value> Sets model FPS ratio. Note, ratio is the same for all the animations.

rotationbone <type> <bone name> Defines that bone as a rotator. There are 2 possible types: upper and head. You can set as many bones as you want as rotators of the same type, the rotation angle will be divided by all them.

tagmask <bone name> <tag name> <offsetForward> <offsetRight> <offsetUp> Defines a tag mask for that bone, so, the bone will be used as the tag when looking for a tag of name <tag name>. This is done so different models, with different skeletons can use the same tag name.

isnumframes Makes the third value in the animation definition to be read as animation frames count, instead of the frame number where the animation finishes.

islastframe The opposite as isnumframes. It's used by default.

offset Makes the first value in the animation lines have offset in it's first value (as Q3 animation configs). By default the offset isn't applied, and every animation is defined by it's real frame value in the model.

alljumps Makes use of the different jump animations to simulate bunny hopping.

And finally, each animation is defined by 4 values in a line, meaning this by default:

<first frame> <last frame> <looping frames> <fps>

Note: looping frames don't have to be the same lenght of the animation extension.

The list of animations which are defined in Skelmod

BOTH_DEATH1	Death animation	
BOTH_DEAD1	corpse on the ground
BOTH_DEATH2
BOTH_DEAD2
BOTH_DEATH3
BOTH_DEAD3

LEGS_STAND_IDLE
LEGS_WALK_FORWARD
LEGS_WALK_BACK
LEGS_WALK_LEFT
LEGS_WALK_RIGHT

LEGS_RUN_FORWARD
LEGS_RUN_BACK
LEGS_RUN_LEFT
LEGS_RUN_RIGHT

LEGS_JUMP_LEG1 (left leg)
LEGS_JUMP_LEG2
LEGS_JUMP_NEUTRAL
LEGS_LAND

LEGS_CROUCH_IDLE
LEGS_CROUCH_WALK

LEGS_SWIM_FORWARD
LEGS_SWIM_NEUTRAL

LEGS_WALLJUMP
LEGS_WALLJUMP_LEFT
LEGS_WALLJUMP_RIGHT
LEGS_WALLJUMP_BACK

LEGS_DASH	
LEGS_DASH_LEFT
LEGS_DASH_RIGHT
LEGS_DASH_BACK

TORSO_HOLD_BLADE	GB
TORSO_HOLD_PISTOL	LG
TORSO_HOLD_LIGHTGUN	PG, RG
TORSO_HOLD_HEAVYGUN	RL, GL
TORSO_HOLD_AIMGUN	EB

TORSO_SHOOT_BLADE	weak GB
TORSO_SHOOT_PISTOL	LG, strong GB
TORSO_SHOOT_LIGHTGUN	PG, RG
TORSO_SHOOT_HEAVYGUN	RL, GL
TORSO_SHOOT_AIMGUN	EB

TORSO_WEAPON_SWITCHOUT
TORSO_WEAPON_SWITCHIN

TORSO_DROPHOLD	Unused
TORSO_DROP

TORSO_SWIM

TORSO_PAIN1
TORSO_PAIN2
TORSO_PAIN3

Example of animation.cfg file

//==============================================================
//
// Example of animation.cfg of a Warsow model
//
//==============================================================

sex f

rootanim upper "Bip01 Spine1"
rotationbone upper "Bip01 Spine1"
rotationbone upper "Bip01 Spine2"
rotationbone upper "Bip01 Neck"
rotationbone head "Bip01 Head"

tagmask "Bip01 R Hand" "tag_weapon" -2 0 0 // numbers mean offset forward, right & up
tagmask "Bip01 Spine2" "tag_flag1" 0 -6 0
tagmask "bip01 head" "tag_head" 28 0 0

// first frame, last frame, looping frames, fps

// frames 1 to 39 are reserved for the ui animation

40	58	0	24	// BOTH_DEATH1	Death animation	
58	58	0	24	// BOTH_DEAD1	corpse on the ground
59	83	0	24	// BOTH_DEATH2
83	83	0	24	// BOTH_DEAD2
84	107	0	24	// BOTH_DEATH3
107	107	0	24	// BOTH_DEAD3

160	200	40	24	// LEGS_STAND_IDLE
267	291	24	24	// LEGS_WALK_FORWARD
292	316	24	24	// LEGS_WALK_BACK
317	341	24	24	// LEGS_WALK_LEFT
342	366	24	24	// LEGS_WALK_RIGHT

367	383	16	24	// LEGS_RUN_FORWARD
384	400	16	24	// LEGS_RUN_BACK
401	413	12	24	// LEGS_RUN_LEFT
414	426	12	24	// LEGS_RUN_RIGHT

465	484	0	24	// LEGS_JUMP_LEG1 (left leg)
514	533	0	24	// LEGS_JUMP_LEG2
489	509	0	24	// LEGS_JUMP_NEUTRAL
485	488	1	24	// LEGS_LAND

157	159	1	24	// LEGS_CROUCH_IDLE
242	266	24	24	// LEGS_CROUCH_WALK

427	445	18	24	// LEGS_SWIM_FORWARD
446	464	18	24	// LEGS_SWIM_NEUTRAL

605	622	0 	24	// LEGS_WALLJUMP
643	658	0	24	// LEGS_WALLJUMP_LEFT
659	674	0	24	// LEGS_WALLJUMP_RIGHT
623	642	0	24	// LEGS_WALLJUMP_BACK

675	690	0	24	// LEGS_DASH	
711	726	0	24	// LEGS_DASH_LEFT
727	742	0	24	// LEGS_DASH_RIGHT
695	710	0	24	// LEGS_DASH_BACK

160	162	1	24	// TORSO_HOLD_BLADE	GB
160	162	1	24	// TORSO_HOLD_PISTOL	LG
160	162	1	24	// TORSO_HOLD_LIGHTGUN	PG, RG
160	162	1	24	// TORSO_HOLD_HEAVYGUN	RL, GL
160	162	1	24	// TORSO_HOLD_AIMGUN	EB

138	156	0	24	// TORSO_SHOOT_BLADE	weak GB
123	137	0	24	// TORSO_SHOOT_PISTOL	LG, strong GB
123	137	0	24	// TORSO_SHOOT_LIGHTGUN	PG, RG
123	137	0	24	// TORSO_SHOOT_HEAVYGUN	RL, GL
123	137	0	24	// TORSO_SHOOT_AIMGUN	EB

108	110	1	24	// TORSO_WEAPON_SWITCHOUT
111	122	0	24	// TORSO_WEAPON_SWITCHIN

565	605	40	24	// TORSO_DROPHOLD	Unused
538	554	0	24	// TORSO_DROP

427	445	18	24	// TORSO_SWIM

555	575	0	24	// TORSO_PAIN1
576	588	0	24	// TORSO_PAIN2
589	604	0	24	// TORSO_PAIN3
Clone this wiki locally