Difference between revisions of "FSKA (File Format)"

From MK8
Jump to navigation Jump to search
m (Moving this to the BFRES (File Format) page)
 
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{Under-construction}}
+
The '''FSKA''' (ca'''F'''e '''SK'''eletal '''A'''nimation) subfile stores animations which control how to transform bones of a model over time. It appears as a subfile of a '''[[BFRES (File Format)|BFRES file]]''' in the '''2nd''' [[index group]].
The '''FSKA''' subfile stores animations which control how to transform bones of a model over time. It appears as a subfile of a '''[[BFRES (File Format)|BFRES file]]''' in the '''2:nd''' [[index group]]. Unless otherwise noted, all offsets in the file are relative to themselves.
+
 
 +
__TOC__
 +
 
 +
= Format =
 +
 
 +
An '''FSKA file''' begins with an '''FSKA header'''. This is then followed by a number of sections pointed to by the header, many of which can occur multiple times. The purpose of these sections is described in the table below.
 +
 
 +
'''FSKA''' shares many similarities with the '''[[FSHU]]''', '''[[FTXP]]''', '''[[FVIS]]''', '''[[FSHA]]''' and '''[[FSCN]]''' subfiles, which mostly only differ in the structure describing what is changed by animations over time, but reusing the same animation curve and key structures, and even headers being very similar to one another.
  
 
== Header (FSKA) ==
 
== Header (FSKA) ==
An FSKA file begins with an 0x24 byte header that starts with the file identifier, followed by info about the image.
+
 
 +
