M3

From wowdev
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

M3 files contain model objects. They are the next iteration over the original M2 file. Each M3 file describes the mesh data of an object, as well as collision mesh data, and other information. Material data is stored in separate files, and they required in order to render the model correctly. Unlike their predecessor M2, M3 files have a fully chunked format similar to WMO files. And also they are no longer split into Skin and Lod Skin files. All of the vertex and geoset data is stored in a single file.

The first M3 file was introduced in The War Within expansion, with the file ID 5569152.

Details on how to read them are described below.

Each chunk is made out of a chunk header that is 16 bytes long, with the exception of the collision mesh subchunks which are only 8 bytes long, as they don't include the property fields. The chunk header is followed by the chunk data. The chunk data is a sequence of bytes that is interpreted based on the chunk ID.

The chunk header contains the following fields:

struct 
{
 /*0x000*/  uint32_t chunkID;      // The ID of the chunk, used to identify the type of data stored in the chunk.
 /*0x004*/  uint32_t chunkSize;    // The size of the chunk data, in bytes. This excludes the size of the chunk header.
 /*0x008*/  uint32_t propertyA;    // A property field that is used to store additional information about the chunk.
 /*0x010*/  uint32_t propertyB;    // A second property field that is used to store additional information about the chunk.
                                   // The meaning of these fields is dependent on the chunk type, but generally they indicate a count of elements in the chunk.
                                   // They may not always be used, and just have 0 assigned to them.
};

Each chunk header is followed by the chunk data. The chunk data is a sequence of bytes that is interpreted based on the chunk ID. The property fields will be metioned in each chunk description with different names based on the data they contain. But the chunk ID and size will be ignored.

M3DT header

  • Header for the m3 object. 376 bytes.
struct M3DT
{
 /*0x000*/  uint32_t propertyA;    // Unknown property field.    
 /*0x004*/  uint32_t propertyB;    // Unknown property field.
 /*0x008*/  uint32_t unknown0;
 /*0x00C*/  uint32_t unknown1;
 /*0x010*/  uint32_t unknown2;
 /*0x014*/  uint32_t unknown3;
 /*0x018*/  uint32_t unknown4;
 /*0x01C*/  uint32_t unknown5;
 /*0x020*/  uint32_t unknown6;
 /*0x024*/  CAaBox boundingBox;
 /*0x038*/  float radius;
 /*0x03C*/  CAaBox boundingBox2;
 /*0x058*/  float radius2;
 /*0x05C*/  uint32_t unknown7;
};

MES3 mesh

  • Mesh data.

Contains a number of subchunks that follow right after the property fields. The number of subchunks is variable, so just loop over them until the chunkSize is reached.

struct MES3
{
 /*0x000*/  uint32_t propertyA;    // Unknown property field.
 /*0x004*/  uint32_t propertyB;    // Unknown property field.
 // Subchunks follow here.
};

M3VR

  • Mesh version.

This chunk does not contain any data, besides the property fields. Chunk size is 0.

struct M3VR
{
 /*0x000*/ uint32_t version;   // Property field indicating the version of the mesh data.
 /*0x004*/ uint32_t padding;   // Unused property field.
};

VPOS

  • Vertex positions.
struct VPOS
{
 /*0x000*/ char format[4];                       // Property field indicating the format of the vertex buffer data.
 /*0x004*/ uint32_t padding;                     // Unused property field.
 /*0x008*/ Buffer vertices[];             // Array of vertex positions. See below for the format of the vertex buffer.
                                                 // The number of elements depends on the size of the chunk size divided by the size of the buffer format.
};

VNML

  • Vertex normals.
struct VNML
{
 /*0x000*/ char format[4];                       // Property field indicating the format of the vertex buffer data.
 /*0x004*/ uint32_t padding;                     // Unused property field.
 /*0x008*/ Buffer normals[];              // Array of vertex normals. See below for the format of the vertex buffer.
                                                 // The number of elements depends on the size of the chunk size divided by the size of the buffer format.
};

VUV0

  • Vertex UV set 0.
