K3D is the native, binary format used by Kohi to store mesh shape, animation, and skeletal data. This document serves as a basic specification for the K3D format.
| Field Name | Bytes | Data Type | Description |
|---|---|---|---|
| Kohi Magic | 4 | u32 | Marks file as Kohi Asset. Value must be 0xDECAFBAD |
| Asset Type | 4 | u32 | Should match the enum value of KASSET_TYPE_MODEL |
| Version | 1 | u8 | The K3D asset version. |
| Exp. Type | 1 | u32 | Used to track the type of exporter used. 0x00000001 means imported via Kohi's importer toolchain. Ignored by the engine, mostly used for debugging purposes. |
| Exp. Ver. | 1 | u8 | Used to track version of the exporter used. Ignored by the engine, mostly used for debugging purposes. |
| Extents | 24 | extents_3d | The combined extents of all submeshes. |
| Center | 12 | vec3 | The center point of all submeshes. |
| Inverse Global Transform | 64 | mat4 | The inverse global transform matrix. |
| Submesh Count | 2 | u16 | Number of submeshes present. |
| Bone count | 2 | u16 | Number of bones present. |
| Node count | 2 | u16 | Number of nodes present. |
| Animation count | 2 | u16 | Number of animations present. |
| String table offset | 4 | u32 | Offset in bytes in the entire file where the string table begins. |
NOTE: This section should only exist if Submesh Count > 0.
| Field Name | Bytes | Data Type | Description |
|---|---|---|---|
| SUBMESHES BEGIN GUARD | 4 | u32 | Serves as a checkpoint to ensure the beginning of the submeshes section is where it belongs. Value should indicate section type = 0x00000001. |
| Name Ids | 2 * Submesh Count | u16* | An array of string ids of the names of the submeshes (length = Submesh Count). |
| Material Name Ids | 2 * Submesh Count | u16* | An array of string ids of the material names of the submeshes (length = Submesh Count). |
| Vertex Counts | 4 * Submesh Count | u32* | An array of counts of vertices per Submesh (length = Submesh Count). |
| Index Counts | 4 * Submesh Count | u32* | An array of counts of indices per Submesh (length = Submesh Count). |
| Mesh Types | 1 * Submesh Count | u8* | An array of types of vertex data for a submesh. I.e. 0 = vertex_3d format, 1 = skinned_vertex_3d format, etc. |
| Centers | 12 * Submesh Count | vec3* | An array of center positions per Submesh (length = Submesh Count). |
| Extents | 24 * Submesh Count | extents_3d* | An array of extents per Submesh (length = Submesh Count). |
| Vertex Data Buffer | 4 | f32* or i32* | A buffer of f32s that stores all vertex data for all submeshes, regardless of format. The overall size of this is determined by the vertex format of each submesh, how many vertices that submesh has, as well as how many submeshes there are. |
| Index Data Buffer | 4 | u32* | A buffer of u32s that stores all index data for all submeshes. The overall size of this is determined by the how many indices each submesh has, as well as how many submeshes there are. |
NOTE: This section should only exist if Bone Count > 0.
| Field Name | Bytes | Data Type | Description |
|---|---|---|---|
| BONES BEGIN GUARD | 4 | u32 | Serves as a checkpoint to ensure the beginning of the bones section is where it belongs. Value should indicate section type = 0x00000002. |
| Name Ids | 2 * Bone Count | u16* | An array of string ids of the names of the bones (length = Bone Count). |
| Offset Matrices | 64 * Bone Count | mat4* | An array of offset matrices of the bones (length = Bone Count). |
NOTE: This section should only exist if Node Count > 0.
| Field Name | Bytes | Data Type | Description |
|---|---|---|---|
| NODES BEGIN GUARD | 4 | u32 | Serves as a checkpoint to ensure the beginning of the nodes section is where it belongs. Value should indicate section type = 0x00000003. |
| Name Ids | 2 * Node Count | u16* | An array of string ids of the names of the nodes (length = Node Count). |
| Parent Indices | 2 * Node Count | u16* | An array of indices of parents of the nodes (length = Node Count). INVALID_ID_U16 = root node (no parent) |
| Local transforms | 64 * Node Count | mat4* | An array of local transform matrices of the nodes (length = Node Count). |
NOTE: This section should only exist if Animation Count > 0.
| Field Name | Bytes | Data Type | Description |
|---|---|---|---|
| ANIMATIONS BEGIN GUARD | 4 | u32 | Serves as a checkpoint to ensure the beginning of the animations section is where it belongs. Value should indicate section type = 0x00000004. |
| Total Channel Count | 2 | u16 | The total number of channels for all animations |
| Name Ids | 2 * Animation Count | u16* | An array of string ids of the names of the animations (length = Animation Count). |
| Durations | 4 * Animation Count | f32* | An array of durations of each animation (length = Animation Count). |
| Ticks Per Seconds | 4 * Animation Count | f32* | An array of ticks-per-second of each animation (length = Animation Count). |
| Channel Counts | 2 * Animation Count | u16* | An array of channel counts of each animation (length = Animation Count). |
NOTE: This section should only exist if Animation Count > 0 AND Total Channel Count > 0.
| Field Name | Bytes | Data Type | Description |
|---|---|---|---|
| ANIMATION CHANNELS BEGIN GUARD | 4 | u32 | Serves as a checkpoint to ensure the beginning of the animation channels section is where it belongs. Value should indicate section type = 0x00000005. |
| Channel Anim. Ids | 2 * Total Channel Count | u16* | An array of animation ids for each channel (length = Total Channel Count). Used to link a channel back to an animation. |
| Channel Name Ids | 2 * Total Channel Count | u16* | An array of string ids of the names of the animation channels (length = Total Channel Count). |
| Channel Position Counts | 4 * Total Channel Count | u32* | An array of position counts for each channel (length = Total Channel Count). |
| Channel Position Offsets | 4 * Total Channel Count | u32* | An offset into the positions array for each channel (length = Total Channel Count). |
| Channel Rotation Counts | 4 * Total Channel Count | u32* | An array of rotation counts for each channel (length = Total Channel Count). |
| Channel Rotation Offsets | 4 * Total Channel Count | u32* | An offset into the rotations array for each channel (length = Total Channel Count). |
| Channel Scale Counts | 4 * Total Channel Count | u32* | An array of scale counts for each channel (length = Total Channel Count). |
| Channel Scale Offsets | 4 * Total Channel Count | u32* | An offset into the scales array for each channel (length = Total Channel Count). |
| Channel Data Buffer | 4 | f32* | A buffer of f32s that stores all position/rotation/scale data for all animation channels. The overall size of this is determined by the how many keys each channel has, as well as how many channels there are. Bytes extracted from this vary by the type of key data being extracted (i.e a key_vec3 extracts 4 f32s whereas a key_quat extracts 5. Each channel is stored in the order of position, rotation, then scale. |
| Field Name | Bytes | Data Type | Description |
|---|---|---|---|
| STRINGS BEGIN GUARD | 4 | u32 | Serves as a checkpoint to ensure the beginning of the strings section is where it belongs. Value should indicate section type = 0x00000006. |
NOTE: Strings are handled by a binary_string_table that is serialized into one large block of memory and is appended to the end of the file.