Every FSKA begins with an 0x30 byte '''FSKA header'''.
  
 
{|class="wikitable"
 
{|class="wikitable"
 
|-
 
|-
! Offset !! Type !! Description
+
! Offset !! Size !! Type !! Description
 
|-
 
|-
| 0x00 || String || '''File magic'''. Always ''FSKA'' in ASCII.
+
| 0x00 || 4 || Char[4] || "'''FSKA'''" file identifier, ASCII string.
 
|-
 
|-
| 0x04 || Int32 || '''Filename''' offset. The name of this file.
+
| 0x04 || 4 || Int32 || '''File name''' offset (without file extension).
 
|-
 
|-
| 0x08 || Int32 || End of '''[[BFRES#String Table|String table]]''' offset.
+
| 0x08 || 4 || Int32 || '''File path''' offset, the path of the file this data was originally created from. Stripped in [[Mario Kart 8]] files, always pointing to an empty string at the end of the BFRES [[BFRES (File Format)#String Table|string table]].
 
|-
 
|-
| 0x0C || UInt32 || '''Unknown''' (possibly flags, as in other subfiles).
+
| 0x0C || 4 || UInt32 || '''Flags'''. Set of bits controlling how data is stored, packed as '''xxxxxxxx xxxxxxxx xxxRxxSS xxxxxPxC'''.
|- bgcolor="#AFA"
+
* '''C''' determines whether curves are baked.
| colspan="3" align="center" | '''if BFRES version >= 3.4.0'''
+
* '''P''' controls whether the animation is looping.
|- bgcolor="#DFD"
+
* '''SS''' controls how to perform scaling:
| 0x10 || UInt32 || '''Frame count'''.
+
{| class="wikitable"
|- bgcolor="#DFD"
+
! Value !! Description
| 0x14 || UInt16 || '''[[#Bone|Bone]] count'''.
+
|-
|- bgcolor="#DFD"
+
| 0 || No scaling
| 0x16 || UInt16 || '''Unknown''', possibly padding.
 
|- bgcolor="#FAA"
 
| colspan="3" align="center" | '''else'''
 
|- bgcolor="#FDD"
 
| 0x10 || UInt16 || '''Frame count'''.
 
|- bgcolor="#FDD"
 
| 0x12 || UInt16 || '''[[#Bone|Bone]] count'''.
 
|- bgcolor="#FDD"
 
| 0x14 || UInt32 || '''Unknown''', possibly padding.
 
 
|-
 
|-
| 0x18 || UInt32 || '''Unknown'''.
+
| 1 || Standard scaling
 
|-
 
|-
| 0x1C || UInt32 || '''Unknown'''.
+
| 2 || Maya scaling
 
|-
 
|-
| 0x20 || Int32 || '''[[#Bone|Bone]]''' array offset.
+
| 3 || Softimage scaling
 
|}
 
|}
 
+
* '''R''' controls the rotation mode, either euler XYZ rotation (bit set) or quaternion (bit unset).
After this follows something like a UInt16 array of unknown length (around 38 to 42 elements), each mostly having values 0x0000 or 0xFFFF. It might be possible the first ones are an offset to user data like in other subfile formats.
+
|- bgcolor="#AAFFAA"
 
+
| colspan="4" align="center" | '''if BFRES version >= 3.4.0.0'''
== Bone ==
+
|- bgcolor="#DDFFDD"
This section describes how a bone of the model has to be transformed over time. It appears in an array of bones following and referenced by the header.
+
| 0x10 || 4 || UInt32 || '''Frame count'''.
 
+
|- bgcolor="#DDFFDD"
{|class="wikitable"
+
| 0x14 || 2 || UInt16 || '''[[#Bone Animation|Bone Animation]] count'''.
 +
|- bgcolor="#DDFFDD"
 +
| 0x16 || 2 || UInt16 || '''[[User Data]] entry count'''.
 +
|- bgcolor="#FFAAAA"
 +
| colspan="4" align="center" | '''else'''
 +
|- bgcolor="#FFDDDD"
 +
| 0x10 || 2 || UInt16 || '''Frame count'''.
 +
|- bgcolor="#FFDDDD"
 +
| 0x12 || 2 || UInt16 || '''[[#Bone Animation|Bone Animation]] count'''.
 +
|- bgcolor="#FFDDDD"
 +
| 0x14 || 2 || UInt16 || '''[[User Data]] entry count'''.
 +
|- bgcolor="#FFDDDD"
 +
| 0x16 || 2 || — || Padding.
 
|-
 
|-
! Offset !! Type !! Description
+
| 0x18 || 4 || UInt32 || '''[[#Curve|Curve]] count''', the total number of Curve structures in all Material Animations.
 
|-
 
|-
| 0x00 || UInt32 || '''Unknown'''.
+
| 0x1C || 4 || UInt32 || '''Baked length'''.
 
|-
 
|-
| 0x04 || Int32 || '''Bone name offset''' of the bone to be transformed.
+
| 0x20 || 4 || Int32 || '''[[#Bone Animation|Bone Animation]]''' array offset.
 
|-
 
|-
| 0x08 || UInt16 || '''Unknown'''.
+
| 0x24 || 4 || Int32 || '''[[FMDL#FSKL|Skeleton]]''' offset. Points to the affected FSKL skeleton structure.
 
|-
 
|-
| 0x0A || Byte || '''[[#Track|Track]]''' count. Might be 0 if the bone is not changed at all.
+
| 0x28 || 4 || Int32 || '''[[#Bind Indices|Bind index]] array''' offset.
 
|-
 
|-
| 0x0B || Byte || '''Unknown''', possibly padding.
+
| 0x2C || 4 || Int32 || '''[[User Data]] [[index group]]''' offset.
 
|-
 
|-
| 0x0C || UInt32 || '''Unknown'''.
+
| 0x30 || colspan="3" {{Unknown|End of FSKA header}}
|-
 
| 0x10 || Int32 || '''[[#Track|Track]]''' array offset.
 
|-
 
| 0x14 || Int32 || '''[[#Base Transform|Base transform]]''' structure offset.
 
 
|}
 
|}
  
== Base Transform ==
+
=== Bind Indices ===
This structure stores how a bone is transformed in its initial state, and is referenced by each Bone section once.
+
The header points to an array of UInt16 elements with as many elements as specified in ''Bone Animation count''. It holds indices to bones, but an index can be 0xFFFF to reference no bone. The exact purpose of this array is unknown.
 +
The end of the array is aligned to 4 bytes.
  
{|class="wikitable"
+
== Bone Animation ==
 +
The header points to an array of Bone Animation structures with as many elements as specified in ''Bone Animation count'', each of 0x18 bytes size.
 +
 
 +
{| class="wikitable"
 +
|-
 +
! Offset !! Size !! Type !! Description
 
|-
 
|-
! Offset !! Type !! Description
+
| 0x00 || 4 || UInt32 || '''Flags'''. Sets of bits packed as '''xxxxSSSS Sxxxxxxx CCCCCCCC CCBBBxxx''' determining if initial transformational values exist.
 +
* '''BBB''' are combinable flags determining if data is available in the Bone Animation Data to animate specific transformations:
 +
{| class="wikitable"
 +
! Value !! Data Type
 
|-
 
|-
| 0x00 || Single[3] || '''Scale Vector''' 3 floats. The amount to scale the bone by.
+
| 1 || Scaling, a 3-component Single vector
 
|-
 
|-
| 0x0C || Single[4] || '''Rotation Vector''', normally stored as euler rotation (X, Y, Z in radians) but it can be stored as a quaternion. The last float is not used by euler rotation and is therefore set to 1f.
+
| 2 || Rotate, a 4-component Single vector, storing an euler XYZ (last component unused) or quaternion rotation.
 
|-
 
|-
| 0x1C || Single[3] || '''Translation Vector''' 3 floats. The amount to translate the bone by.
+
| 4 || Translate, a 3-component Single vector
 
|}
 
|}
 
+
* '''CC CCCCCCCC''' are combinable flags apparently describing what kind of Curves are available.
== Track ==
+
{| class="wikitable"
This section controls how a specific transformation is applied on a bone over time. Tracks are referenced in an array by the Bone section; there might be no tracks if the bone will not be animated.
+
! Value !! Description
 
+
|-
{|class="wikitable"
+
| 1 || Scale X
 +
|-
 +
| 2 || Scale Y
 +
|-
 +
| 4 || Scale Z
 +
|-
 +
| 8 || Rotate X
 
|-
 
|-
! Offset !! Type !! Description
+
| 16 || Rotate Y
 
|-
 
|-
| 0x00 || UInt16 || '''Data type''' of the key frames and key data array.
+
| 32 || Rotate Z
 
|-
 
|-
| 0x02 || UInt16 || '''Key''' count.
+
| 64 || Translate X
 
|-
 
|-
| 0x04 || UInt32 || '''Animation type'''.
+
| 128 || Translate Y
{|class="wikitable"
 
 
|-
 
|-
 +
| 256 || Translate Z
 +
|}
 +
* '''S SSSS''' are additional combinable flags which apparently describe how bones affect transformations.
 +
{| class="wikitable"
 
! Value !! Description
 
! Value !! Description
 
|-
 
|-
| 0x04 || X Scale
+
| 1 || Segment Scale Compensate
 +
|-
 +
| 2 || Scale Uniform
 +
|-
 +
| 4 || Scale Volume One
 
|-
 
|-
| 0x08 || Y Scale
+
| 6 (2 + 4) || Scale One
 
|-
 
|-
| 0x0C || Z Scale
+
| 8 || Rotate Zero
 
|-
 
|-
| 0x10 || X Translate
+
| 16 || Translate Zero
 
|-
 
|-
| 0x14 || Y Translate
+
| 24 (8 + 16) || Rotate Translate Zero
 
|-
 
|-
| 0x18 || Z Translate
+
| 30 (2 + 4 + 8 + 16) || Identity
 +
|}
 
|-
 
|-
| 0x20 || X Rotate
+
| 0x04 || 4 || Int32 || '''Bone name''' offset of the bone to be transformed.
 
|-
 
|-
| 0x24 || Y Rotate
+
| 0x08 || 1 || Byte || '''Start rotation''', exact purpose unknown.
 
|-
 
|-
| 0x28 || Z Rotate
+
| 0x09 || 1 || Byte || '''Start translation''', exact purpose unknown.
|}
 
 
|-
 
|-
| 0x08 || UInt32 || '''Unknown'''.
+
| 0x0A || 1 || Byte || '''[[#Curve|Curve]]''' count.
 
|-
 
|-
| 0x0C || Single || Number of '''frames''' the animation plays.
+
| 0x0B || 1 || Byte || '''Base [[#Bone Animation Data|Bone Animation Data]] translate offset''', an offset into the base Bone Animation Data structure to retrieve the initial bone translation for resetting it.
 
|-
 
|-
| 0x10 || Single || '''Data value scale''', a factor to scale the data values with.
+
| 0x0C || 1 || Byte || '''Start [[#Curve|Curve]]''' index, relative to the whole FSKA subfile (an array where all Bone Animation Curves would be stored together, in the order of which they appear in the subfile).
 
|-
 
|-
| 0x14 || Single || '''Data value init''', an initial value to offset the data values with.
+
| 0x0D || 3 || — || Padding.
|- bgcolor="#AFA"
 
| colspan="3" align="center" | '''if BFRES version >= 3.4.0'''
 
|- bgcolor="#DFD"
 
| 0x18 || Single || '''Unknown'''.
 
|- bgcolor="#DFD"
 
| 0x1C || Int32 || '''[[#Key Frames|Key frames]]''' array offset.
 
|- bgcolor="#DFD"
 
| 0x20 || Int32 || '''[[#Key Data|Key data]]''' array offset.
 
|- bgcolor="#FAA"
 
| colspan="3" align="center" | '''else'''
 
|- bgcolor="#FDD"
 
| 0x18 || Int32 || '''[[#Key Frames|Key frames]]''' array offset.
 
|- bgcolor="#FDD"
 
| 0x1C || Int32 || '''[[#Key Data|Key data]]''' array offset.
 
|}
 
 
 
=== Key Frames ===
 
 
 
The key frame array is of length and element type given by the header:
 
{|class="wikitable"
 
 
|-
 
|-
! Data Types !! Key Frame Element Type
+
| 0x10 || 4 || Int32 || '''[[#Curve|Curve]] array''' offset.
 
|-
 
|-
| 0x02, 0x05, 0x06, 0x09, 0x0A || UInt16 >> 5
+
| 0x14 || 4 || Int32 || '''Base [[#Bone Animation Data|Bone Animation Data]]''' offset, storing the initial state of the bone.
 
|-
 
|-
| else || Byte
+
| 0x18 || colspan="3" {{Unknown|End of Bone Animation}}
 
|}
 
|}
The resulting values of the elements specify the frame at which the key with the same index in the key data array is placed.
 
  
=== Key Data ===
+
=== Bone Animation Data ===
 +
 
 +
The Bone Animation header points to an array of float values, which have to be interpreted as 3- or 4-component vectors. Only the elements appearing in the ''Flags'' are stored, in the order as follows. The Curve target type is an offset into this structure to animate the corresponding field.
  
Each key in the key array consists of 4 unknown values of different type dependent upon the data type specified in the header:
+
{| class="wikitable"
{|class="wikitable"
 
 
|-
 
|-
! Data Types !! Key Data Element Type
+
! Size !! Type !! Description
 
|-
 
|-
| 0x02 || Single
+
| 12 || Single[3] || '''Scaling'''.
 
|-
 
|-
| 0x05 || Int16
+
| 16 || Single[4] || '''Rotation''', either euler XYZ or quaternion as specified in the header ''Flags''.
 
|-
 
|-
| 0x06 || Int16
+
| 12 || Single[3] || '''Translation'''.
 
|-
 
|-
| 0x09, 0x0A || Byte
+
| colspan="3" {{Unknown|End of Bone Animation Data}}
 
|}
 
|}
  
= Tools =
+
{{NW4FCurve}}
The following tools can handle FSKA files:
 
* [https://github.com/Ploaj/ModelThingy ModelThingy], by [https://github.com/Ploaj Ploaj] (can animate models)
 
  
 
[[Category:File Format]]
 
[[Category:File Format]]

Latest revision as of 19:19, 19 July 2017

The FSKA (caFe SKeletal Animation) subfile stores animations which control how to transform bones of a model over time. It appears as a subfile of a BFRES file in the 2nd index group.

Format

An FSKA file begins with an FSKA header. This is then followed by a number of sections pointed to by the header, many of which can occur multiple times. The purpose of these sections is described in the table below.

FSKA shares many similarities with the FSHU, FTXP, FVIS, FSHA and FSCN subfiles, which mostly only differ in the structure describing what is changed by animations over time, but reusing the same animation curve and key structures, and even headers being very similar to one another.

Header (FSKA)

Every FSKA begins with an 0x30 byte FSKA header.

Offset Size Type Description
0x00 4 Char[4] "FSKA" file identifier, ASCII string.
0x04 4 Int32 File name offset (without file extension).
0x08 4 Int32 File path offset, the path of the file this data was originally created from. Stripped in Mario Kart 8 files, always pointing to an empty string at the end of the BFRES string table.
0x0C 4 UInt32 Flags. Set of bits controlling how data is stored, packed as xxxxxxxx xxxxxxxx xxxRxxSS xxxxxPxC.
  • C determines whether curves are baked.
  • P controls whether the animation is looping.
  • SS controls how to perform scaling:
Value Description
0 No scaling
1 Standard scaling
2 Maya scaling
3 Softimage scaling
  • R controls the rotation mode, either euler XYZ rotation (bit set) or quaternion (bit unset).
if BFRES version >= 3.4.0.0
0x10 4 UInt32 Frame count.
0x14 2 UInt16 Bone Animation count.
0x16 2 UInt16 User Data entry count.
else
0x10 2 UInt16 Frame count.
0x12 2 UInt16 Bone Animation count.
0x14 2 UInt16 User Data entry count.
0x16 2 Padding.
0x18 4 UInt32 Curve count, the total number of Curve structures in all Material Animations.
0x1C 4 UInt32 Baked length.
0x20 4 Int32 Bone Animation array offset.
0x24 4 Int32 Skeleton offset. Points to the affected FSKL skeleton structure.
0x28 4 Int32 Bind index array offset.
0x2C 4 Int32 User Data index group offset.
0x30 End of FSKA header

Bind Indices

The header points to an array of UInt16 elements with as many elements as specified in Bone Animation count. It holds indices to bones, but an index can be 0xFFFF to reference no bone. The exact purpose of this array is unknown. The end of the array is aligned to 4 bytes.

Bone Animation

The header points to an array of Bone Animation structures with as many elements as specified in Bone Animation count, each of 0x18 bytes size.

Offset Size Type Description
0x00 4 UInt32 Flags. Sets of bits packed as xxxxSSSS Sxxxxxxx CCCCCCCC CCBBBxxx determining if initial transformational values exist.
  • BBB are combinable flags determining if data is available in the Bone Animation Data to animate specific transformations:
Value Data Type
1 Scaling, a 3-component Single vector
2 Rotate, a 4-component Single vector, storing an euler XYZ (last component unused) or quaternion rotation.
4 Translate, a 3-component Single vector
  • CC CCCCCCCC are combinable flags apparently describing what kind of Curves are available.
Value Description
1 Scale X
2 Scale Y
4 Scale Z
8 Rotate X
16 Rotate Y
32 Rotate Z
64 Translate X
128 Translate Y
256 Translate Z
  • S SSSS are additional combinable flags which apparently describe how bones affect transformations.
Value Description
1 Segment Scale Compensate
2 Scale Uniform
4 Scale Volume One
6 (2 + 4) Scale One
8 Rotate Zero
16 Translate Zero
24 (8 + 16) Rotate Translate Zero
30 (2 + 4 + 8 + 16) Identity
0x04 4 Int32 Bone name offset of the bone to be transformed.
0x08 1 Byte Start rotation, exact purpose unknown.
0x09 1 Byte Start translation, exact purpose unknown.
0x0A 1 Byte Curve count.
0x0B 1 Byte Base Bone Animation Data translate offset, an offset into the base Bone Animation Data structure to retrieve the initial bone translation for resetting it.
0x0C 1 Byte Start Curve index, relative to the whole FSKA subfile (an array where all Bone Animation Curves would be stored together, in the order of which they appear in the subfile).
0x0D 3 Padding.
0x10 4 Int32 Curve array offset.
0x14 4 Int32 Base Bone Animation Data offset, storing the initial state of the bone.
0x18 End of Bone Animation

Bone Animation Data

The Bone Animation header points to an array of float values, which have to be interpreted as 3- or 4-component vectors. Only the elements appearing in the Flags are stored, in the order as follows. The Curve target type is an offset into this structure to animate the corresponding field.

Size Type Description
12 Single[3] Scaling.
16 Single[4] Rotation, either euler XYZ or quaternion as specified in the header Flags.
12 Single[3] Translation.
End of Bone Animation Data


Curve

Curves store how animations are performed over time and store the required keys and values for this. They appear in multiple animation subfiles, and their header is of 0x24 bytes size (for BFRES versions earlier than 3.4.0.0, they are of 0x20 bytes size).

Offset Size Type Description
0x00 2 UInt16 Flags. Sets of bits packed as xxxxxxxx xCCCKKFF.
  • FF determines the data type of frames in the Frame array.
Value Size Type
0 4 Single
1 2 16-bit fixed point value (1 bit sign, 10 bits integral and 5 bits fractional).
  • To convert to Single, use Float(x) / (1 << 5).
  • To retrieve from Single, use Round(x * (1 << 5))
2 1 Byte
  • KK determines the data type of keys in the Key array.
Value Size Type
0 4 Single
1 2 Int16
2 1 SByte
  • CCC determines what kind of curve data is stored, resulting in a different number of elements stored per Key. They are used to set the key values and control the interpolation from one key to the next.
Value Description Elements per Key
0 Cubic Single 4 (hermite interpolation)
1 Linear Single 2 (linear interpolation)
2 Baked Single 1 (no interpolation)
4 Step Integer 1 (no interpolation)
5 Baked Integer 1 (no interpolation)
6 Step Boolean 1 (no interpolation)
7 Baked Boolean 1 (no interpolation)
0x02 2 UInt16 Key count.
0x04 4 UInt32 Target Offset, an offset in bytes into the corresponding Animation Data structure to animate the field at that relative address.
0x08 4 Single Start frame, the first frame at which a key is placed.
0x0C 4 Single End frame, the last frame at which a key is placed.
0x10 4 Int32 / Single Data scale, multiplier to the raw key values to get the final result. Together with Data offset, it is chosen carefully to consider an optimal granularity between the stored values.
0x14 4 Single Data offset, added to the raw values (after multiplying them with Data scale) to get the final key value.
if BFRES version >= 3.4.0.0
0x18 4 Single Data delta, stores the difference between the first and last key value.
0x1C 4 Int32 Frame array offset.
0x20 4 Int32 Key array offset.
0x24 End of Curve
else
0x18 4 Int32 Frame array offset.
0x1C 4 Int32 Key array offset.
0x20 End of Curve

Frames

The Curve header points to a Frame array which stores values controlling at which frame a Key from the Key array is placed. Thus, the array has as many elements as specified in Key count. The data type of the frames is given in the Curve's Flags.

The end of the array is aligned to 4 bytes.

Keys

The Curve header points to a Key array which stores the key values and additional values to interpolate the curve from one point to the next. Thus, the array has as many elements as specified in Key count, multiplied by the number of elements stored per key (depending upon the CCC Curve Type bits in the Curve Flags as described above). The data type of each element is given by the KK Key Type bits in the Curve Flags.

The end of the array is aligned to 4 bytes.

Step Curves

The elements apparently represent the key values directly.

Linear Curves

For linearly interpolated curves, 2 elements are stored per key:

  1. Value at which the key is set. To get the final value, scale and then offset it.
  2. Delta to value at next frame to which the curve linearly runs. To get the final value, scale it. If there is no next frame, this is always 0.

A key can be discarded by the next key if that one is stored at the same frame. In that case, only the value of the next key is stored, and the delta of the previous key is adjusted to run to the value of the now discarded key.

This example curve's keys are stored as SByte elements. The curve scale was computed as 2, the offset as 200 and the curve delta (if available in the BFRES version) as 300. Due to the lower key in frame 20 being discarded in favor of the higher key, only 3 keys are stored in 6 elements as follows.

NW4FCurveExampleLinear.png
Point Array Index Raw Value *2 (Scale) +200 (Offset) Notes
0,0 0 -100 -200 0 Initial key with value 0.
(20,254) 1 127 254 - Delta to end value of initial key at next frame.
20,254 - - - - This key is discarded in favor of the next.
20,400 2 100 200 400 Overrides previous key.
(30,300) 3 -50 -100 - End value of overriding key at next frame.
30,300 4 50 100 300 Value of fourth (but third stored) key.
(end) 5 0 0 - Since no frame follows, always 0.


Hermite Curves

For hermite curves, 4 elements are stored for each key. It is unclear how to exactly interprete them to form the curve out of it.