struct VUV0
{
 /*0x000*/ char format[4];                       // Property field indicating the format of the vertex buffer data.
 /*0x004*/ uint32_t padding;                     // Unused property field.
 /*0x008*/ Buffer uvSet0[];               // Array of UV set 0. See below for the format of the vertex buffer.
                                                 // The number of elements depends on the size of the chunk size divided by the size of the buffer format.
};


VUV1

  • Vertex UV set 1.
struct VUV1
{
 /*0x000*/ char format[4];                     // Property field indicating the format of the vertex buffer data.
 /*0x004*/ uint32_t padding;                   // Unused property field.
 /*0x008*/ Buffer uvSet1[];             // Array of UV set 1. See below for the format of the vertex buffer.
                                               // The number of elements depends on the size of the chunk size divided by the size of the buffer format.
};

VUV2

  • Vertex UV set 2.
struct VUV2
{
 /*0x000*/ char format[4];                     // Property field indicating the format of the vertex buffer data.
 /*0x004*/ uint32_t padding;                   // Unused property field.
 /*0x008*/ Buffer uvSet2[];             // Array of UV set 2. See below for the format of the vertex buffer.
                                               // The number of elements depends on the size of the chunk size divided by the size of the buffer format.
};

VUV3

  • Vertex UV set 3.
struct VUV3
{
 /*0x000*/ char format[4];                     // Property field indicating the format of the vertex buffer data.
 /*0x004*/ uint32_t padding;                   // Unused property field.
 /*0x008*/ Buffer uvSet3[];             // Array of UV set 3. See below for the format of the vertex buffer.
                                               // The number of elements depends on the size of the chunk size divided by the size of the buffer format.
};

VUV4

  • Vertex UV set 4.
struct VUV4
{
 /*0x000*/ char format[4];                     // Property field indicating the format of the vertex buffer data.
 /*0x004*/ uint32_t padding;                   // Unused property field.
 /*0x008*/ Buffer uvSet4[];             // Array of UV set 4. See below for the format of the vertex buffer.
                                               // The number of elements depends on the size of the chunk size divided by the size of the buffer format.
};


VUV5

  • Vertex UV set 5.
struct VUV5
{
 /*0x000*/ char format[4];                     // Property field indicating the format of the vertex buffer data.
 /*0x004*/ uint32_t padding;                   // Unused property field.
 /*0x008*/ Buffer uvSet5[];             // Array of UV set 5. See below for the format of the vertex buffer.
                                               // The number of elements depends on the size of the chunk size divided by the size of the buffer format.
};

VTAN

  • Vertex tangents.
struct VTAN
{
 /*0x000*/ char format[4];                       // Property field indicating the format of the vertex buffer data.
 /*0x004*/ uint32_t padding;                     // Unused property field.
 /*0x008*/ Buffer tangents[];             // Array of vertex tangents. See below for the format of the vertex buffer.
                                                 // The number of elements depends on the size of the chunk size divided by the size of the buffer format.
};

VSTR

  • Material String?.

Seems to contain a string reference to the material file.

struct VSTR
{
 /*0x000*/ uint64_t padding;                 // Property fields unused.
 /*0x008*/ char materialString[chunkSize];   // Material string.
};

VINX

  • Vertex indices.
struct VINX
{
 /*0x000*/ char format[4];                       // Property field indicating the format of the vertex buffer data.
 /*0x004*/ uint32_t padding;                     // Unused property field.
 /*0x008*/ Buffer indices[];              // Array of vertex indices. See below for the format of the vertex buffer.
                                                 // The number of elements depends on the size of the chunk size divided by the size of the buffer format.
};

VGEO

  • Geoset data.
struct VGEO
{
 /*0x000*/ uint32_t geosetCount;           // Property field indicating the number of geosets.
 /*0x004*/ uint32_t padding;               // Unused property field.
 /*0x008*/ Geoset geosets[];               // Array of geosets. The number of elements is equal to the geosetCount property field.
};

Geoset

struct Geoset
{
 /*0x000*/ uint32_t unknown0;
 /*0x004*/ uint32_t unknown1;
 /*0x008*/ uint32_t unknown2;
 /*0x00C*/ uint32_t indicesIndex;  // The index at which this geoset's indices start (in the LODS chunk).
 /*0x010*/ uint32_t indicesCount;  // Number of indices in the geoset.
 /*0x014*/ uint32_t unknown3;
 /*0x018*/ uint32_t unknown4;
 /*0x01C*/ uint32_t unknown5;
 /*0x020*/ uint32_t unknown6;
};

