Starcraft 2 Model Format Pt. 1

Due to a number of requests I’ve received, I’ve decided to write down some of my findings in the .m3 model format. Here we go:
Overall structure
The .m3 format is a mixture of the World of Warcraft .m2 format and the Warcraft 3 .mdx format in that it has a parsing structure similar to the former, but uses tags, like the later. The list of tags with offsets are located at the end of the .m3 file. Specifically, the file header is
struct M3Header {
fourcc header_tag
uint32 tagindex_offset
uint32 tagindex_size
uint32 unknown1
uint32 unknown2
The header_tag should be ‘MD33’. The tagindex is the aforementioned list of tags, and starts at tagindex_offset and has tagindex_size elements. I suspect that unknown1 and unknown2 may point to the tag where to start the recursive parsing, which is the ‘MODL’ tag. The elements of the tagindex have the form:
struct Tag {
fourcc tag
uint32 offset
uint32 repetitions
uint32 version
The first two elements, tag and offset, are pretty obvious I guess. The interesting part starts at the repetitions part. Each tag describes a fixed-size structure, which may be a little different for different files, hence the version number. The number of repetitions tells us how often this
structures is repeated in the chunk. As an example, a string chunk (with a ‘CHAR’ tag) describes a string that consists of repetitions many characters of size 1 byte (unless it’s UTF8, but I’ve not encountered any special characters yet). This is great for loading, because we don’t need dynamic parsing. We can just allocate and read the structure as many times as requested, without worrying about dynamically sized content.
If dynamic sizes are required, they are placed in a seperate chunk and referenced via the tag. Again, a good example are strings, which you can find all over the file, usually directly after the chunks where they are needed.
All chunks are padded to 16 byte boundaries using 0xaa.
Once the tag directory has been read, my parsing starts at the ‘MODL’ tag (and I suspect Blizzards parsing does, too). The ‘MODL’ chunk is essentially the root of the parsing tree for the .m3 format, just like the header of the .m2 format, but instead of referencing the other chunks by offsets, they are referenced by their index in the tagindex. The references usually also contain the number of repetitions, which make them quite easy to spot.
That’s it for today and the general parsing and file structure. Next time I’ll get into the details of detecting the vertex format, reading out the vertices and faces and finally rendering a rough version of the model.
As an outlook, here are some more pictures (Templar, Ultralisk, Hydralisk):

Blizzards art team is just incredible!

8 thoughts on “Starcraft 2 Model Format Pt. 1

Leave a Reply

Your email address will not be published. Required fields are marked *