All data is stored in binary in a chunk-based file.
It starts with a header containing the number of chunks and their offsets followed by the data.
A .t3dm
file can be accompanied by one or more streaming-data files (.t3ds
).
This file can be compressed and contains data to be streamed in during runtime (e.g. animations).
Offset | Type | Description |
---|---|---|
0x00 | char[4] |
Magic (T3M + version) |
0x04 | u32 |
Chunk count |
0x08 | u16 |
Total vertex count |
0x0A | u16 |
Total index count |
0x0C | u32 |
First Vertex-chunk index |
0x10 | u32 |
First Indices-chunk index |
0x14 | u32 |
First Material-chunk index |
0x18 | u32 |
String table offset (in bytes) |
0x1C | void* |
Block, only set by users |
0x20 | s16[3] |
AABB min (model space) |
0x26 | s16[3] |
AABB max (model space) |
0x2C | ChunkOffset[] |
Chunk offsets/types |
Offset | Type | Description |
---|---|---|
0x00 | char |
Type (e.g. M ) |
0x01 | u24 |
Offset relative to file start |
After the header the chunks are stored in the order of their offsets.
Chunks are sorted by type and may be aligned.
The first chunk type must be O
(Object).
Vertex buffer, this is a shared buffer across all model/parts.
This chunk must only appear once.
Offset | Type | Description |
---|---|---|
0x00 | Vertex[] |
Vertices, no size is stored |
Interleaved data for two vertices.
Offset | Type | Description |
---|---|---|
0x00 | int16[3] |
Position A (16.0 fixed point) |
0x06 | u16 |
Normal A (5.6.5 packed) |
0x08 | int16[3] |
Position B (16.0 fixed point) |
0x0E | u16 |
Normal B (5.6.5 packed) |
0x10 | u32 |
RGBA A (RGBA8 color) |
0x14 | u32 |
RGBA B (RGBA8 color) |
0x18 | int16[2] |
UV A (pixel coords) |
0x1C | int16[2] |
UV B (pixel coords) |
Index buffer, this is a shared buffer across all model/parts.
This will contain both 8 and 16 bit indices, depending on if used as triangles or triangle strips.
Since 16bit indices are DMA'd by the RSP, they are aligned to 8 bytes.
Offset | Type | Description |
---|---|---|
0x00 | u8[] / u16[] |
Local Indices, no size is stored |
Material data referenced by Objects.
Directly mapped to the struct T3DMaterial
.
Objects can have two materials assigned (with two textures),
only the first materials CC and draw flags are used.
Offset | Type | Description |
---|---|---|
0x00 | u64 |
Color-Combiner |
0x08 | u64 |
Other-mode values |
0x10 | u64 |
Other-mode mask |
0x18 | u32 |
Blend Mode, 0 for none |
0x1C | u32 |
T3D Draw flags |
0x20 | u8 |
|
0x21 | u8 (FogMode) |
Fog mode |
0x22 | u8 |
Color flags (prim, env, blend) |
0x23 | u8 (VertexFX) |
Vertex Effect |
0x24 | u8[4] |
Prim-Color |
0x28 | u8[4] |
Env-Color |
0x2C | u8[4] |
Blend-Color |
0x30 | u32 |
Material name (string table offset) |
0x34 | T3DMaterialTexture |
Texture A |
0x60 | T3DMaterialTexture |
Texture B |
Each material has two texture slots, which may or may not be filled with a texture.
Offset | Type | Description |
---|---|---|
0x00 | u32 |
Texture reference (offscreen) |
0x04 | u32 |
Texture path offset |
0x08 | u32 |
Texture hash / ID |
0x0C | u32 |
Runtime texture pointer (0 ) |
0x10 | u16 |
Texture width |
0x12 | u16 |
Texture height |
0x14 | T3DMaterialAxis[2] |
Setting per UV axis |
Each texture can have settings for each UV axis (aka tile settings)
Offset | Type | Description |
---|---|---|
0x00 | f32 |
Low |
0x04 | f32 |
High |
0x08 | s8 |
Mask |
0x09 | s8 |
Shift |
0x0A | u8 |
Mirror |
0x0B | u8 |
Clamp |
0 - Default (no change applied)
1 - Fog Disabled
2 - Fog Active
0 - None
1 - Spherical
Model data consisting of multiple parts, can exist multiple times in a file.
Offset | Type | Description |
---|---|---|
0x00 | u32 |
Name |
0x04 | u16 |
Part count |
0x06 | u16 |
Triangle count |
0x08 | u32 |
Material, chunk index |
0x0C | void* |
Block |
0x10 | u8 |
visible flag |
0x11 | u8[3] |
padding |
0x14 | s16[3] |
AABB min (XYZ) |
0x1A | s16[3] |
AABB max (XYZ) |
0x20 | Part[] |
Parts |
Model part data.
Offset | Type | Description |
---|---|---|
0x00 | u32 |
Vertex src. offset |
0x04 | u16 |
Vertex count |
0x06 | u16 |
Vertex dest. offset |
0x08 | u32 |
Index offset |
0x0A | u16 |
Triangle Index count |
0x0C | u16 |
Matrix index, 0xFFFF for none |
0x10 | u8[4] |
Strip Index count |
Contains a tree of bones, used for skeletal animation.
Offset | Type | Description |
---|---|---|
0x00 | u16 |
Bone count |
0x04 | u16 |
reserved |
0x08 | T3DBone[] |
List of bones |
Bone data, each bone references its parent by index.
The list is sorted by index, so index references are guaranteed to be parsed before the bone itself.
Offset | Type | Description |
---|---|---|
0x00 | u32 |
Name |
0x04 | u16 |
Parent index |
0x06 | u16 |
Depth / Level |
0x08 | f32[3] |
Scale |
0x14 | f32[4] |
Rotation (Quat, XYZW) |
0x24 | f32[3] |
Translation |
Contains a single animation with one or more channels.
Each animation then contains a list of keyframe changing the state of a channel.
Offset | Type | Description |
---|---|---|
0x00 | char* |
Name, offset into string table |
0x04 | f32 |
Duration (seconds) |
0x08 | u32 |
Keyframe count |
0x0C | u16 |
Quaternion Channel count |
0x0E | u16 |
Scalar Channel count |
0x10 | char* |
sdata path (offset into string table) |
0x14 | ChannelMapping[] |
Maps channel to targets |
Array of channels that define the connection to the data to be modified.
They are sorted so that all rotation channels come first.
Offset | Type | Description |
---|---|---|
0x00 | u16 |
Target index |
0x02 | u8 |
Target Type |
0x03 | u8 |
Attribute index (0-2 for x/y/z, 0 for quat.) |
0x04 | f32 |
Quantization scale |
0x08 | f32 |
Quantization offset |
0 = Translation
1 = Scale (XYZ)
2 = Scale (uniform)
3 = Rotation (quaternion)
To drive arbitrary values, Translation
should be used as a default.
The actual data is stored in the streaming file.
It is referenced by the data-offsets in the page.
To know how large the next keyframe is, the MSB is used to encode size.
0
means scalar (2 data bytes), 1
means rotation (4 data bytes).
The initial KF has always 4 bytes, to have a known start.
Offset | Type | Description |
---|---|---|
0x00 | u16 |
Time till next KF in ticks, MSB sets type of next KF |
0x01 | u16 |
Channel Index |
0x02 | u16[] |
Data, on u16 for scalars, two u16 for rotation |
Binary tree of bounding boxes, optional.
Offset | Type | Description |
---|---|---|
0x00 | u32 |
Base pointer for data (set at runtime) |
0x04 | u16 |
Node count |
0x06 | u16 |
Data count |
0x08 | BVHNode[] |
Nodes |
0x?? | u16[] |
Data array |
Offset | Type | Description |
---|---|---|
0x00 | s16[3] |
AABB min (model space) |
0x06 | s16[3] |
AABB max (model space) |
0x0C | u16 |
12-MSB index, 4-LSB data count |
If the data count is >0
, the node is a leaf node and the index points to the data array.
If the data count is 0
, the node is an inner node and the index points to the next 2 nodes.
At the end of the t3dm
file, after all chunk data, a string-table is stored.
This contains arbitrary strings used by the model, e.g. texture paths.
Values in there are referenced by a relative offset from the start of the string table.
All strings are zero-terminated.