Difference between revisions of "ANIM (File Format)"

From Retro Modding Wiki
Jump to: navigation, search
(Rotation Vector Bitstream Format)
 
(6 intermediate revisions by 2 users not shown)
Line 1: Line 1:
The '''ANIM format''' is used in conjunction with [[CINF (File Format)|CINF]] + [[CSKR (File Format)|CSKR]]
+
The '''ANIM''' format is used to represent discrete [[wikipedia:Key frame|animation keys]]
rigging to animate [[CMDL (File Format)|CMDL meshes]].
+
bound to a skeletal rig.
  
There are two versions of the ANIM format in ''Metroid Prime'' (indicated by the file's first long value):
+
Keyed attributes include:
  
{| class="wikitable"
+
* [[wikipedia:Quaternion|Quaternion]] Rotations (WXYZ)
!Version
+
* Translations (XYZ)
!Description
+
* Scale (XYZ, since MP2)
|-
+
|0x0
+
|[[#Quaternion Array Format|Quaternion Array Format]]
+
|-
+
|0x2
+
|[[#Rotation Vector Bitstream Format|Rotation Vector Bitstream Format]]
+
|}
+
  
== Quaternion Array Format ==
+
ANIMs are used in a variety of ways by Retro's engine. A single ANIM resource is known as
 +
a ''primitive'' which may be blended and/or sequenced with other primitives to assemble
 +
complex character animations (defined by [[ANCS (File Format)|ANCS]] and [[CHAR (File Format)|CHAR]]).
  
The '''Quaternion Array Format''' (0x0) is a less common animation format in ''Metroid Prime''.
+
Each game has deviations in the format, but the principle of operation remains the same for all of them:
It's only used in a ''Ridley'' intro animation and the rotating ''pirate data'' artifact hologram
+
above the Impact Crater.
+
  
The format maps animation channels to bones and supplies rotations as an array of [[wikipedia:Quaternion|quaternion]] (WXYZ) keys.
+
* [[ANIM (Metroid Prime)]] (used in Metroid Prime 1 and 2)
Optionally, translations may be specified for a subset of bones as an array of float3 keys.
+
* [[ANIM (Metroid Prime 3)]]
 
+
* [[ANIM (Donkey Kong Country Returns)]]
=== Layout ===
+
* [[ANIM (Tropical Freeze)]]
 
+
{| class="wikitable"
+
!Data Type
+
!Element Count
+
!Identifier
+
!Notes
+
|-
+
|[[#Header0|Header0]]
+
|1
+
|header
+
|
+
|-
+
|char
+
|header‑>bone_entry_count
+
|bone_entry_map
+
|The index-positions of this table correspond to the ''Bone IDs'' in the associated [[CINF (File Format)|CINF]]. The value is 0xff if the bone is not animated by this ANIM or an index relating the ''bone_translation_map'' and ''quaternion_key_array'' below
+
|-
+
|long
+
|1
+
|bone_channel_count
+
|Count of bone channels present in the ''bone_translation_map'' and ''quaternion_key_array'' below
+
|-
+
|char
+
|bone_channel_count
+
|bone_translation_map
+
|Each bone channel may be optionally augmented with translation vectors at the bottom of the file. The index-positions of this table correspond to the values in the ''bone_entry_map'' above. The value is 0xff if the bone is not translated by this ANIM or an index relating the ''quaternion_key_array'' below
+
|-
+
|long
+
|1
+
|quaternion_key_count
+
|Count of elements in ''quaternion_key_array'' below
+
|-
+
|float4
+
|quaternion_key_count
+
|quaternion_key_array
+
|The quaternion keys are interleaved as such (bone-major):
+
<pre>
+
|------------|------------|-----|------------|
+
| bone0/key0 | bone0/key1 | ... | bone0/keyN |
+
| bone1/key0 | bone1/key1 | ... | bone1/keyN |
+
| .......... | .......... | ... | .......... |
+
| boneN/key0 | boneN/key1 | ... | boneN/keyN |
+
|------------|------------|-----|------------|
+
</pre>
+
|-
+
|long
+
|1
+
|translation_key_count
+
|Count of elements in ''translation_key_array'' below
+
|-
+
|float3
+
|translation_key_count
+
|translation_key_array
+
|The translation keys are interleaved as such (bone-major):
+
<pre>
+
|------------|------------|-----|------------|
+
| bone0/key0 | bone0/key1 | ... | bone0/keyN |
+
| bone1/key0 | bone1/key1 | ... | bone1/keyN |
+
| .......... | .......... | ... | .......... |
+
| boneN/key0 | boneN/key1 | ... | boneN/keyN |
+
|------------|------------|-----|------------|
+
</pre>
+
Any bone channels that were marked 0xff in the ''bone_translation_map'' are skipped by this array
+
|-
+
|long
+
|1
+
|evnt_ref
+
|ID for this ANIM's [[EVNT (File Format)|EVNT]] resource, or 0xffffffff if no events triggered
+
|}
+
 
+
=== Header0 ===
+
 
+
{| class="wikitable"
+
!Offset
+
!Length
+
!Data Type
+
!Identifier
+
!Notes
+
|-
+
|0x0
+
|4
+
|float
+
|duration
+
|Time in seconds that the animation plays for
+
|-
+
|0x4
+
|4
+
|float
+
|key_interval
+
|Time in seconds between keys of each bone channel (reciprocal of frame-rate)
+
|-
+
|0x8
+
|4
+
|long
+
|bone_entry_count
+
|Count of bone-channels in animation
+
|-
+
|0xC
+
|4
+
|long
+
|key_count
+
|Count of keys for each bone channel (keys are set for every frame of the animation)
+
|}
+
 
+
== Rotation Vector Bitstream Format ==
+
 
+
The '''Rotation Vector Bitstream Format''' (0x2) is the most widely used animation format in ''Metroid Prime''.
+
The format uses a compressed [[wikipedia:Bitstream|bitstream]] to store keys that have been
+
[[wikipedia:Delta encoding|delta encoded]] and [[wikipedia:Quantization (signal processing)|quantized]]
+
to make for a very compact, compressed animation. The data is processed sequentially to reconstruct the
+
uncompressed bone channel data as quaternions.
+
 
+
In addition to the bitstream quantization, the format includes a bitmap specifying which frames of the animation have
+
keys added. Consequently, the runtime generates missing keys via interpolation (reducing animation size further).
+
 
+
=== Key Values ===
+
When decoding the animation, each bone's rotation (and possibly translation) values are initialized to the ''initial_*''
+
values in the ''bone channel descriptors''. For every frame of every bone channel, the key value in the bitstream is ''added''
+
with the previous key value (to resolve the delta encoding).
+
 
+
Once resolved, rotation components are divided by ''rotation_divisor'', resulting in an axis-angle
+
[[wikipedia:Axis–angle_representation#Rotation_vector|rotation vector]]. This rotation vector is converted
+
to quaternion imaginary components with the W component derived via normalization and a ''sign-bit''
+
packed into the bitstream:
+
 
+
<pre>
+
q = &pi; / 2.0 / rotation_divisor
+
X = sin(rx * q)
+
Y = sin(ry * q)
+
Z = sin(rz * q)
+
W = sqrt(MAX((1.0 - (X^2 + Y^2 + Z^2)), 0.0))
+
W = sign_bit ? -W : W
+
</pre>
+
 
+
Translation components are multiplied by ''translation_multiplier'', yielding world units.
+
 
+
=== Layout ===
+
 
+
{| class="wikitable"
+
!Data Type
+
!Element Count
+
!Identifier
+
!Notes
+
|-
+
|[[#Header2|Header2]]
+
|1
+
|header
+
|
+
|-
+
|long
+
|round_up(header&#8209;>key_bitmap_length / 32)
+
|key_bitmap
+
|Word-packed bitmap. Each word is read from least-significant to most-significant bit. A set bit indicates the frame at the bit's position has keys for each bone channel.
+
|-
+
|long
+
|1
+
|bone_channel_count
+
|Count of animated bone channels (matches header&#8209;>bone_channel_count)
+
|-
+
|long
+
|1
+
|bone_channel_count
+
|Duplicate channel count for some reason
+
|-
+
|[[#Bone Channel Descriptor|Bone Channel Descriptor]]
+
|header&#8209;>bone_channel_count
+
|bone_channel_descriptor_table
+
|Table describing animated bone channels
+
|-
+
|long
+
|<remainder of file>
+
|key_bitstream
+
|Word-packed bitstream laid out as described by the descriptor table. The bitstream is unpacked just like ''key_bitmap'' (least-significant to most-significant).
+
Key values are tightly-packed, quantized integers whose bit-depth is specified by the ''q_*'' values in the descriptor table.
+
Each bone-channel key-set starts with a single bit providing the ''W sign-bit'' (1 for negative, 0 for positive).
+
 
+
The key integers are signed using [[wikipedia:Two's complement|Two's complement]] representation.
+
|}
+
 
+
=== Header2 ===
+
 
+
{| class="wikitable"
+
!Offset
+
!Length
+
!Data Type
+
!Identifier
+
!Notes
+
|-
+
|0x0
+
|4
+
|long
+
|scratch_size
+
|Amount of memory that the animation system needs to allocate to process animation
+
|-
+
|0x4
+
|4
+
|long
+
|evnt_ref
+
|ID for this ANIM's [[EVNT (File Format)|EVNT]] resource, or 0xffffffff if no events triggered
+
|-
+
|0x8
+
|4
+
|long
+
|unknown0
+
|Always 0x1
+
|-
+
|0xC
+
|4
+
|float
+
|duration
+
|Time in seconds that the animation plays for
+
|-
+
|0x10
+
|4
+
|float
+
|interval
+
|Time in seconds between frames (reciprocal of frame-rate, typically 30-fps)
+
|-
+
|0x14
+
|4
+
|long
+
|unknown1
+
|Always 0x3
+
|-
+
|0x18
+
|4
+
|long
+
|unknown2
+
|Always 0x0
+
|-
+
|0x1C
+
|4
+
|long
+
|rotation_divisor
+
|Rotation vectors are divided by this value before being applied
+
|-
+
|0x20
+
|4
+
|float
+
|translation_multiplier
+
|Translation vectors are multiplied by this value before being applied
+
|-
+
|0x24
+
|4
+
|long
+
|bone_channel_count
+
|Count of bone channels present in ANIM
+
|-
+
|0x28
+
|4
+
|long
+
|unknown3
+
|Always 0x1
+
|-
+
|0x2C
+
|4
+
|long
+
|key_bitmap_length
+
|Number of bits in ''key_bitmap''
+
|}
+
 
+
=== Bone Channel Descriptor ===
+
 
+
{| class="wikitable"
+
!Offset
+
!Length
+
!Data Type
+
!Identifier
+
!Notes
+
|-
+
|0x0
+
|4
+
|long
+
|bone_id
+
|''Bone ID'' in the associated [[CINF (File Format)|CINF]] for this bone channel
+
|-
+
|0x4
+
|2
+
|short
+
|key_count
+
|Number of keys in the bitstream for this bone channel (same value for all channels in animation)
+
|-
+
|0x6
+
|2
+
|short
+
|initial_rx
+
|Initial X value of bone's rotation vector
+
|-
+
|0x8
+
|1
+
|char
+
|q_rx
+
|Number of bits allocated to bone's ''rx'' in bitstream
+
|-
+
|0x9
+
|2
+
|short
+
|initial_ry
+
|Initial Y value of bone's rotation vector
+
|-
+
|0xB
+
|1
+
|char
+
|q_ry
+
|Number of bits allocated to bone's ''ry'' in bitstream
+
|-
+
|0xC
+
|2
+
|short
+
|initial_rz
+
|Initial Z value of bone's rotation vector
+
|-
+
|0xE
+
|1
+
|char
+
|q_rz
+
|Number of bits allocated to bone's ''rz'' in bitstream
+
|-
+
|0xF
+
|2
+
|short
+
|translation_key_count
+
|If this bone channel has an animated translation, its value will match ''key_count'', otherwise the value will be 0.
+
'''If the value is 0, this descriptor ends here'''
+
|-
+
|0x11
+
|2
+
|short
+
|initial_tx
+
|Initial X value of bone's translation vector
+
|-
+
|0x13
+
|1
+
|char
+
|q_tx
+
|Number of bits allocated to bone's ''tx'' in bitstream
+
|-
+
|0x14
+
|2
+
|short
+
|initial_ty
+
|Initial Y value of bone's translation vector
+
|-
+
|0x16
+
|1
+
|char
+
|q_ty
+
|Number of bits allocated to bone's ''ty'' in bitstream
+
|-
+
|0x17
+
|2
+
|short
+
|initial_tz
+
|Initial Z value of bone's translation vector
+
|-
+
|0x19
+
|1
+
|char
+
|q_tz
+
|Number of bits allocated to bone's ''tz'' in bitstream
+
|}
+
  
 
[[Category:File Formats]]
 
[[Category:File Formats]]

Latest revision as of 19:50, 5 May 2016

The ANIM format is used to represent discrete animation keys bound to a skeletal rig.

Keyed attributes include:

  • Quaternion Rotations (WXYZ)
  • Translations (XYZ)
  • Scale (XYZ, since MP2)

ANIMs are used in a variety of ways by Retro's engine. A single ANIM resource is known as a primitive which may be blended and/or sequenced with other primitives to assemble complex character animations (defined by ANCS and CHAR).

Each game has deviations in the format, but the principle of operation remains the same for all of them: