Motion (.MOT) File Format

From Ōkami Speedrun Wiki
Revision as of 20:57, 7 September 2025 by Akito (talk | contribs)
Jump to navigation Jump to search

Note: This page pertains to Reverse Engineering of Okami File Formats.

Explanation

This file incorporates curves and/or properties for an given embbed model. Because of that, it's almost always certain that they are contained in a file container (dat). There's instances of mots that controlled properties instead of bones, so it's not always certain of what it animates. A further inspection have to be done. But since it animates bones most of the times, i will threat it as curves that animates bones.


Every curve is computed using the Cubic Hermite interpolation formula. That means every curve is treated as a Hermite Curve.

Formula of the Cubic Hermite Interpolation, used in curves.


Note: This formula's image was taken from the Cubic Hermite spline Wiki.

Mot main header (8 bytes length)

Offset Type Size Description
0x00 uint32_t 4 File identifier (Magic number).
0x04 uint16_t 2 Animation's frame count.
0x06 uint8_t 1 Animation's curve count.
0x07 uint8_t 1 Loop flag, sets if the animation either loops or not (1/0).

On offset 8, The File gives informations about the curves, i.e: what bone it animates, etc.

Curve Info (8 bytes length)

Offset Type Size Description
0x00 int8_t 1 Bone index (-1 means it animates the mode's root bone).
0x01 int8_t 1 Curve properties (See below).
0x02 uint16_t 2 Curve keyframe count.
0x04 uint32_t / float32_t 4 Keyframes offset / value

the 4th offset of each curve info can be either a float, or uint32. it's only set as a float if the Property Family of the curve is a Single Pose. Otherwise, it's a offset. The curve property will define what property of the bone/object it is animating. There's some properties who could not be determined yet. See some already identified values bellow.

Curve Properties (Already identified)

Value Property Family Property
0 Single Pose Position X
1 Single Pose Position Y
2 Single Pose Position Z
3 Single Pose Rotation X
4 Single Pose Rotation Y
5 Single Pose Rotation Z
6 Single Pose Scale X
7 Single Pose Scale Y
8 Single Pose Scale Z
16 Quantized Curve Position X
17 Quantized Curve Position Y
18 Quantized Curve Position Z
19 Quantized Curve Rotation X
20 Quantized Curve Rotation Y
21 Quantized Curve Rotation Z
22 Quantized Curve Scale X
23 Quantized Curve Scale Y
24 Quantized Curve Scale Z
50 Quantized-Precision Curve Position X
51 Quantized-Precision Curve Position Y
52 Quantized-Precision Curve Position Z
53 Quantized-Precision Curve Rotation X
54 Quantized-Precision Curve Rotation Y
55 Quantized-Precision Curve Rotation Z
56 Quantized-Precision Curve Scale X
57 Quantized-Precision Curve Scale Y
58 Quantized-Precision Curve Scale Z
80 Full-Precision Curve Position X
81 Full-Precision Curve Position Y
82 Full-Precision Curve Position Z
83 Full-Precision Curve Rotation X
84 Full-Precision Curve Rotation Y
85 Full-Precision Curve Rotation Z
86 Full-Precision Curve Scale X
87 Full-Precision Curve Scale Y
88 Full-Precision Curve Scale Z

The Property Family tells the game how the keyframes are handled ingame. Depending on the Family the property is set in, curves will be readen diferently.

Single Pose

This Property Family is the cheapest to compute. Because since it's a single pose, The there's only one keyframe, in which is given on the Curve Info.

(Example):

Offset Value Description
0x00 -1 This field is telling that the curve is animating the root bone of the model.
0x01 5 This field is telling that the curve animates the Z rotation of the root bone, being set on a Single-Pose Property Family.
0x02 1 This field is telling that there's only one keyframe on this curve, which makes sense, since this curve is set on a Single-Pose Property Family.
0x04 0.52 This field is telling the value or the Z rotation right away, no more computing needed.

Quantized Curve

This Property Family Is known for having Quantized values. It's the most eficient type of curve, regarding storage size.

(Example):

Offset Value Description
0x00 0 This field is telling that the curve is animating the bone index 0 of the model.
0x01 16 This field is telling that the curve animates the X Position of the root bone, being set on a Quantized Curve Property Family.
0x02 4 This field is telling that there's 4 keyframes on this curve.
0x04 512 This field is telling in which offset of the file the keyframes header are located.

Quantized Curve Keyframe Header (12 bytes length)

Only Quantized property families contain a keyframe Header. That's because Every keyframe is dependent on the values given on the Header.

Offset Type Size Description
0x00 float16_t 2 Minimum value of a keyframe.
0x02 float16_t 2 Maximum value of a keyframe.
0x04 float16_t 2 Minimum value of the start tangent (m0)
0x06 float16_t 2 Maximum value of the start tangent (m0)
0x08 float16_t 2 Minimum value of the end tangent (m1)
0x0A float16_t 2 Maximum value of the end tangent (m1)

This is the only Property Family that uses the float16_t type. That's a special type of float that can be represented as two bytes. Especifically, this type of float is built with a 1 bit sign, 6 bit exponent, a 9 bit significand and a bias of 47. The bias favours smaller numbers. That means, the highest the number, the less precise it is. That's to compensate the small amount of data two bytes can pack.

After reading the keyframes header, what follows up are the keyframes in which the actual keyframes are stored in.

Quantized Keyframes (4 bytes length)

Offset Type Size Description
0x00 uint8_t 1 Keyframe time (Relative to the time of the last keyframe).
0x01 uint8_t 1 Delta value of the Keyframe.
0x02 uint8_t 1 Delta value of the keyframe's start tangent. (m0)
0x03 uint8_t 1 Delta value of the keyframe's end tangent. (m1)


The keyframe deltas are calculated as following: X = Y + Z * W Where X is the output value, Y is the minimum value, Z is the maximum value, and W is the delta value. Essentially, the formula is telling that the output value is blending from the minimum to the maximum value, based on the value of Delta.

So, that would leave us with...

  • P_value = minimum_value + maximum_value * delta_value
  • M0_value = minimum_m0 + maximum_m0 * delta_m0
  • M1_value = minimum_m1 + maximum_m1 * delta_m1

After computing the full values, The curve is to be computed using the Hermite Cubic Interpolation.


Quantized-Precision Curve

For this Property Family, the process is almost the exact same. However, there are some changes. First of, This is a more precise version of the Quantized curves. Therefore, the values are doubled up.

(Example):

Offset Value Description
0x00 0 This field is telling that the curve is animating the bone index 0 of the model.
0x01 50 This field is telling that the curve animates the X Position of the root bone, being set on a Quantized-Precision Curve Property Family.
0x02 4 This field is telling that there's 4 keyframes on this curve.
0x04 512 This field is telling in which offset of the file the keyframes header are located.

(Keyframes header):

Offset Type Size Description
0x00 float32_t 4 Minimum value of a keyframe.
0x02 float32_t 4 Maximum value of a keyframe.
0x04 float32_t 4 Minimum value of the start tangent (m0)
0x06 float32_t 4 Maximum value of the start tangent (m0)
0x08 float32_t 4 Minimum value of the end tangent (m1)
0x0A float32_t 4 Maximum value of the end tangent (m1)

You can notice that, since the values were doubled up, The use of the custom float16_t were completely removed, since now the file can use float32's instead, which are more precise and stable in comparision. This results on the size of the keyframe header to be extended to 24 bytes each.

(Keyframe):

Offset Type Size Description
0x00 uint16_t 2 Keyframe time (Absolute).
0x02 uint16_t 2 Delta value of the Keyframe.
0x04 uint16_t 2 Delta value of the keyframe's start tangent. (m0)
0x06 uint16_t 2 Delta value of the keyframe's end tangent. (m1)

Aside from the keyframe time being Aboslute, the rest of the process remains the exact same.


Full-Precision Curve

This is the most straightforward Property Family. However, the most expensive (in storaging terms). Different from the Quantized types, this one is not dependent of a Keyframe Header. Instead, it tells the values right away, Rendering this Property Family the easiest to compute (considering this is not a single pose), the one with the most accurate movements, but the most expensive to store in storage terms.

(Example):

Offset Value Description
0x00 0 This field is telling that the curve is animating the bone index 0 of the model.
0x01 80 This field is telling that the curve animates the X Position of the root bone, being set on a Full-Precision Curve Property Family.
0x02 4 This field is telling that there's 4 keyframes on this curve.
0x04 512 This field is telling in which offset of the file the keyframes are located.

(Keyframes):

Offset Type Size Description
0x00 uint16_t 2 Keyframe time (Absolute).
0x02 uint16_t 2 Padding, used to align the file, It has no use.
0x04 float32_t 4 Keyframe Value
0x06 float32_t 4 Value of the keyframe's end tangent. (m0)
0x06 float32_t 4 Value of the keyframe's end tangent. (m1)

After that, the values can be used straight into the cubic interpolation formula.

Final nodes

The space in which the movement of bones takes in also depends of the Property Family the curve is set in. For instance, if a bone's rest position's property (let's say it's 125.14 for X) is animated on a quantized curve, Since this is a big value, movement information will be lost due to the nature of the quantized Property Family, especially when not used in a Quantized-Precision Curve. Because of that, The bone's movements are relative to the bone's parent's pose on quantized types. For full precision however, since quantization is not needed, the property values are absolute.