This post explores the way that the .mdl format handles skin mapping. The 3d models in Quake have a 2d texture applied to them, and the skin map determines which portions of the 2d texture appear on which part of the model. Creating a skin map is often called “unwrapping” the model; portions of the model are effectively rolled flat and laid out in 2d. There are two challenges: deciding how to divide up and lay out the skin map, and how to store it in the .mdl format.
When Quake was created, the model tool offered a simple and practical way to create your skin mapping. You fed the tool a 3d model pose, the base frame. The tool looked at this pose from the front view, and flattened what it saw to 2d. This formed the left hand side of the skin. The right hand side of the skin is similar, but takes a snapshot from the back view. Each triangle in the model either faces forward or faces back in the base frame, so it appear exactly once on the skin. The quake models had carefully designed base frames to try and ensure the triangles were clearly visible from front or back and did not overlap.
In the .mdl format the skin mapping records only the coordinates of the vertices in the model. The triangles are expected to be connected to all the same vertices as they are in the 3d model, but this creates an issue. Consider the vertices which are connected to both front faces and back faces – the seam vertices. The front faces expect these vertices to appear on the left hand side of the skin, and the back faces expect them to appear on the right half. Whichever set of coordinates you give for these vertices, one side of the skin is going to be broken.
The .mdl format has some extra features to get round this. All triangles in the model record whether they face the front or the back. Similarly, all vertices record if they are on the seam or not. The seam vertex are allowed to appear in two different places on the skin map, one for the front faces and one for the back faces. The model stores the vertex position for the front half of the skin, and positions it in the same place on the right half of the skin (half a skin-width to the right). The end result is that the seam vertices form an outline of the model which is duplicated on the left and the right sides of the skin.
The seam vertices are named after the line around the 3d model where the front and back faces meet. These seams require particular attention when it comes to making skins; disguising their existence makes the model look like a continuous object. Seams are not unique to the way that the Quake tools create skin maps, almost all models will have seams somewhere. However, the Quake tools don’t give you much control over your seams, and worse they usually occur adjacent to stretched triangles which have a low pixel density.
The Power Of QME
As new games came out, Quake’s skin mapping rapidly looked dated. The sequels Quake 2 and Quake 3 built up a community creating custom player models. These models could be very technically proficient – they were assessed not just on how good they looked and moved, but also hard numbers like percentage skin usage. By this point models were being unwrapped in 3d modelling packages, giving these modellers the ability to hide seams discretely, to make use of the full texture space and unwrap smaller components to reduce distortion. Quake 1 didn’t have the tools for this, so while custom bsps were surpassing those of the original games, custom mdls were not.
However, the arrival of QME did give modders something to work with. QME was designed for .mdl, so it supported and embraced the front-back skin maps of Quake. The skin editor allowed you to manipulate the skin coordinates directly. It supported the seam vertices in a very illustrative way, they appeared on the front and back sides of the skin and if you moved one, the other moved accordingly. Internal skin vertices – those not on the seams – could be moved freely anywhere on the skin in QME. The original tools would always generate skins where vertices attached to front faces would lie on the left hand side. While QME didn’t have this restriction, the only way to use it was to move internal vertices across the outline of the seam, which would create ugly overlaps.
However, there were little-known ways that QME could generate previously impossible skin mappings which were practical. One example can be taken from the Quake knight, who has a near-perfect line of symmetry in his geometry. With patience you can move each seam vertex from the knight’s left hand side to overlap the matching vertex on the right. The QME command “Cut Away Unused Skin” leaves you with a skin that’s half the width. You might try and create a base frame which generates the same skin layout, by mirroring the left hand vertices onto the right. But in doing that, you’ve flipped the orientation of those triangles as well, so they get mapped to the back half instead! You can’t do it without QME.
Complete Skin Maps
While a neat trick, it’s still a long way from the maps that Quake 3 models have. QuArK, without much fanfare, was the first tool to offer a totally new approach to skinmaps, catching Quake up with her younger sisters. In a sense it’s much simpler than the above system of seams and backfaces, but we’ll learn it easiest from first principles – time for a quick practical!
Start a new model in QME – we’re actually going to build a model from scratch, vertex by vertex. In order to avoid dying of boredom, the model we’ll aim for will be a plane made from two triangles. Set the viewpoint to “View Front – YZ”. Go into vertex mode, and using the Ins key add four vertices in a rectangle. Select 3 of them and press ctrl-t to make a triangle. Then select the isolated vertex and the two diagonals and press ctrl-t to finish the geometry. Run the Skinmap wizard to create a Quake 1 skin for our plane, then go into Skin View. You’ll notice that all four skin vertices are internal and can be moved freely – because there were no backfaces in our model there are no seams! This lets us resize the rectangle to fill the whole skin for 100% coverage.
So this looks promising, we can make a model in our 3d package, and then when we generate our mdl file we just mark all of the vertices as internal, all of our triangles as front facing, and have no seams. We are then back at the original problem from this article: how do we cope when we have one vertex on the 3d model, but we need it to be in multiple places on the skin?
The QuArK-style models solve this by generating multiple vertices on the 3d model, one for every vertex on the skin! The extra vertices are just for the benefit of the 2d texture, on every frame of the 3d model they are “coincidentally” in exactly the same position (if you’ll excuse the pun). Before you object that this is completely crazy, it actually arose from the conversion from md3 to mdl that QuArK offered – because this is exactly the way that the md3 models work internally. One of the reasons that my own md3tomdl (which emulates the QuArK conversion on the command line) uses md3 format input is that it made the conversion process brainless!
There are two main drawbacks to this method. The first is that it uses more vertices than the equivalent model with a standard skin mapping. This is undeniable and unavoidable, it’s the cost of the better mapping. However, the limit (with a negligible exception) is 2000 vertices, so I would not worry too much about this.
The other drawback is that it has an impact on vertex normals. Normals are a little-known aspect of modelling, which only generate a subtle effect and are stored internally in a very obscure way. It would be far too much of a detour to cover them here, but more can be found in the follow-up vertex normal post. This drawback can be overcome when tools are aware of the issue and designed to cope – but beware as QME is not “in on the trick” and will alter vertex normals if it loads and saves one of these models. It’s not the end of the world, but as we’ll see next time it can be noticed!