M3

From wowdev
Revision as of 12:45, 20 May 2014 by Schlumpf (talk | contribs)
Jump to navigation Jump to search

This file format is actually no WoW file format. Its the next generation of the MDX model format which had MDX (m1) in WC3 / prior to WoW, MDX2 (m2) in WoW, MDX2.2 (m2 with skin and anim) in WoW:WotLK and MDX3 (m3) in SC2.

As always, the format has similarities but also big revamps like on references this time.

Instead of using direct references, the references are now all in one global list. This list also contains the type and number of entries referenced (as well as another uint32). If one block references another one, it only says, how many of that data is referenced (similar to the entry in the reference table) and which reference is referenced (the id in the global list).

The reference table consists of entries of this structure:

struct referenceentry 
{
  /*0x00*/ uint32_t type;
  /*0x04*/ uint32_t offset;
  /*0x08*/ uint32_t nEntries;
  /*0x0C*/ uint32_t nFields;//this defines, how many Entries belong to that structure(like 'LAYR'+'CHAR' entries)
};

When a block is referenced somewhere, the reference looks like this:

struct reference 
{
  /*0x00*/ uint32_t entries;
  /*0x04*/ uint32_t referenceid;
};

The position of the reference table is not fixed and mostly on the end of the file due to easier saving. The position is told in the header of the file:

struct MD33
{
  /*0x00*/ uint32_t token; // 'MD33'
  /*0x04*/ uint32_t offsettotable;
  /*0x08*/ uint32_t entriesoftable;
  /*0x0C*/ reference MODL;
};

The MODL block is the actual information about the model.

Typelist

'CHAR' = char, contains a zero-terminated string of Length nEntries; string may contain embedded zero bytes

'U32_' = uint32

'I32_' = int32

'U16_' = uint16

'U8__' = uint8

'QUAT' = Quaternion

'VEC2' = Vector2D

'VEC3' = Vector3D

'VEC4' = Vector4D

'REAL' = Float

'BNDS' = Bounds

struct{
   Vec3D min;
   Vec3D max;
   float radius;
}Bounds;

'FLAG' = Flags

struct{//???
  uint16 unk1;
  uint16 unk2;
}Flags;

MODL =

struct{
   Reference ModelName;
   int unk[2];
   Reference Sequence;
   Reference STC;
   Reference STG;
   Reference a;
   Reference STS;
   Reference Bone;
   int unk2[2];
   Reference Vertices;
   Reference Geoset;
   Reference unk3;
   Reference Extents;
   int unk4[18];
   Reference Attachment;
   Reference b;
   Reference Lite;
   Reference Camera;
   Reference c;
   Reference Matm;
   Reference Material;
   Reference dis;
   Reference cmp;
   Reference ter; 
   int unk5[4];
   Reference crep;
   Reference par;
   Reference parc;
   Reference ribbon;
   int unk6[24];
   Reference iref;
   int unk7[2];
   float unk8[16];
   int unk9[18];
}MODL;

'STC_'

Size: 0x8D

Follows after some blocks, additional information?

'SD**'

The Sequence Data block contains information about animated things, it's the replacement for the Animation-Blocks. The two following chars define the type of the animation(like 4Q=Quaternion, see list below). The timeline is made of int32's

struct SD
{
    /*0x00*/ Reference timeline;
    /*0x08*/ uint32 flags;
    /*0x0C*/ uint32 length;
    /*0x08*/ Reference data;
};

'SD4Q': Sequence Data Quaternion

'SD3V': Sequence Data Vector3D

'SD2V': Sequence Data Vector2D

'SDR3': Sequence Data Float

'SDS6': Sequence Data Short

'SDEV': Sequence Data Event

'SDMB': Sequence Data Model Bounds

'SDFG': Sequence Data Flags

'EVNT'

Size: 0x5C

Events


'MODL'

type: 'MODL'
size: 0x228

The 'CHAR'-block following contains the *.max filename at blizzard.

Sequences

type: 'SEQS' Size: 0x58

struct SEQS
{
    /*0x00*/ int32 d1;
    /*0x04*/ int32 d2;
    /*0x08*/ Reference name;
    /*0x10*/ int32 d3;
    /*0x14*/ int32 length;
    /*0x18*/ int32 d4;
    /*0x1C*/ uint32 flags;
    /*0x20*/ int32 unk[5];
    /*0x34*/ Bounds extents;
    /*0x50*/ int32 d5;
    /*0x54*/ int32 d6;
};

This defines the Animation sequences. The 'CHAR'-block after 'SEQS' contains the name of the Animation (like 'Stand', 'Stand Work' etc.)

Bones

type: 'BONE'
Size: 0x9C
struct BONE
{
    /*0x00*/ int32 d1; // Keybone?
    /*0x04*/ Reference name;
    /*0x0C*/ uint32 flags;
    /*0x10*/ int16 parent;
    /*0x9C*/
};

This block contains the bones, the 'CHAR'-block afterwards contains the name of the bone.

'MAT_'

Material

struct{
    Reference name;
    int ukn1[8];
    float x,y;  //always 1.0f -- 5.0f, 3.5f in Immortal.m3, some sort of scaling?
    Reference layers[13];
    int ukn2[15];
}MAT_

Texture Layers

type: 'LAYR' size: 0x160

typedef struct{
    int unk;
    Reference name;
    int unk2[85];
}LAYR;

'IREF'

Matrix? size: 0x40

struct{
  float unk[16];
}IREF;

Vertices

The Vertices are saved in the U8__ Block before the DIV_ Block which is very weird. Struct is:

struct{
    Vec3D pos;
    char boneWeight[4];
    char boneIndex[4];
    uint32 d1;
    uint16 uv[2];
    uint32 d2;
}Vertex;


gzz100:

Most models's vertice length is 0x24,the vertices struct is:

struct{
    Vec3D pos;
    char boneWeight[4];
    char boneIndex[4];
    char normal[4];  //normal_x = (float)normal[0]/255.0f...
    uint16 uv[2];
    uint32 d1;
    uint32 d2;
}Vertex;

'DIV_'

Size: 0x24

struct{
   Reference u16_; //Triangles
   Reference regn;
   Reference bat;
   Reference msec;
   uint32 unk;// 1
}DIV_;

Unknown Types

The following types have been encountered have been encountered in model files in the SC2 Beta. Note that some of those fields only occur in a single file (e.g. SVC3 is only present in LavaSplashBig.m3).

Keep this list sorted in alphabetical order and remove types as they are documented.

ATT_
ATVL
BAT_
BBSC
CAM_
CMP_
CMS_
CREP
DIS_
FOR_
IKJT
LITE
COL - This is the only type that consists of only three chars, as the first character is '\0'
MATM
MSEC
PAR_
PARC
PATU
PHRB
PHSH
PROJ
REGN
RIB_
SCHR
SDCC
SDEV
SDMB
SDU6
SHBX
SRIB
SSGS
STG_
STS_
SVC3
TER_
TMD_
TRGD
VOL_
WRP_


Partly retrieved from http://code.google.com/p/libm3/wiki