OBD:TRAM/raw0x34
This part belongs to the 01865-KONCOMpunch_heavy.TRAM file.
Offset | Type | Raw Hex | Value | Description |
---|---|---|---|---|
0x00 | int16 | 26 00 | 38 | start position of the pelvis animation (80 BD 00 + 26 = 80 BD 26) |
... | ... | ... | ... | ... |
0x24 | int16 | 84 0E | 3716 | start position of the right fist animation (80 BD 00 + 0E 84 = 80 CB 84) |
First element (black outline) - pelvis animation | ||||
0x26 | int16 | EE FA | 357 | x-start-position in degrees |
0x28 | int16 | E2 25 | 54 | y-start-position in degrees |
0x2A | int16 | 11 51 | 280 | z-start-position in degrees |
int8 | number of frames, which the animation has to go from one position to the next | |||
int16 | x-position in degrees | |||
int16 | y-position in degrees | |||
int16 | z-position in degrees | |||
0x00 | int16 | 82 F7 | 352 | x-end-position in degrees |
0x00 | int16 | BB 1B | 39 | y-end-position in degrees |
0x00 | int16 | 23 42 | 94 | z-end-position in degrees |
Detailed Information
Here's the minimal structure of the body animation tracks for a TRAM file (address stored at 0x34 in the dat)
(The example below is for SHINZOMidle1 : those bone tracks are found at 0x480020 in the original level18_Final.raw)
The global stucture is 19 bone tracks, preceded by a list of their offsets (the "header").
Information required to read this part :
- number of body parts (at 0x16A in the dat, always 19 in Oni)
- "compression size" (at 0x160 in the dat, 6 for almost all anims, 16 for a few)
- frame count (at 0x16C in the dat)
The size of a bone track is not known in advance. See "General info" below.
Header
0x00-0x25 : list of the offsets of the 19 bone tracks
Offset | Body part | Raw hex | Value (offset of bone track) |
---|---|---|---|
0x00 | Pelvis | 2600 | 0x26 |
0x02 | Lt Thigh | 3300 | 0x33 |
0x04 | Lt Calf | 4000 | 0x40 |
0x06 | Lt Foot | 4D00 | 0x4D |
0x08 | Rt Thigh | 5A00 | 0x5A |
0x0A | Rt Calf | 6700 | 0x67 |
0x0C | Rt Foot | 7400 | 0x74 |
0x0E | Mid | 8100 | 0x81 |
0x10 | Chest | 8E00 | 0x8E |
0x12 | Neck | 9B00 | 0x9B |
0x14 | Head | A800 | 0xA8 |
0x16 | Lt Shoulder | B500 | 0xB5 |
0x18 | Lt Arm | C200 | 0xC2 |
0x1A | Lt Wrist | CF00 | 0xCF |
0x1C | Lt Fist | DC00 | 0xDC |
0x1E | Rt Shoulder | E900 | 0xE9 |
0x20 | Rt Arm | F600 | 0xF6 |
0x22 | Rt Wrist | 0301 | 0x103 |
0x24 | Rt Fist | 1001 | 0x110 |
Bone tracks
General info
An orientation track is a succession of keyframe fields (either 6 or 16 bytes depending on the "compression size") defining the orientation of a bone (with respect to its parent) at a key moment. Every pair of keyframes is separated by an interval field (one byte) defining the number of frames between the two key moments. Orientation is interpolated linearly between two keyframes over the interval between them. If the cumulated intervals reach the total frame count of the animation (minus 1) then the next keyframe is the final one.
Thus the length of the track is determined upon reading
Compression size 6
Angle | Short | Raw hex |
---|---|---|
0° | 0x0000 | 0x0000 |
45° | 0x2000 | 0x0020 |
90° | 0x4000 | 0x0040 |
180° | 0x8000 | 0x0080 |
270° | 0xC000 | 0x00C0 |
An orientation consists of three angles, each of them a 2-byte integer (short). To get the angle in radians one needs to multiply the value with 9.587526e-5 (that is PI / 32767.5). Note that these angles cannot be used directly for interpolation, they must first be converted to quaternions.
The example here is the SHINZOMidle1 animation (10 frames long)
Offset | Body part | Raw hex | from | over | to |
---|---|---|---|---|---|
0x26 | Pelvis | 5F45 F93D B6FA 09 5F45 F93D B6FA | (98°, 87°, 353°) | 9 frames | (98°, 87°, 353°) |
0x33 | Lt Thigh | 1839 1B34 8877 09 1839 1B34 8877 | (80°, 73°, 168°) | 9 frames | (80°, 73°, 168°) |
0x40 | Lt Calf | 0000 0000 96AB 09 0000 0000 96AB | (0°, 0°, 241°) | 9 frames | (0°, 0°, 241°) |
0x4D | Lt Foot | 9436 DFFB 3E15 09 9436 DFFB 3E15 | (77°, 354°, 30°) | 9 frames | (77°, 354°, 30°) |
0x5A | Rt Thigh | 5351 3D13 DC9C 09 5351 3D13 DC9C | (114°, 27°, 221°) | 9 frames | (114°, 27°, 221°) |
0x67 | Rt Calf | 0000 0000 D5E7 09 0000 0000 D5E7 | (0°, 0°, 326°) | 9 frames | (0°, 0°, 326°) |
0x74 | Rt Foot | 5703 30FA ACF4 09 5703 30FA ACF4 | (5°, 352°, 344°) | 9 frames | (5°, 352°, 344°) |
0x81 | Mid | 1302 6301 6DFE 09 1302 6301 6DFE | (3°, 2°, 358°) | 9 frames | (3°, 2°, 358°) |
0x8E | Chest | 0402 9F06 7FF4 09 0402 9F06 7FF4 | (3°, 9°, 344°) | 9 frames | (3°, 9°, 344°) |
0x9B | Neck | 0000 FEFF 496F 09 0000 FEFF 496F | (0°, 360°, 156°) | 9 frames | (0°, 360°, 156°) |
0xA8 | Head | 90FB 2504 639B 09 90FB 2504 639B | (354°, 6°, 219°) | 9 frames | (354°, 6°, 219°) |
0xB5 | Lt Shoulder | 6548 B4DF 1677 09 6548 B4DF 1677 | (102°, 315°, 167°) | 9 frames | (102°, 315°, 167°) |
0xC2 | Lt Arm | 90E2 360D 48E5 09 90E2 360D 48E5 | (319°, 19°, 322°) | 9 frames | (319°, 19°, 322°) |
0xCF | Lt Wrist | 0000 0000 D7E4 09 0000 0000 D7E4 | (0°, 0°, 322°) | 9 frames | (0°, 0°, 322°) |
0xDC | Lt Fist | 1ABD 51EB D718 09 1ABD 51EB D718 | (266°, 331°, 35°) | 9 frames | (266°, 331°, 35°) |
0xE9 | Rt Shoulder | AD8B 592B 0D5E 09 AD8B 592B 0D5E | (196°, 61°, 132°) | 9 frames | (196°, 61°, 132°) |
0xF6 | Rt Arm | 2C1C 1116 40D7 09 2C1C 1116 40D7 | (40°, 31°, 303°) | 9 frames | (40°, 31°, 303°) |
0x103 | Rt Wrist | 0000 0000 1734 09 0000 0000 1734 | (0°, 0°, 73°) | 9 frames | (0°, 0°, 73°) |
0x110 | Rt Fist | 2341 5404 53EE 09 2341 5404 53EE | (92°, 6°, 335°) | 9 frames | (92°, 6°, 335°) |
In this example, there are only two keyframes for every bone, and the orientation is identical for both keyframes : in fact, Shinatama remains completely frozen during the whole anim.
Origin and direction of the angles
If the (0°, 0°, 0°) orientation is set for every bone, then all the bones point along the x axis of the character (from right to left) and face upwards
Viewed from above, you get something like this : "o" is a pivot (yeah, the shoulders are attached to the neck); ":)" is a smiley :)
15-o-14-o-13-o-12-o 4-o-3-o-2-o ^ z | | ^ :)11-o-10-o-9-o-8-o-1 < < <^< < < | | x ^ 19-o-18-o-17-o-16-o 7-o-6-o-5-o ^
Every angle triplet defines the rotation of a bone with respect to its parent (the "parent" of the pelvis lies on its back with its head pointing left, as above...). The orientation of the parent defines an (x,y,z) axis set : assuming the parent is aligned as above, this is simply the normal coordinate system (x=left, y=up, z=front).
The first rotation is about the x axis, the second one is about the new y axis, and the last one is about the newest z axis. All rotations are in the normal trigonometric direction (clockwise if looking in the direction of the axis).
Effectively, the first angle is the "twist" of the bone with respect to its parent (because the direction of the parent is the "x axis", i.e. the axis of the first rotation).
A leg's orientation is quite intuitive : if you set everything to (0°, 0°, 0°) except the orientation of the thighs (both set to (0°, 0°, 180°)), you get "normal" legs. Arms are a bit more complicated.
More, later...
- Here is kinda "polished" formula how to get angle in degrees from binary data and vice versa.
- X is value from binary in decimal (converted)
- α is angle in degrees
- α= X*2,4/436,9
- X= α*436,9/2,4
- Receipt is easy. Get value from binary data and conver it into decimal. this number is X, so use first formula to get angle. Maybe these formulas can be shorted even more, but I think this is both quite nice and accurate.
- Loser 21:13, 12 July 2007 (CEST)
- Can't see what's so un-nice about 8192/45 and 45/8192 or (duh) 65536/360 and 360/65536...
- For dequantization to radians, the engine uses 9.587526e-5= 2*PI/65535 as detailed ABOVE.
- (although in my opinion it's more consistent to use 9.587380e-5= 2*PI/65536 ... oh well)
- geyser 04:37, 13 July 2007 (CEST)
Compression size 16
In this case a quaternion (4 float values) is stored instead of 3 angles. It applies to the following original anims :
|
|
|
|
|
|
|