Tiny3D - 3D Model (T3DM)

August 3, 2025 ยท View on GitHub

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.

Streaming-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).

OffsetTypeDescription
0x00char[4]Magic (T3M + version)
0x04u32Chunk count
0x08u16Total vertex count
0x0Au16Total index count
0x0Cu32First Vertex-chunk index
0x10u32First Indices-chunk index
0x14u32First Material-chunk index
0x18u32String table offset (in bytes)
0x1Cvoid*Block, only set by users
0x20s16[3]AABB min (model space)
0x26s16[3]AABB max (model space)
0x2CChunkOffset[]Chunk offsets/types

ChunkOffset

OffsetTypeDescription
0x00charType (e.g. M)
0x01u24Offset relative to file start

Chunks

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).

Vertices (V)

Vertex buffer, this is a shared buffer across all model/parts.
This chunk must only appear once.

OffsetTypeDescription
0x00Vertex[]Vertices, no size is stored

Vertex

Interleaved data for two vertices.

OffsetTypeDescription
0x00int16[3]Position A (16.0 fixed point)
0x06u16Normal A (5.6.5 packed)
0x08int16[3]Position B (16.0 fixed point)
0x0Eu16Normal B (5.6.5 packed)
0x10u32RGBA A (RGBA8 color)
0x14u32RGBA B (RGBA8 color)
0x18int16[2]UV A (pixel coords)
0x1Cint16[2]UV B (pixel coords)

Indices (I)

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.

OffsetTypeDescription
0x00u8[] / u16[]Local Indices, no size is stored

Material (M)

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.

OffsetTypeDescription
0x00u64Color-Combiner
0x08u64Other-mode values
0x10u64Other-mode mask
0x18u32Blend Mode, 0 for none
0x1Cu32T3D Draw flags
0x20u8
0x21u8 (FogMode)Fog mode
0x22u8Color flags (prim, env, blend)
0x23u8 (VertexFX)Vertex Effect
0x24u8[4]Prim-Color
0x28u8[4]Env-Color
0x2Cu8[4]Blend-Color
0x30u32Material name (string table offset)
0x34T3DMaterialTextureTexture A
0x60T3DMaterialTextureTexture B

T3DMaterialTexture

Each material has two texture slots, which may or may not be filled with a texture.

OffsetTypeDescription
0x00u32Texture reference (offscreen)
0x04u32Texture path offset
0x08u32Texture hash / ID
0x0Cu32Runtime texture pointer (0)
0x10u16Texture width
0x12u16Texture height
0x14T3DMaterialAxis[2]Setting per UV axis

T3DMaterialAxis

Each texture can have settings for each UV axis (aka tile settings)

OffsetTypeDescription
0x00f32Low
0x04f32High
0x08s8Mask
0x09s8Shift
0x0Au8Mirror
0x0Bu8Clamp

FogMode

0 - Default (no change applied)
1 - Fog Disabled
2 - Fog Active

VertexFX

0 - None
1 - Spherical

Object (O)

Model data consisting of multiple parts, can exist multiple times in a file.

OffsetTypeDescription
0x00u32Name
0x04u16Part count
0x06u16Triangle count
0x08u32Material, chunk index
0x0Cvoid*Block
0x10u8visible flag
0x11u8[3]padding
0x14s16[3]AABB min (XYZ)
0x1As16[3]AABB max (XYZ)
0x20Part[]Parts

Part

Model part data.

OffsetTypeDescription
0x00u32Vertex src. offset
0x04u16Vertex count
0x06u16Vertex dest. offset
0x08u32Index offset
0x0Au16Triangle Index count
0x0Cu16Matrix index, 0xFFFF for none
0x10u8[4]Strip Index count
0x14u8Index Sequence base index
0x15u8Index Sequence count (0=none)
0x16u8[2]padding

Skeleton (S)

Contains a tree of bones, used for skeletal animation.

OffsetTypeDescription
0x00u16Bone count
0x04u16reserved
0x08T3DBone[]List of bones

T3DBone

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.

OffsetTypeDescription
0x00u32Name
0x04u16Parent index
0x06u16Depth / Level
0x08f32[3]Scale
0x14f32[4]Rotation (Quat, XYZW)
0x24f32[3]Translation

Animation (A)

Contains a single animation with one or more channels.
Each animation then contains a list of keyframe changing the state of a channel.

OffsetTypeDescription
0x00char*Name, offset into string table
0x04f32Duration (seconds)
0x08u32Keyframe count
0x0Cu16Quaternion Channel count
0x0Eu16Scalar Channel count
0x10char*sdata path (offset into string table)
0x14ChannelMapping[]Maps channel to targets

ChannelMapping

Array of channels that define the connection to the data to be modified.
They are sorted so that all rotation channels come first.

OffsetTypeDescription
0x00u16Target index
0x02u8Target Type
0x03u8Attribute index (0-2 for x/y/z, 0 for quat.)
0x04f32Quantization scale
0x08f32Quantization offset

Target Type

0 = Translation
1 = Scale (XYZ)
2 = Scale (uniform)
3 = Rotation (quaternion)

To drive arbitrary values, Translation should be used as a default.

Data

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.

Keyframe
OffsetTypeDescription
0x00u16Time till next KF in ticks, MSB sets type of next KF
0x01u16Channel Index
0x02u16[]Data, on u16 for scalars, two u16 for rotation

Mesh BVH (B)

Binary tree of bounding boxes, optional.

OffsetTypeDescription
0x00u32Base pointer for data (set at runtime)
0x04u16Node count
0x06u16Data count
0x08BVHNode[]Nodes
0x??u16[]Data array

BVHNode

OffsetTypeDescription
0x00s16[3]AABB min (model space)
0x06s16[3]AABB max (model space)
0x0Cu1612-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.

String Table

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.