LODS

  • Level of detail data.
struct LODS
{
 /*0x000*/ uint32_t lodCount;      // Property field indicating the number of LODs.
 /*0x004*/ uint32_t geosetCount;   // Property field indicating the number of Geoset's in each LOD.
 /*0x008*/ LOD lods[];             // Array of LODs. The number of elements is equal to the lodCount property field.
};

LOD

  • Level of detail pair. Size is 8 bytes.
struct LOD
{
 /*0x000*/ uint32_t vertexCount;
 /*0x004*/ uint32_t indexCount;
}

RBAT

  • Render Batches.
struct RBAT
{
 /*0x000*/ uint32_t batchCount;                // Property field indicating the number of render batches.
 /*0x004*/ uint32_t padding;                   // Unused property field.
 /*0x008*/ Batch batches[];                    // Array of render batches. The number of elements is equal to the batchCount property field.
};

Batch

  • Render batch. Size is 8 bytes.
struct Batch
{
 /*0x000*/ uint16_t unknown0;
 /*0x002*/ uint16_t unknown1;
 /*0x004*/ uint32_t unknown2;  // Index into Geosets ???
 /*0x008*/ uint32_t unknown3;  // Material index ???
}

VWTS

  • Vertex bone weights.
struct VWTS
{
 /*0x000*/ char indicesFormat[4];                // Property field indicating the format of the bone indices data.
 /*0x004*/ char weightsFormat[4];                // Property field indicating the format of the bone weights data.
 /*0x008*/ Buffer weights[];              // Array of vertex weights. See below for the format of the vertex buffer.
                                                 // The number of elements depends on the size of the chunk size divided by the size of the buffer format.
};

VIBP

  • Vertex bone inverse bind poses.
struct VIBP
{
 /*0x000*/ char format[4];                               // Property field indicating the format of the vertex buffer data.
 /*0x004*/ uint32_t padding;                             // Unused property field.
 /*0x008*/ Buffer inverseBindPoses[];             // Array of vertex bone indices. See below for the format of the vertex buffer.
                                                         // The number of elements depends on the size of the chunk size divided by the size of the buffer format.
};

VCL0

  • Vertex color set 0.
struct VCL0
{
 /*0x000*/ char format[4];                     // Property field indicating the format of the vertex buffer data.
 /*0x004*/ uint32_t padding;                   // Unused property field.
 /*0x008*/ Buffer colors[];             // Array of vertex colors. See below for the format of the vertex buffer.
                                               // The number of elements depends on the size of the chunk size divided by the size of the buffer format.
};

VCL1

  • Vertex color set 1.
struct VCL1
{
 /*0x000*/ char format[4];                     // Property field indicating the format of the vertex buffer data.
 /*0x004*/ uint32_t padding;                   // Unused property field.
 /*0x008*/ Buffer colors[];             // Array of vertex colors. See below for the format of the vertex buffer.
                                               // The number of elements depends on the size of the chunk size divided by the size of the buffer format.
};

Vertex Buffer

The vertex buffer is read based on the first property field format of the corresponding chunk.

The following format types are known:

1F32

  • Format: "1F32"
  • Description: A single float32 value.
  • Size: 4 bytes.
struct _1F32
{
 float value;
};

2F32

  • Format: "2F32"
  • Description: Two float32 values.
  • Size: 8 bytes.
struct _2F32
{
 /*0x000*/ float x;
 /*0x004*/ float y;
};

3F32

  • Format: "3F32"
  • Description: Three float32 values.
  • Size: 12 bytes.
struct _3F32
{
 /*0x000*/ float x;
 /*0x004*/ float y;
 /*0x008*/ float z;
};

4F32

  • Format: "4F32"
  • Description: Four float32 values.
  • Size: 16 bytes.
struct _4F32
{
 /*0x000*/ float x;
 /*0x004*/ float y;
 /*0x008*/ float z;
 /*0x00C*/ float w;
};

2F16

  • Format: "2F16"
  • Description: Two float16 values. Or Half Floats
  • Size: 4 bytes.
