OpenKh

This is a centralized place for the documentation and other discoveries about the internal working of Kingdom Hearts games.

View on GitHub

Kingdom Hearts II - Interpolated motion

This documentation is based on the hard work of Kenjiuno’s MSET docs, data from decompilations and animation research.

Interpolated motions are a sub-category of a motion file, found inside ANB files.

The purpose of this file is to animate a 3D model. Models are animated using Straight Ahead Animation. That means it uses an initial pose and then it applies Transformations (Scale, rotate, translate) to specific bones at specific times to make the animation.

Since the animation is interpolated, the game engine can seamlessly change the running animation to another animation by interpolating the movement, creating fluidity. Also it is possible to scale the animation at n FPS. Those two advantages are not present in RAW animations.

Also, a motion file can define additional bones, in addition to the bones from the model: those are used by the Inverse Kinematic. For the animation P_EX100\A000 (battle idle), those IK bones are parents of the feet’s bones. That is used to both animate the legs movement in a realistic way and to move the leg up when it performs a collision to the stairs, for instance.

Structure

The file consists of the following structures:

Motion header

This is a continuation of the motion header. The very top header is exactly the same as the RAW motions, but the rest of the structure is compeltely different.

architectural diagram of an inteprolated motion file

Interpolated motion header

Located straight after the motion header, it defines where all the structures are phyisically located inside the files. All the offsets uses 0x90 as origin. Some of the tables have no count, but only their offset. It is speculated that the game engine do not need to know their amount because there is no need to loop through them: other tables will reference them through an index.

Offset Type Description
0x00 short Bone count. Must match with the bone count of the model
0x02 short Total bone count. This is Bone Count + IK Bone Count
0x04 int Total frame count. How many frames the animation contains
0x08 int IK helpers offset
0x0C int Joint indices offset
0x10 int Key times count
0x14 int Initial pose offset
0x18 int Initial pose count
0x1C int Root Position offset
0x20 int F-Curves Forward offset
0x24 int F-Curves Forward count
0x28 int F-Curves Inverse offset
0x2C int F-Curves Inverse count
0x30 int F-Curve Keys offset
0x34 int Key Times offset
0x38 int Key Values offset
0x3C int Key Tangents offset
0x40 int Constraints offset
0x44 int Constraints count
0x48 int Constraint Activations offset
0x4C int Limiters offset
0x50 int Expressions offset
0x54 int Expressions count
0x58 int Expression Nodes offset
0x5C int Expression Nodes count
0x60 vec4f Bounding Box minimum
0x70 vec4f Bounding Box maximum
0x80 float Frame start
0x84 float Frame end
0x88 float Frames per second, defines the LFR
0x8c float Frame return, expressed in LFR
0x90 int External Effectors offset
0x94 int[3] Reserved

Initial pose

It is responsible to set the model into the initial pose.

Offset Type Description
0x00 short Bone index
0x02 short Channel ID
0x04 float Value to assign to the channel

F-Curves

Specifies how a specific bone should animate over time. The curve is modified by a series of keys. This Blender document helps visualize how the curves and their keys work.

Offset Type Description
0x00 short Bone / IK Helper index
0x02 4-bit Channel ID
0x02 2-bit Pre-type
0x02 2-bit Post-type
0x03 byte Key count
0x04 short Key start index

The table for the Forward Kinematic animation (skeleton) is followed by the table for the Inverse Kinematic animation (IK Helpers), which has the same structure. The IK Helper index starts from 0.

Cycle type

Channel Description
0 First / Last key
1 Subtractive / Additive
2 Repeat
3 Zero

F-Curve Keys

The keys that modify the F-Curves at specific times.

Offset Type Description
0x00 2-bit Interpolation type
0x00 14-bit Time index
0x02 short Value index
0x04 short Tangent index for ease-in (left)
0x06 short Tangent index for ease-out (right)

Interpolation types

Value Description
0 Constant
1 Linear
2 Hermite

Key Times

List of floats to define at which time a key applies. Measured in frames. Note that there can be decimal values, hence they apply between frames.

Key Values

List of floats used as values for the keys’ transformations.

Key Tangents

List of floats used as values for the keys’ tangents.

Constraints

Constraints a bone to another in a way (Follow position, orientation, direction…). Usually, the model bones connect to are ankles or hands as those are what it’s most likely to use IK.

Offset Type Description
0x00 byte Constraint type index
0x01 byte Temporary active flag
0x02 short Constrained joint index
0x04 short Source joint index
0x06 short Limiter index; -1 when not used
0x08 short Activation count
0x0A short Activation start index

Joint indexes refers to the bones followed by the IK helpers.

Constraint type

Channel Description
0 Position
1 Path
2 Orientation
3 Direction
4 Up Vector
5 Two Points
6 Scale
7 Camera
8 Camera Path
9 Int Path
10 Int
11 Camera Up Vector
12 Position Limit
13 Rotation Limit

