by mh » Sat Apr 02, 2011 9:53 pm
MDLs are just a lump of data. You've got heavy vertex compession, heavy texcoord compression, etc in them. Each basically contains a table of positions, each of which is unique, and a table of texcoords, each of which is also unique. Each frame then has a list of indexes to do lookups into these tables. That's the simplified explanation, but it'll do for this discussion.
This kind of data layout is more or less useless for hardware-accelerated rendering (although if glDraw(Range)Elements/IDirect3DDevice9::DrawIndexedPrimitive allowed separate indexes for each input array it would be perfect). So what Quake does when loading an MDL is take that lump of data and re-order it in a manner that was more suitable for 1996-1999 level hardware - lots of little triangle strips and triangle fans.
The MS2 file contains this reordered data and is merely used to speed up load times a little (because Quake had to run on 1996-level hardware this was important). When loading an MDL Quake looks for the MS2 file; if it finds one it says "ah-ha, my data has already been reordered before so I don't need to do so again, I can just read it from this instead". Otherwise it reorders the data and saves it out for the next time that MDL is loaded.
The obvious flaw with this is that the MS2 file contains absolutely nothing that connects it to the original MDL used to generate it. If you have a mod that has a replacement v_shot.mdl (for example) then Quake will quite happily use the MS2 file from ID1, with the end result being that your shotgun on-screen looks like something that's been through a garbage grinder.
One way of resolving this is to just remove the code that checks for and generates the MS2 files from the engine. Loading times will be a little slower, but not so much that 99.999% of people would even notice.
Another way is to force the MS2 file to only load from the same game directory as the original MDL. A third way is to modify the format (and change the extension to MS3 or something like that) to include a checksum in a header. I'm sure that there are more.
Important to note as well that the MS2 ordering into lots of little strips and fans that was so useful in 1996-1999 is quite hopeless today. This is almost a textbook example of how not to get the best out of today's hardware (it also contains significant vertex duplication - a maybe 3x overhead, depending on the MDL). Today you'd use an indexed triangle list reordered for optimal vertex cache reuse, but that's a separate topic.