PSA and PSK binary files contain the raw animation and mesh information used to import skeletal animation art into the Unreal Engine. The PSK file contains the mesh, bone influence indices and weights for each vertex, the bone names, bone hierarchy, and skeletal default pose.
In Mass Effect 3, PSK data is included inside PCC files and can be exported using PCC Editor 2. Exported PSK files may be viewed with blender, Maya, or 3DSMax; editing must be done with one of the latter two tools. This page will be concerned with the specifics of the PSK binary format.
File Structure[]
The PSK file is structured as a collection if header-data pairs, of which there are eight types: Head, Points, Wedges, Faces, Materials, Bones, Weights, and Additional UV maps.
Chunk Header
The Chunk Header contains information about its companion data chunk: id, type, size and count. There are eight possible IDs, corresponding to each of the eight mesh objects:
- ACTRHEAD: Does not contain a data pair.
- PNTS0000: Vertices.
- VTXW0000: Weighted edges (wedges).
- FACE0000: Triangle faces.
- MATT0000: Materials.
- REFSKELT: Bone structure.
- RAWWEIGHTS: Bone raw weights.
- EXTRAUVS#: Extra UV maps.
Each header is defined as a 32 byte struct:
Bytes | Type | Description |
---|---|---|
20 | String | Chunk ID |
4 | Int32 | Type Flag |
4 | Int32 | Data Size |
4 | Int32 | Data Count |
Head
The Head data chunk is defined by its header as having zero size and zero elements (count). It contains no information, thus it derives that only the header has useful meaning. The header chunk may act as a file-header, but does not necessarily have to be the first chunk in the file.
Points
The Points data chunk stores the vertices (points) of the mesh, arranged as an array of structs with the vertex coordinates.
Bytes | Type | Description |
---|---|---|
4 | Float | X |
4 | Float | Y |
4 | Float | Z |
Wedges
The Wedges data chunk stores weighted edge information. A wedge is a reference to a point with texture coordinates; in other words, the union of a three-dimensional vertex array and its texturing information. It defines a point over the index of points and combines it with a texture coordinate (U,V) and a material. Single points can be shared between different wedges (texture seams). The format of this structure depends on the edge count.
Count lower/equal than 65536d
Bytes | Type | Description |
---|---|---|
2 | Int16 | Point index |
2 | Int16 | Padding |
4 | Float | U |
4 | Float | V |
1 | Int8 | Material index |
1 | Int8 | Reserved |
2 | Int16 | Padding |
Count greater than 65536d
Bytes | Type | Description |
---|---|---|
4 | Int32 | Point index |
4 | Float | U |
4 | Float | V |
4 | Int32 | Material index |
Faces
The Faces data chunk stores the different mesh triangles. Each triangle is defined by a vector struct (3 vertices), filled with the texture of its assigned material and fit by the texture coordinate (U,V). All vectors contained inside a vector array. The data can be formatted as one of two possible structures: Unreal Engine format (FACE0000) or as a Umodel PSK extension (FACE0032).
FACE0000
Bytes | Type | Description |
---|---|---|
2 | Int16 | Wedge 0 |
2 | Int16 | Wedge 1 |
2 | Int16 | Wedge 2 |
1 | Int8 | Material index |
1 | Int8 | Auxiliary material index |
4 | Int32 | Smoothing groups |
FACE0032
This variant is used as replacement for FACE0000 section for meshes with more than 64 vertices. This is umodel's psk format extension, Unreal Engine has no support for FACE3200 chunks.
Bytes | Type | Description |
---|---|---|
4 | Int32 | Wedge 0 |
4 | Int32 | Wedge 1 |
4 | Int32 | Wedge 2 |
1 | Int8 | Material index |
1 | Int8 | Auxiliary material index |
4 | Int32 | Smoothing groups |
Materials
The Material chunk stores the materials used by the mesh:
Bytes | Type | Description |
---|---|---|
64 | String | Name |
4 | Int32 | Texture index |
4 | Int32 | Poly Flags |
4 | Int32 | Auxiliary material |
4 | Int32 | Auxiliary flags |
4 | Int32 | LOD bias |
4 | Int32 | LOD style |
Bones
The Bones chunk stores information about the bones' position, size, articulations, and structure:
Bytes | Type | Description |
---|---|---|
64 | String | Name |
4 | Int32 | Flags |
4 | Int32 | Children count |
4 | Int32 | Parent index |
4 | Float | Rotation X |
4 | Float | Rotation Y |
4 | Float | Rotation Z |
4 | Float | Rotation W |
4 | Float | Position X |
4 | Float | Position Y |
4 | Float | Position Z |
4 | Float | Length |
4 | Float | Size X |
4 | Float | Size Y |
4 | Float | Size Z |
Weights
The Weights chunk applies raw weighting to a vertex bone (bone <-> vertex connection with factor 0..1f) to allow the deforming of the mesh by the movement of bones and during the animation.
Bytes | Type | Description |
---|---|---|
4 | Float | Weight |
4 | Int32 | Point index |
4 | Int32 | Bone index |
Additonal UV Maps
Additionally, up to three Additional UV (AUV) maps may be stored for each wedge construct:
- EXTRAUVS0: as the second UV set
- EXTRAUVS1: as the third UV set
- EXTRAUVS2: as the fourth UV set
Each AUV type is stored in a separate table or list. The AUV count for each type must be then equal to the wedge count, so that wedge[ i ] gets the AUV[ i ] of each table/type. Because every material defines all textures, these will be accordingly applied to the coordinates defined by the base UV (defined by the wedge) and the AUV sets.
AUV sets are stored as 8 byte structs:
Bytes | Type | Description |
---|---|---|
4 | Float | U |
4 | Float | V |