KCL (File Format)/Wii
KCL files are collision files, which is the model the game runs collision against. KCL files has been used since at least Mario Kart DS, but this documentation is about the format used in Nintendo DS, Wii and Nintendo 3DS. The only differences is that Nintendo DS uses a specific format which replaces all floats. For other formats, see KCL (File Format).
KCL stores triangle in a format which allow fast access and collision calculation, and has an octree which splits the world space into many cubes, to make the game test collision on less triangles, which allows for much faster collision detection.
File Format
Header
The header is a 0x3C byte structure as follows:
Offset | Type | Description |
---|---|---|
0x00 | UInt32 | Offset to vertex positions, relative to the start of the file. |
0x04 | UInt32 | Offset to directional vectors, relative to the start of the file. |
0x08 | UInt32 | Offset to triangles - 0x10, relative to the start of the file. To get the actual offset, add 0x10 to this value. It works like this because the octree triangle indices are 1-based. |
0x0C | UInt32 | Offset to octree, relative to the start of the file. |
0x10 | Float | Unknown. Always 300. |
0x14 | Float[3] | Octree origin. |
0x20 | UInt32 | X mask. |
0x24 | UInt32 | Y mask. |
0x28 | UInt32 | Z mask. |
0x2C | UInt32 | Coordinate shift. |
0x30 | UInt32 | Y shift. |
0x34 | UInt32 | Z shift. |
0x38 | Float | Unknown. Always 250. |
Vertices
Section 1 is simply a large array of vertices, stored as 3 successive singles for x, y and z. The length of this array is not stored, but can usually be calculated by subtracting the section 1 offset from the section 2 offset and dividing by 0x0C.
Directional Vectors
Section 2 is much the same as section 1, in that it is a large array of directional vectors. Again the values are stored as 3 successive singles for x, y and z. The length of this array is not stored, but can usually be calculated by subtracting the section 2 offset from the section 3 offset and dividing by 0x0C.
Triangles
The third section is the section containing the actual model information. The structure of each entry in this section is a 0x10 byte structure given below.
Offset | Type | Description |
---|---|---|
0x00 | Float | Length of triangle. |
0x04 | UInt16 | The index of the first vertex position into the vertex array. |
0x06 | UInt16 | The index of the normal into the directional vector array. |
0x08 | UInt16 | The index of the direction A into the directional vector array. |
0x0A | UInt16 | The index of the direction B into the directional vector array. |
0x0C | UInt16 | The index of the direction C into the directional vector array. |
0x0E | UInt16 | Collision attributes. |
All indices in this section are 0 indexed. The position index is an index for section 1, and the others are indices to section 2. The exact manner in which the values are used for collision detection is unknown, however a method for converting this form of triangle to a set of three coordinates is outlined below. The coordinate system is right handed.
CrossA = Cross(DirectionA, Normal) CrossB = Cross(DirectionB, Normal) Vertex1 = Position Vertex2 = Position + CrossB * (Length / Dot(CrossB, DirectionC)) Vertex3 = Position + CrossA * (Length / Dot(CrossA, DirectionC))
A method for converting three vertices into the KCL form is given below. This method assumes the vertices are arranged anti clockwise when viewed from the collidable side.
Position = Vertex1 Direction = Normalize(Cross(Vertex2 - Vertex1, Vertex3 - Vertex1 )) DirectionA = Normalize(Cross(Normal, Vertex3 - Vertex1 )) DirectionB = Normalize(-Cross(Normal, Vertex2 - Vertex1 )) DirectionC = Normalize(Cross(Normal, Vertex2 - Vertex3 )) Length = Dot(Vertex2 - Vertex1, DirectionC )
Octree
The octree subdivides the world space into cubes, to allow much faster triangle collision detection. The number of root nodes can be calculated by the following algorithm:
NrRootNodes = (~MaskX >> CoordinateShift + 1) * (~MaskY >> CoordinateShift + 1) * (~MaskZ >> CoordinateShift + 1)
Then the number of root nodes are written to the file. These nodes link to more nodes or triangle lists.
Node
Each node has the following structure:
Offset | Type | Description |
---|---|---|
0x00 | UInt32 | Flag: ABBB BBBB BBBB BBBB BBBB BBBB BBBB BBBB
A: 1 means it's a leaf. See below. |
If the node is a leaf, then it means it isn't subdivided anymore and it contains triangle lists. This triangle list is terminated by 0, and contains 1-based indices of the triangles that are present in this subspace. If it's not a leaf, then this node is subdivided into 8 more nodes, which the offset into the structure links to.
Tools
The following tools can handle KCL files:
- Wexos's Toolbox, by Wexos (Wii)
- Wiimms SZS Tools, by Wiimm (Wii)