Error: Failed to load processor ArchivePage
No macro or processor named 'ArchivePage' found

Maintainer: Patrick Boenzli

The MD2 fileformat has been invented by id software, they have released it with the quake2 source-code under the GPL.

An MD2 file consists out of two main parts: header and payload. The header has a fixed and well known size, the payload on the other hand can have variable lenght, this variable length is specified in the header. First we are only speaking about file loading and parsing, so when we are reading MD2 files, there are two major steps to take:

  1. read the header data, which will give you all information you need to find data in the payload
  2. read in the payload and perform the necessary conversions (data is often compressed)

The header is read in the MD2Model::loadModel() function. Since all the data formats in which the data is stored are exactly defined in the MD2 file spec fread(...) is our friend!

  fread(buffer, size, length, stream);

An MD2Model stores the model animation in "KeyFrames", these are just the models in certain movment states. Like a cartoon, if you look at these KeyFrames very fast, the movement flows. Technicaly spoken, KeyFrames are only a collection of vertices. MD2 doesn't only display KeyFrames, it also interpolates between them, so there seems to be a smooth movmement; the faster the computation (computer), the smoother the animation gets. Again technicaly, the MD2Model::interpolate() function does interpolate between all the vertices of the two KeyFrames, using the equation x = p1 + t*(p1 - p2) if t = {0..1}
MD2 defines different sorts of animations, that have all been defined from the id software team: {STAND, RUN, JUMP, ... } . The animations vary in animation speed (fps) and animation length. The animations (model) data is stored in the payload:

  • MD2Model::loadModel() will read out all the data needed and store:
  • vertices data: MD2Model::pVertices
  • normals data: MD2Model::pLightNormals
  • frame data: MD2Model::pFrames

Once we have loaded all the data, there is some data decompression we have to perform, in detail its just a scale and translate process that we apply on the raw coordinates.

This is where we start with the drawing process: this is a little bit more complicated: Actually we could now just start drawing the vertices on the screen using GL_TRIANGLES, give them normals and tex coordinates and we get our model. Since this is not very efficient, the people from id did think of a faster and much more performant way: MD2 uses a so called "opengl command list" to perform drawing in an efficient way: The idea is to use GL_TRIANGLE_FAN and GL_TRIANTLE_STRIP. With this drawing mode, we send less (almost no) redundant vertices. If we want to draw the model in this mode we must use the verices in a very specific order, which is defined in the openl command list.

  int* MD2Model::pGLCommandList;

The gl command list is an int array, terminated with 0. Vertices that can be drawn with _FAN or _STRIP are grouped together. The steps to draw a group of vertices looks like this:

  1. gllist[offset + 0]: indicates type and number of triangles to draw: once this is read
  2. gllist[offset + 1]: u coordinate for texture
  3. gllist[offset + 2]: v coordinate for texture
  4. gllist[offset + 0]: vertex index in the vertex array

This is actually all the magic behind the md2 file format. There is some more in the way its implemented: since it has to be very efficent, there are some tricks used in the source code, but dont fear, once you see the trick, they are obvious. I tried to put as much comments in the code as possible.

source files: lib/graphics/importer/{MD2Model.h,, abstract_model.h}