Constraint Activations

Activations used in constraints. Use not known.

Offset Type Description
0x00 float Time
0x04 int Active

Constraint Limiters

Defines multiple limits for the constraint.

Offset Type Description
0x00 3b type
0x00 1b global
0x00 1b x min
0x00 1b x max
0x00 1b y min
0x00 1b y max
0x00 1b z min
0x00 1b z max
0x00 22b Reserved
0x04 int Padding
0x08 float Damping Width
0x0A float Damping Strength
0x0E vec4f Min
0x1E vec4f Max

Expressions

Applies a transformation to a target bone. These transformations are not direct and use an expression / formula instead.

Offset Type Description
0x00 short Joint index
0x02 short Channel ID
0x04 short Reserved
0x06 short Node index

The joint always applies to an IK Helper.

Expression Nodes

Nodes used by expressions. It seems to be a graph, where every node can point to multiple nodes.

Offset Type Description
0x00 byte Type index
0x01 byte isGlobal (1bit + 7 reserved)
0x02 short Element (-1 when unused)
0x04 float Value
0x08 short CAR (Node index or -1 when unused)
0x0a short CDR (Node index or -1 when unused)

Expression type

| Index | Description |———|————— | 0 | FUNC_SIN | 1 | FUNC_COS | 2 | FUNC_TAN | 3 | FUNC_ASIN | 4 | FUNC_ACOS | 5 | FUNC_ATAN | 6 | FUNC_LOG | 7 | FUNC_EXP | 8 | FUNC_ABS | 9 | FUNC_POW | 10 | FUNC_SQRT | 11 | FUNC_MIN | 12 | FUNC_MAX | 13 | FUNC_AV | 14 | FUNC_COND | 15 | FUNC_AT_FRAME | 16 | FUNC_CTR_DIST | 17 | FUNC_FMOD | 18 | OP_PLUS | 19 | OP_MINUS | 20 | OP_MUL | 21 | OP_DIV | 22 | OP_MOD | 23 | OP_EQ | 24 | OP_GT | 25 | OP_GE | 26 | OP_LT | 27 | OP_LE | 28 | OP_AND | 29 | OP_OR | 30 | VARIABLE_FC | 31 | CONSTANT_NUM | 32 | FCURVE_ETRNX | 33 | FCURVE_ETRNY | 34 | FCURVE_ETRNZ | 35 | FCURVE_ROTX | 36 | FCURVE_ROTY | 37 | FCURVE_ROTZ | 38 | FCURVE_SCALX | 39 | FCURVE_SCALY | 40 | FCURVE_SCALZ | 41 | LIST | 42 | ELEMENT_NAME | 43 | FUNC_AT_FRAME_ROT | -1 | EXPR_UNKNOWN

Inverse Kinematic helper

Creates additional “joints”, in a very similar way the bones or a skeleton are structured. Please see Constraints to know more. Its strucutre is exactly the same as the one found on MDLX’s models.

Offset Type Description
0x00 short Bone index
0x02 short Sibling bone index
0x04 short Parent bone index (-1 if root)
0x06 short Child bone index (-1 if root)
0x08 int Reserved
0x0C int Flags (10b unknown, 19b reserved, 1b enableBias, 1b below, 1b terminate)
0x10 float Scale X
0x14 float Scale Y
0x18 float Scale Z
0x1C float Scale W
0x20 float Rotate X
0x24 float Rotate Y
0x28 float Rotate Z
0x2C float Rotate W
0x30 float Translate X
0x34 float Translate Y
0x38 float Translate Z
0x3C float Translate W

Joint definition

The list of bones + IK Helpers. The order is not clear, but bones are in order on IK Helpers appear in the list based on both their IK parent and constrained bone. If we structure it as a graph it seems to be stored as pre-order traversal. The order is important as the game engine calculate first the matrix of both Model’s skeleton root and IK helper root.

Offset Type Description
0x00 short Joint index
0x02 2b ik
0x02 1b translation
0x02 1b rotation
0x02 1b fixed
0x02 1b calculated
0x02 1b calculated matrix 2 rotation
0x02 1b external effector
0x03 byte Reserved

Root Position

Defines the position of the object’s root as well as it’s movement through time.

Offset Type Description
0x00 vec4f Scale
0x10 vec4f Rotation
0x20 vec4f Translation
0x30 int[9] FCurve Forward index (-1 if unused)

External Effectors

Unknown. Possibly to aid on interaction with other objects. They point to an IK Helper.

Offset Type Description
0x00 short Joint index

Common Enum

Channels

Channel Description
0 Modify scale.x
1 Modify scale.y
2 Modify scale.z
3 Modify rotate.x
4 Modify rotate.y
5 Modify rotate.z
6 Modify translate.x
7 Modify translate.y
8 Modify translate.z
-1 Unknown (Fail-safe)