Table of contents:
Animation Format
SWTOR animations are stored in JBA files, one animation per file. Each animation consists of one or more parts.
Here and below, "aligned at 128-byte boundary" means that the section in question must start at offsets like 80h, 100h, 180h and so on.
File Layout
- File Header
- Part Header, one per part
- Run-time initialized values, 4 bytes per part
- Bone Data
- Part Data, one per part
- Keyframes
- Bones
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 parts | 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 |
Part Header
Offset (h) | Type | Count | Description | Values |
---|---|---|---|---|
00 | uint32 | 1 | Index into the timestamps | N/A |
04 | uint32 | 1 | Size of the data structure | N/A |
Bone Data
This section is aligned at 128-byte boundary. It contains exactly 12 float values per bone.
It is very likely that these values are minimum/maximum translation and minimum/maximum orientation of each bone (orientations are represented as quaternions minus the W component). Translations are probably scaled (multiplied by a 1000?).
Part Data
This section is aligned at 128-byte boundary.
Keyframe Layout
Keyframe layout contains four integer values per bone, where the first value represents a number of orientation poses and the third value represents a number of translation poses (optional).
Keyframes are stored according to this layout:
- Bone 0: keyframe 0 orientation
- Bone 0: keyframe 1 orientation
- Bone 0: keyframe 0 translation (optional)
- Bone 0: keyframe 1 translation (optional)
- Bone 1: keyframe 0 orientation
- Bone 1: keyframe 1 orientation
- Bone 1: keyframe 0 translation (optional)
- Bone 1: keyframe 1 translation (optional)
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 Encoding
Orientation (on disk): X(16)-Y(16)-Z(16)
Translation (on disk): Z(10)-Y(11)-X(11)
Exact order of components is unknown. Highest bit of each component is most likely a sign bit.
Keyframes
This section is aligned at 128-byte boundary.
Data section at 48h is 4-byte aligned, i.e. if number of keyframes is odd, there are 2 additional bytes at the end.
Offset (h) | Type | Count | Description | Values |
---|---|---|---|---|
00 | uint32 | 1 | Unknown | 0 |
04 | float | 1 | FPS | 15.0/30.0 |
08 | float | 3 | Translation maximum | N/A |
14 | float | 3 | Translation minimum | N/A |
20 | float | 3 | Orientation maximum (run-time initialized?) | N/A |
2C | float | 3 | Orientation minimum (run-time initialized?) | N/A |
38 | uint32 | 1 | Number of keyframes | N/A |
3C | uint32 | 1 | Pointer to orientation poses (run-time initialized) | 0 |
40 | uint32 | 1 | Number of keyframes | N/A |
44 | uint32 | 1 | Pointer to translation poses (run-time initialized) | 0 |
48 | uint16 | 3 * number of keyframes | Compressed orientations (run-time initialized?) | N/A |
N/A | uint32 | Number of keyframes | Compressed translations | N/A |
Bones
When two animations target the same skeleton, they have identical values at 04h, 08h and 0Ch.
Offset (h) | Type | Count | Description | Values |
---|---|---|---|---|
00 | uint32 | 1 | Number of bones | N/A |
04 | uint32 | 1 | Unknown | N/A |
08 | uint32 | 1 | Unknown | 00000014h |
0c | uint32 | 2 | Unknown | N/A |
14 | uint32 | number of bones | Bone indices | 0-N |
N/A | uint32 | number of bones | Offsets into the names array | N/A |
N/A | char | N/A | Null-terminated bone names | N/A |