Jump to content

OBD:TRAM: Difference between revisions

1,734 bytes added ,  17 December 2021
tedious math covering the known limitations on animation length
m (note on the motion blur padding)
(tedious math covering the known limitations on animation length)
Line 188: Line 188:
:While Oni can store a number as large as 255 in 0x187, Oni only allocates memory for 16 particles per TRAM, and it does not check to make sure that the actual number of particles is ≤ 16. Thus you can easily crash Oni by initiating a move which has 17 particles attached.
:While Oni can store a number as large as 255 in 0x187, Oni only allocates memory for 16 particles per TRAM, and it does not check to make sure that the actual number of particles is ≤ 16. Thus you can easily crash Oni by initiating a move which has 17 particles attached.


;Eight-bit frame counts and limiting consequences thereof
;Limitations on animation length
:Frame counts in Oni's TRAM are either absolute frame counts since the beginning of the animation, or intervals between events or keyframes. Mostly they are 16-bit integer fields (allowing for a range of either 65535 frames = 1092.25 seconds, or 32767 frames = 546.1333... seconds, depending on whether it's interpreted as signed or unsigned by the engine). In some contexts, though, 8-bit integers (bytes) are used instead, which reduces the range to 255 frames = 4.25 seconds (or 127 frames = 2.11666... seconds if the engine reads the byte as signed).
:Frame counts in Oni's TRAM are either absolute frame counts since the beginning of the animation, or intervals between events or keyframes.
:The following contexts involve 8-bit frame counts:
:(The following analysis assumes 60fps as an animation's frame rate. If the framerate can be reduced, the limiting time amounts will increase accordingly.)
*[[OBD:TRAM/raw0x1C|Motion blur]]:
:'''''16-bit frame counts'''''
**the "Lifetime" parameter is an 8-bit frame count, meaning a "ghost" cannot last more than 4.25 frames before disappearing completely; (LIMITATION SEVERITY: MINOR)
:Most typically a frame count is an unsigned 16-bit integer, which allows for a comfortable range of 65535 frames = 1092.25 seconds = 18 m 12.25 s. Even if the integer is accidentally parsed as 16-bit ''signed'', the wraparound to negative values only happens after 32767 frames = 546.1<span style="text-decoration:overline;">3</span> seconds = 9 m 6.1<span style="text-decoration:overline;">3</span> s. Oni has other contexts where frame counts are stored as 16-bit integers, e.g., [[OBD:SNDD|SNDD]] and [[OBD:OBAN|OBAN]].
**the "Interval" is an 8-bit frame interval, meaning that successive "ghosts" can be spawned no more than 4.25 seconds apart; (LIMITATION SEVERITY: MINOR)
 
**<strike>the undocumented final field also looks like it could be an 8-bit count or interval (hypothesis so far is "trailing in frames").</strike> This field appears to be padding/garbage.
:'''''8-bit frame counts'''''
*[[OBD:TRAM/raw0x34|Rotation data]]:
:Some of the frame counts inside a TRAM are stored as 8-bit integers (unsigned), which reduces the range to 255 frames = 4.25 seconds (or, in the event of signed interpretation, 127 frames = 2.11<span style="text-decoration:overline;">6</span> seconds). The contexts where 8-bit frame counts are as follows.
**Intervals between a bone's keyframes are 8-bit fields, meaning that keyframes cannot be more than 4.25 seconds apart. (LIMITATION SEVERITY: MINOR)
:*[[OBD:TRAM/raw0x1C|Motion blur]], "Lifetime" and "Interval", meaning that "ghosts" can be spawned no more than 4.25 seconds apart and can last no more than 4.25 before disappearing (LIMITATION SEVERITY: MINOR)
*"Extent info" (main TRAM file, see above):
:*[[OBD:TRAM/raw0x34|Rotation data]], intervals between a bone's keyframes, meaning that rotation keyframes for a bone cannot be more than 4.25 seconds apart. (LIMITATION SEVERITY: MINOR)
**The "attack frame offset from the attack with index 0" is an 8-bit frame interval, meaning that attacks belonging to a same TRAM cannot be more than 4.25 seconds apart, or the extent of the later attacks may not be taken into account properly by the AI. (LIMITATION SEVERITY: Can be an issue for very long special moves or throws, where damage is dealt both at the beginning and at the end of the animation.)
:*"Extent info" (main TRAM file, see above): the "attack frame offset from the attack with index 0" is an 8-bit frame interval, meaning that attacks belonging to a same TRAM cannot be more than 4.25 seconds apart, or the extent of the later attacks may not be taken into account properly by the AI. (LIMITATION SEVERITY: Can be an issue for very long special moves or throws, where damage is dealt both at the beginning and at the end of the animation.)
*"Invulnerable" range (main TRAM file, see above):
:*"Invulnerable" range (main TRAM file, see above): The invulnerability range is a pair of 8-bit frame indices, meaning that the invulnerability range cannot extend past 4.25 seconds. (LIMITATION SEVERITY: Can be an issue for very long crowd-clearing moves, like a much longer "Whirling Dervish" (ELICOMpunch_heavy) or long versions of Muro's "Breakdancer" or "Helicopter" moves; a possible workaround is to set invulnerability for the whole animation rather than for an 8-bit frame range)
**The invulnerability range is a pair of 8-bit frame indices, meaning that the invulnerability range cannot extend past 4.25 seconds. (LIMITATION SEVERITY: Can be an issue for very long crowd-clearing moves, like a much longer "Whirling Dervish" (ELICOMpunch_heavy) or long versions of Muro's "Breakdancer" or "Helicopter" moves; a possible workaround is to set invulnerability for the whole animation rather than for an 8-bit frame range)
 
:The above information assumes 60fps as the animation's frame rate. If the framerate can be reduced, the limiting time amounts will increase accordingly.
:'''''16-bit raw data offsets'''''
:Unlike files like [[OBD:AGDB|AGDB]] and [[OBD:SUBT|SUBT]] (which use 32-bit pointers into the .raw data stored in the .dat part), a TRAM's [[OBD:TRAM/raw0x34|rotation data]] starts off with a set of 16-bit offsets, stored in the .raw part and pointing into the following data (typically there are 19 such offsets, one for each bone in a skeleton).
:For the last offset to work, it must be at most equal to 65535 and, since the first 38 bytes are taken up by the offsets, this leaves at most 65497 bytes for the cumulated size of the 18 first rotation tracks.
:The raw size of a rotation track depends on the number of keyframe intervals (let's call it N) and on the compression size (either 6 or 16 bytes): a size-6 rotation track takes up 7N+6 bytes, and a size-16 rotation track takes up 17N+16 bytes.
:For a size-6 animation, the "average N" for the first 18 tracks cannot exceed 518.96, so that 126N+108 stays below 65497. For a size-16 animation, this "average N" for the first 18 tracks must not exceed 213.1013, so that 306N+288 stays below 65497.
:For an animation that has a keyframe for every bone at each game tick, a 518-frame duration corresponds to 8.6<span style="text-decoration:overline;">3</span> seconds, whereas 213 frames = 3.55 seconds. Typically, however, rotation tracks will have significant keyframe reduction, e.g., Konoko's "Rising Fury!" lasts 80 frames but the pelvis rotation has only 23 keyframe intervals. Assuming 4:1 keyframe reduction for typical animations, this means that the 16-bit offset won't be an issue (for size-6 animations) unless the animation is longer than about 30 seconds.


{{OBD_File_Footer | type=TRAM | prev=TRAC | next=TRAS | name=Totoro Animation Sequence | family=Character}}
{{OBD_File_Footer | type=TRAM | prev=TRAC | next=TRAS | name=Totoro Animation Sequence | family=Character}}


{{OBD}}
{{OBD}}