Table of contents
- Current version is
0.0 - File extension is
.p3m - Data is little endian
| Type | Value | Description |
|---|
char[3] | {'P', '3', 'M'} | Header magic |
u8 | 0 | Major version |
u8 | Header flags | Flags |
| Bits (MSB to LSB) | Value | Description |
|---|
| 7..0 | 0 | Reserved |
Data
| Type | Value | Description |
|---|
u8 | – | Part count |
u8[0..32] | – | Part visibility bitmask (Bytes ordered from least to most significant) |
| Part × “Part count” | – | Parts |
u8 | – | Material count |
| Material × “Material count” | – | Materials |
u8 | – | Texture count |
| Texture × “Texture count” | – | Textures |
u8 | – | Bone count |
| Bone × “Bone count” | – | Bones |
u8 | – | Animation count |
| Animation × “Animation count” | – | Animations |
u8 | – | Action count |
| Action × “Action count” | – | Actions |
char[1...] | {..., 0} | String table |
Part
| Type | Value | Description |
|---|
u8 | Part flags | Flags |
| String | – | Part name |
u8 | – | Material index |
u16 | – | Vertex count |
| Vertex × “Vertex count” | – | Vertices |
| Normal × “Vertex count” or 0 | – | Normals (only present if “Has normals” flag is set) |
u16 | – | Index count |
u16 × “Index count” | – | Indices |
u8 | – | Weight group count |
| Weight group × “Weight group count” | – | Weight groups |
Part flags
| Bits (MSB to LSB) | Value | Description |
|---|
| 7..1 | 0 | Reserved |
| 0 | – | Has normals |
Vertex
| Type | Description |
|---|
float[3] | XYZ |
float[2] | UV |
Normal
| Type | Description |
|---|
float[3] | XYZ |
Weight group
| Type | Description |
|---|
| String | Bone name |
| Weight range × 1… | Weight data (terminated by a range with a “Weight count” of 0) |
Weight range
| Type | Description |
|---|
u16 | Vertices to skip |
u16 | Weight count (0 if last range) |
u8 × “Weight count” | Weights |
Note: Weights in Blender are stored as floats from 0.0 to 1.0. The P3M exporter multiplies each weight by 256 and rounds it. Weights with a value of 0 are omitted and the remaining non-zero weights are decremented by 1. To read in weights, add 1, then divide by 256.0.
Material
| Type | Value | Description |
|---|
u8 | Material render mode | Render mode |
u8 | – | Texture index (255 for none) |
u8[4] | – | RGBA color |
u8[3] | – | RGB emission |
u8 | – | Shading |
u8 | – | Shine |
u8 | – | Matcap texture index (255 for none) |
Note: The ‘shading’ value determines how directional light is. The lower the value, the more light is evenly distributed.
Material render mode
| Name | Value |
|---|
P3M_MATRENDMODE_NORMAL | 0 |
P3M_MATRENDMODE_ADD | 1 |
Texture
Texture type
| Name | Value |
|---|
P3M_TEXTYPE_EMBEDDED | 0 |
P3M_TEXTYPE_EXTERNAL | 1 |
Embedded texture
| Type | Value | Description |
|---|
u32 | – | Data size |
u8 × “Data size” | PTF texture | Data |
External texture
| Type | Description |
|---|
| String | Resource path |
Bone
| Type | Description |
|---|
| String | Name |
float[3] | Head XYZ |
float[3] | Tail XYZ |
u8 | Child count |
Animation
Animation action
| Type | Description |
|---|
u8 | Action index |
float | Speed multiplier |
u16 | Start frame |
u16 | End frame |
Action
| Type | Value | Description |
|---|
u32 | – | Microseconds per frame |
u8 | Action part list mode | Part list mode |
u8 | – | Part list length |
| String × “Part list length” | – | Part list |
u8 | – | Action data list length |
| Action data × “Action data list length” | – | Action data |
Action part list mode
| Name | Value |
|---|
P3M_ACTPARTLISTMODE_DEFAULTWHITE | 0 |
P3M_ACTPARTLISTMODE_DEFAULTBLACK | 1 |
P3M_ACTPARTLISTMODE_WHITE | 2 |
P3M_ACTPARTLISTMODE_BLACK | 3 |
Note: The modes with “DEFAULT” in the name use the part visibility mask instead of starting with all or none.
Action data
| Type | Value | Description |
|---|
| String | – | Bone |
u8 | – | Translation keyframe count |
u8 | – | Rotation keyframe count |
u8 | – | Scale keyframe count |
u8 × “Translation keyframe count” | – | Translation keyframe frame skips |
u8 × “Rotation keyframe count” | – | Rotation keyframe frame skips |
u8 × “Scale keyframe count” | – | Scale keyframe frame skips |
u8 × “Translation keyframe count” | Action interpolation mode | Translation keyframe interpolation modes |
u8 × “Rotation keyframe count” | Action interpolation mode | Rotation keyframe interpolation modes |
u8 × “Scale keyframe count” | Action interpolation mode | Scale keyframe interpolation modes |
float[3] × “Translation keyframe count” | – | XYZ translation keyframes |
float[3] × “Rotation keyframe count” | – | XYZ rotation keyframes |
float[3] × “Scale keyframe count” | – | XYZ scale keyframes |
Note: In Blender, a keyframe’s interpolation type is used to transition from that keyframe to the next. In P3M, a keyframe’s interpolation mode is used to transition from the previous keyframe to that keyframe. The P3M exporter will start with the interpolation mode from the last keyframe before the start of the action. If there are no keyframes before the start of the action, the exporter will start with ‘LINEAR’.
Action interpolation mode
| Name | Value |
|---|
P3M_ACTINTERP_NONE | 0 |
P3M_ACTINTERP_LINEAR | 1 |
String
| Type | Description |
|---|
u16 | Offset in string table |