struct _2F16
{
 /*0x000*/ hfloat x;
 /*0x002*/ hfloat y;
};

4F16

  • Format: "4F16"
  • Description: Four float16 values. Or Half Floats
  • Size: 8 bytes.
struct _4F16
{
 /*0x000*/ hfloat x;
 /*0x002*/ hfloat y;
 /*0x004*/ hfloat z;
 /*0x006*/ hfloat w;
};

U10N

  • Format: "U10N"
  • Description: 3 normalized float values stored in 10 bits each. With 2 bits padding.
  • Size: 4 bytes.
struct U10N
{
 uint32_t x : 10;      // Normalize to float by dividing by 1023.0f
 uint32_t y : 10;      // Normalize to float by dividing by 1023.0f              
 uint32_t z : 10;      // Normalize to float by dividing by 1023.0f
 uint32_t padding : 2;
};

1U32

  • Format: "1U32"
  • Description: A single uint32 value.
  • Size: 4 bytes.
struct _1U32
{
 uint32_t value;
};

1U16

  • Format: "1U16"
  • Description: A single uint16 value.
  • Size: 2 bytes.
struct _1U16
{
 uint16_t value;
};

4U16

  • Format: "4U16"
  • Description: Four uint16 values.
  • Size: 8 bytes.
struct _4U16
{
 /*0x000*/ uint16_t x;
 /*0x002*/ uint16_t y;
 /*0x004*/ uint16_t z;
 /*0x006*/ uint16_t w;
};

4U08

  • Format: "4U08"
  • Description: Four uint8 values.
  • Size: 4 bytes.
struct _4U08
{
 /*0x000*/ uint8_t x;
 /*0x001*/ uint8_t y;
 /*0x002*/ uint8_t z;
 /*0x003*/ uint8_t w;
};

4U8N

  • Format: "4U8N"
  • Description: Four normalized float values stored as uint8 values.
  • Size: 4 bytes.
struct _4U8N
{
 /*0x000*/ uint8_t x;  // Normalize to float by dividing by 255.0f
 /*0x001*/ uint8_t y;  // Normalize to float by dividing by 255.0f
 /*0x002*/ uint8_t z;  // Normalize to float by dividing by 255.0f
 /*0x003*/ uint8_t w;  // Normalize to float by dividing by 255.0f
}; 

M3CL collision mesh

  • Collision mesh data.
struct M3CL
{
 /*0x000*/ uint32_t propertyA;   // Unknown property field.
 /*0x004*/ uint32_t propertyB;   // Unknown property field.
 // Subchunks follow here. Note: These subchunks do not have property fields.
};

CPOS

  • Collision mesh vertex positions.
struct CPOS
{
 /*0x000*/ C3Vector vertices[chunkSize / 12];  // Array of vertex positions.
};

CNML

  • Collision mesh vertex normals.

(And / Or face normals, needs checking as there are more normals than positions)

struct CNML
{
 /*0x000*/ C3Vector normals[chunkSize / 12];   // Array of vertex normals.
};

CINX

  • Collision mesh vertex indices.
struct CINX
{
 /*0x000*/ uint16_t indices[chunkSize / 2];    // Array of vertex indices.
};

M3SI

  • Instances

(data deduplication?)

struct M3SI
{
 /*0x000*/ uint32_t propertyA;                         // Unknown property field.
 /*0x004*/ uint32_t propertyB;                         // Unknown property field.
 /*0x008*/ char magic[4];                              // "m3IS"
 /*0x00C*/ uint32_t version;                           // Version of the instances data. 
 /*0x010*/ uint32_t unknown0;
 /*0x014*/ uint32_t unknown1;
 /*0x018*/ uint32_t instanceCount;                     // Number of instances.
 /*0x01C*/ M2Array<Instance> instances;                // Array of instances. The offset is relative to the start of the chunk, after magic.
};

Instance

struct Instance
{
 /*0x000*/ uint32_t filedataID;      // Unknown FileDataID 5614494 (not currently present in the client)
 /*0x004*/ byte md5Hash[16];         // MD5 hash of the instance name? Used to reference the instance in the material file.
 /*0x014*/ uint32_t unknowns[17];    // Unknown data.
};

M3ST

  • Undocumented. String Table

M3VS

  • Undocumented.