JBA File Structure - SWTOR-Slicers/WikiPedia GitHub Wiki
File Layout
- File Header
- Block Header, one per block
- Run-time initialized values, 4 bytes per block
- Array of Bone Data structs, 128-byte aligned, length equals number of bones
- Array of Block Data structs, 128-byte aligned, length equals number of blocks
- World Space, 128-byte aligned
- Bone Names
File Header
Offset (h) | Type | Count | Description | Values |
---|---|---|---|---|
00 | uint32 | 1 | Run-time initialized value | 0 |
04 | float | 1 | Animation length | N/A |
08 | float | 1 | FPS | 15.0,30.0 |
0C | uint32 | 1 | Number of blocks | 1-20 |
10 | uint32 | 2 | Run-time initialized values | 0 |
18 | uint32 | 1 | Number of bones | N/A |
1C | uint32 | 1 | Unknown | 0 |
20 | uint32 | 1 | Pointer to keyframes (run-time initialized) | 0FFFFFFFh |
24 | uint32 | 1 | Unknown | 0 |
Block Header
Offset (h) | Type | Count | Description | Values |
---|---|---|---|---|
00 | uint32 | 1 | Starting frame | N/A |
04 | uint32 | 1 | Size of the data structure | N/A |
Bone Data
Offset (h) | Type | Count | Description | Values |
---|---|---|---|---|
00 | float | 3 | Translation stride | N/A |
0C | float | 3 | Translation base | N/A |
18 | float | 3 | Rotation stride | N/A |
2A | float | 3 | Rotation base | N/A |
Block Data
Offset (h) | Type | Count | Description | Values |
---|---|---|---|---|
00 | uint32 | 1 | Number of bones | N/A |
04 | uint32 | 1 | Unknown | 0 |
08 | uint32 | 4 * number of bones | Keyframe layout | N/A |
N/A | uint16 | N/A | Keyframes (48-bit quaternion + optional 32-bit translation) | N/A |
Keyframe Layout
Keyframe layout contains four integer values per bone, where the first value represents a number of rotation poses and the third value represents a number of translation poses (optional).
Keyframes are stored according to this layout:
- Bone 0: keyframe 0 rotation
- Bone 0: keyframe 1 rotation
- Bone 0: keyframe 0 translation (optional)
- Bone 0: keyframe 1 translation (optional)
- Bone 1: keyframe 0 rotation
- Bone 1: keyframe 1 rotation
- Bone 1: keyframe 0 translation (optional)
- Bone 1: keyframe 1 translation (optional)
Keyframe Encoding
Rotation (on disk): Sign(1)-X(15)-Y(16)-Z(16)
Translation (on disk): Z(10)-Y(11)-X(11)
Decoding in Python:
val = ruint32(file)
pos_x = base.x + (val >> 21) * stride.x
pos_y = base.y + ((val >> 10) & 0x7ff) * stride.y
pos_z = base.z + (val & 0x3ff) * stride.z
pos = Vector((pos_x, pos_y, pos_z))
rot_x_raw = ruint16(file)
rot_x = base.x + (rot_x_raw & 0x7fff) * stride.x
rot_y = base.y + ruint16(file) * stride.y
rot_z = base.z + ruint16(file) * stride.z
rot_dot = rot_x * rot_x + rot_y * rot_y + rot_z * rot_z
rot_w = 0.0 if rot_dot > 1.0 else math.sqrt(1.0 - rot_dot)
if rot_x_raw & 0x8000:
rot_w *= -1.0
rot = Quaternion((rot_w, rot_x, rot_y, rot_z))
Rotations and translations are in the "morpheme" space. Below is its transformation matrix:
1000.0 0.0 0.0 0.0
0.0 0.0 -1000.0 0.0
0.0 1000.0 0.0 0.0
0.0 0.0 0.0 1.0
World Space
Offset (h) | Type | Count | Description | Values |
---|---|---|---|---|
00 | uint32 | 1 | Unknown | 0 |
04 | float | 1 | FPS | 15.0/30.0 |
08 | float | 3 | Translation stride | N/A |
14 | float | 3 | Translation base | N/A |
20 | float | 3 | Rotation stride | N/A |
2C | float | 3 | Rotation base | N/A |
38 | uint32 | 1 | Number of rotations | N/A |
3C | uint32 | 1 | Pointer to rotations (run-time initialized) | 0 |
40 | uint32 | 1 | Number of translations | N/A |
44 | uint32 | 1 | Pointer to translations (run-time initialized) | 0 |
48 | uint16 | 3 * number of rotations | Compressed rotations (run-time initialized?) | N/A |
N/A | uint32 | Number of translations | Compressed translations, 4-byte aligned | N/A |
Bone Names
Offset (h) | Type | Count | Description | Values |
---|---|---|---|---|
00 | uint32 | 1 | Number of names | N/A |
04 | uint32 | 1 | Unknown | N/A |
08 | uint32 | 1 | Offset to indices | 20 |
0C | uint32 | 1 | Offset to offsets | 20+4*(number of names) |
10 | uint32 | 1 | Offset to names | 20+8*(number of names) |
14 | uint32 | number of names | Indices | 0-N |
N/A | uint32 | number of names | Offsets into the names array | N/A |
N/A | char | N/A | Null-terminated names | N/A |