P3M

Format

  • Current version is 0.0
  • File extension is .p3m
  • Data is little endian
TypeDescription
"Header"File header
"Data"Model data

TypeValueDescription
char[3]{'P', '3', 'M'}Header magic
u80Major version
u8Header flagsFlags
Header flags
Bit (Listed from LSB to MSB)ValueDescription
1-80Reserved

Data

TypeValueDescription
u8Part count
u8[0..32]Part visibility bitmask (Bytes ordered from least to most significant)
"Part"[0...]Parts
u8Material count
"Material"[0...]Materials
u8Texture count
"Texture"[0...]Textures
u8Bone count
"Bone"[0...]Bones
u8Animation count
"Animation"[0...]Animations
u8Action count
"Action"[0...]Actions
char[1...]{..., 0}String table

Part

TypeValueDescription
u8Part flagsFlags
"String"Part name
u8Material index
u16Vertex count
"Vertex"[0...]Vertices
"Normal"[0...]Normals (only present if “Has normals” flag is set)
u16Index count
u16[0...]Indices
u8Weight group count
"Weight group"[0...]Weight groups
Part flags
Bit (Listed from LSB to MSB)ValueDescription
1Has normals
2-80Reserved

Vertex

TypeDescription
float[3]XYZ
float[2]UV

Normal

TypeDescription
float[3]XYZ

Weight group

TypeDescription
"String"Bone name
"Weight range"[0...]Weight data

Weight range

TypeDescription
u16Vertices to skip
u16Weight count (0 if last range)
u8[0...]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

TypeValueDescription
u8Material render modeRender mode
u8Texture index (255 for none)
u8[4]RGBA color
u8[3]RGB emission
u8Shading

Note: The ‘shading’ value determines how directional light is. The lower the value, the more light is evenly distributed.

Material render mode
NameValue
P3M_MATRENDMODE_NORMAL0
P3M_MATRENDMODE_ADD1

Texture

TypeValueDescription
u8Texture typeTexture type
{"Embedded texture"|"External texture"}[0...]Texture data
Texture type
NameValue
P3M_TEXTYPE_EMBEDDED0
P3M_TEXTYPE_EXTERNAL1

Embedded texture

TypeValueDescription
u32Data size
u8[...]PTF textureData

External texture

TypeDescription
"String"Resource path

Bone

TypeDescription
"String"Name
float[3]Head XYZ
float[3]Tail XYZ
u8Child count

Animation

TypeDescription
"String"Name
u8Action count
"Animation action"[0...]Action reference

Animation action

TypeDescription
u8Action index
floatSpeed multiplier
u16Start frame
u16End frame

Action

TypeValueDescription
u32Microseconds per frame
u8Action part list modePart list mode
u8Part list length
"String"[0...]Part list
u8Action data list length
"Action data"[0...]Action data
Action part list mode
NameValue
P3M_ACTPARTLISTMODE_DEFAULTWHITE0
P3M_ACTPARTLISTMODE_DEFAULTBLACK1
P3M_ACTPARTLISTMODE_WHITE2
P3M_ACTPARTLISTMODE_BLACK3

Note: The modes with “DEFAULT” in the name use the part visibility mask instead of starting with all or none.

Action data

TypeValueDescription
"String"Bone
u8Translation keyframe count
u8Rotation keyframe count
u8Scale keyframe count
u8[0...]Translation keyframe frame skips
u8[0...]Rotation keyframe frame skips
u8[0...]Scale keyframe frame skips
u8[0...]Action interpolation modeTranslation keyframe interpolation modes
u8[0...]Action interpolation modeRotation keyframe interpolation modes
u8[0...]Action interpolation modeScale keyframe interpolation modes
float[0...][3]Translation keyframes
float[0...][3]Rotation keyframes
float[0...][3]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
NameValue
P3M_ACTINTERP_NONE0
P3M_ACTINTERP_LINEAR1

String

TypeDescription
u16Offset in string table