Making [Q4] Kats Klorr #2 – Mesh, Materials & UVs

Spread the love

Developing game levels is often a long and protracted process, especially where the level and it’s contents are based on customised content, i.e., built models, textures and so on. The following is a partial walk-through of the process to build a custom level for Quake 4. All content was modelled using Blender 3D.

The contents of this article were originally posted several years ago to a now unavailable forum. Some minor editing for clarity has been performed.

UV Mapping Organics

When you read that people “hate” UV mapping models this is what they’re referring to; fiddly bits

Planar mapping and brushwork : When you apply a texture to a brush in Radiant what generally happens is something called ‘“Planar” (flat) projection‘. Imaging a movie being projected onto a screen, if you hold an object up so it’s being lit by the projected images you’ll see the movie appear on all the sides that face the projector. As you rotate the object and change it’s angle of attack relative to the projector you may notice that as the angle gets more acute the image on the object *appears* to distort slightly because of distance and angle of incidence variations.

This is the basic principle behind how brushes are textured in Radiant; each face of a brush gets it’s own little projector which ‘projects’ the image onto it (obviously that’s not technically what’s happening, it’s just a term used to describe visually how brushwork is textured in Radiant) so selecting and texturing a group of objects always ‘works’, each face gets textured either relative to it’s own individual face or as part of a group (like sections of a wall getting the same texture applied to it which all match up correctly).

Where it doesn’t however, is with patch meshes. Because they can be curved and bent out of shape it means that planar projection runs the risk of being distorted; because flat projection can’t go round corners it resulting in bad stretching along the ‘edge’ not facing the (‘projector’) angle of projection. Models suffer from the same issue and it’s why they *can* be fiddly to texture.

So the model of a set of steps, something that’s very simply to texture in Radiant because of the method it uses as described above, suddenly becomes a bit of a chore to apply textures to; you have to UV map the object so the game knows *how* the texture is supposed to be applied (it’s appearance; is it ‘angled’, ‘twisted’, ‘distorted’ etc.), and then apply the texture image so the game know *what* it’s supposed to be applying to the mesh.

There are two really good reasons to use models generally but they are highlighted on objects like steps and stairways, one isĀ texture offset, the other isĀ smooth-groupingsĀ (see below).

Texture/UV Offset

One of the common problems associated with texturing objects like stairways is ‘texture repeat’ – this is where a feature on a texture image is visibly repeated across it’s length/width, it’s not usually noticeable until you look at a relatively large collection of steps.

To get around this problem the texturesĀ should be offset by various amountsĀ which gives the impression of ‘individualism’; that each step is using a different texture – or at the very least using a different part of the same texture. It’s not necessary to do every step like this, it just needs to be done to enough of them to break up the visual pattern repeat that happens.

For models that means breaking the UV map into ‘units’ that correspond to each individual step, these can then be offset relative to their neighbours so that any potential pattern repeat is countered. To do this in Blender is pretty simple; select the faces corresponding to ‘a’ step and then in the UV map/Face Edit (‘F’) window, select and move the UV map section – make sure to line them up with any ‘edges’ present on the textures; the image below for example, shows a texture with three steps on it, each UV map step section is aligned to sit appropriately – the darker area is the ‘back’ of the step.

The UV maps can be straightened out a little bit to that textures flow relative to what you’d expect to see. The steps below are twisted out of shape; in the real world that’s caused by the stones themselves rotating slightly, this obviously means that the stone surface rotates with it. That should be done to objects used in game where ever possible; if an object is rotated then the texture should also follow that alignment. The problem here is that planar projection doesn’t take this into account, nor does Blenders LSCM unwrapping so UV maps often have to be straightened out so textures flow correctly over surfaces.

If you add a bevel to the edge of a step watch out for texture stretching along that edge, more often than not it (the UV map *not* the mesh) will need expanding slightly to compensate for the angle so the textures appear correctly UV mapped where ever possible.

Every other step selectedAssociated UV's are offset

Steps can look repetitive if mapped ‘as is’, here offsetting UV’s can compensate and make the model look more unique overall

Using UVW Break For Smooth-Groups

There’s a useful ‘side effect’ to breaking the UV maps up as described above and that’s to do withĀ smooth-groups Normally these have to be forced by splitting (or separating) faces in such a way as to create a duplicate set of vertices along selected polygon edges; it has to be done like this because pretty much all games apply a uniform smoothing over everything in game so the only way to control their appearance is to break the mesh up.

Because of the way game engines tend to use UV maps it generally means it isn’t necessary to manually split the mesh up; where ever there is a seam on a UV map a mesh is ‘split’. In other words, the various edges that define the shapes of a UV map (arms, legs, body, etc.) will create ‘groups’ of UV mapped polygons (a collection of faces that have the same texture mapped to them). In effect these areas become smooth-groups as a result of this.

Smoothing applied uniformly to the model

Smoothing applied to the model uniformly makes it appear ‘mushy’

Assigning Sharp Edges to highlight mesh structure more clearly

The shots above, although in Blender, shows an approximation of what will happen as a result of using the UV map the way it’s been described above; where ever there is a ‘separation’ of the UV map there will be a smooth-group created. The top image is the steps as they are by default – all vertices are merged, the bottom image is how they will appear in game – smooth-group edges created as a result of breaking the complete UV map for the stairway into smaller ‘individual’ step sections

Prefabs Or Reusable Objects

If it’s not been modelled to serve a specific purpose then it could be used as a prefab or reusable object. Unfortunately the Quake 4 (Doom 3) engine doesn’t make use of ‘instancing’ so nothing is gained from a performance point of view from doing this, it just helps keep a consistent ‘style’ applied to various objects (usually man made).

The shot below shows two sets of prefabs; a stone block and a slanted ‘ramp’. There’s only one original of each of these, the rest being duplicates of the first. The ‘uniqueness’ comes from rotating and positioning the units in such a way to “hide the wood for the trees”; you ‘disguise’ the fact that the completed object (the stairway in this case) is made from reused copies by rotating and angling the objects against each other creating the ‘illusion’ of overall uniqueness. Because they are prefabs and can be reused it means they can be duplicated and used elsewhere in the map and providing they are rotated and angled, their sameness should pass by cursory glances of the player as they run amok.

This method of building can be used on anything that doesn’t require specific models to be made (the cavern walls for instance) but that needs to be part of an overall consistent visual ‘style group’. If a more unique object is still required, then a larger object can be composed of smaller prefabs; these joined together and further work carried out on the newly created object.

Reusing models in Blender

Reusing models in Blender to create a larger unique structure

Using Layers In Blender

Although this is being shown now it’s actually done as a result of breaking the original model up into ‘rooms’ as shown at the beginning of the topic. It’s a good idea to make use of the different layers Blender has so you can organise and work on sections of the model at any given point without the rest of it getting in the way and blocking your view of what’s being done. Initially just using a simple ‘room by room’ organisation is OK, but you may want to refine that further as you work moving objects to different layers depending on ‘function’ or texture type for instance.

How to use layersYouTube Video – Left Mouse Button click on each layer to activate it, Shift+LBM click to activate multiple layers.

Using Blenders Layers for Scene management

Levels can become complex so Blenders Layers can be used for scene management

Aligning Different UV sections

UV maps again, this time to do with relative positions. Because three textures will be used on this model, one of which will actually act as the ‘blend’ between two others, it’s a good idea to make sure that the UV map on each section match up so the textures align correctly in game otherwise the difference between two blended textures may be more noticeable than expected, especially when textures with strong patterns have been used (man made, grids, grill, lines etc.).

At this point the textures scale isn’t too important; it has to be consistent with the rest of the map but because the textures can be scaled via a material in game the relative ‘size’ matters only so much as all the UV maps using (approximately) the same UV map : texture size density ratio. The three textures being used also need to be the same size otherwise they’ll mismatch in game because of the way the UV map will shrink or stretch to fit the relative image size available.

Rock section UV map show in the UV/Image EditorMatching ground UV mapBoth sections aligned in the UV/Image Editor

Separate ‘rock’ and ‘ground’ objects have distinct UV maps that are aligned as a visual optimisation – texture patterns flow from one to the other when later mixed and blended

First ASE Export Test

Time for the first export test to make sure everything fits and works the way it should. Although the model was based on a brushwork template, during the polygon pushing phase it’s not uncommon to find that faces have been pulled or pushed a bit too much, so importing the mesh now just checks this to make sure everything is OK.

At this stage the textures are all created and the material files written; although just one material is used to cover everything at the moment – because this is a test it’s only purpose is to get the model into the brushwork prefab that was originally used as the template and make sure none of the mesh pokes into the brushwork hull (which will cause ‘blackouts’ where the caulk brush causes the overlapped area to remain unlit).

In Blender all the mesh sections are duplicated (Shift+DĀ once they’re selected) and moved to their own layer, it’s all that’s needed for now with regards to the organisation of the various mesh sections. All the objects are ‘fixed’ in place so the cursor is moved to the “0,0,0” grid centre in Blender and then “Apply size and rotation” is done (Ctrl+A); this locks the positions of the objects relative to the centre point. There will be more on this aspect of prepping the model later because it’s important to get right.

Smooth-groups etc. aren’t a concern at the moment and neither is triangulating the mesh before export. This will be covered in more detail later on as well as this is also important to get right.Ā Using Goofos’s ASE export scriptĀ (Doc Holidays USMExporter can’t be used for models like this), all the objects are selected and the script run outputting only the objects highlighted – this will result in one physical object composed of many sub-objects Ā as an ASE model (and a lot of Blender materials as those aren’t cleaned up at this point either). Incidentally, this isĀ notĀ how a map made from models should be finally exported because it results in the whole mesh being rendered all the time – more on this later as well!.

Entire level exported as an ASE

Initially he entire level is exported as a single model so it can be easily and quickly tested in Radiant for fit and alignment (model is a textured ASE model assigned a single placeholder image

ASE Texture Edits

Depending on what 3D app is used to export the ASE mesh it may result in slightly different data being written to the text file, Goofos’ ASE exports this as part of that data;

*MATERIAL 0 {
*MATERIAL_NAME "Multi # build"
*MATERIAL_CLASS "Multi/SubĀ Object"
*MATERIAL_AMBIENT 0.0000 0.0000 0.0000
*MATERIAL_DIFFUSE 1.0000 0.0000 1.0000
*MATERIAL_SPECULAR 1.0000 1.0000 1.0000
*MATERIAL_SHINE 0.5000
*MATERIAL_SHINESTRENGTH 0.0978
*MATERIAL_TRANSPARENCY 0.0000
*MATERIAL_WIRESIZE 1.0000
*NUMSUBMTLS 9
*SUBMATERIAL 0 { *MATERIAL_NAMEĀ "build" *MATERIAL_CLASSĀ "Standard" *MATERIAL_AMBIENT 0.0000 0.0000 0.0000 *MATERIAL_DIFFUSE 1.0000 0.0000 1.0000 *MATERIAL_SPECULAR 1.0000 1.0000 1.0000 *MATERIAL_SHINE 0.5000 *MATERIAL_SHINESTRENGTH 0.0978 *MATERIAL_TRANSPARENCY 0.0000 *MATERIAL_WIRESIZE 1.0000 *MATERIAL_SHADING Blinn *MATERIAL_XP_FALLOFF 0.0000 *MATERIAL_SELFILLUM 0.0000 *MATERIAL_FALLOFF In *MATERIAL_XP_TYPE Filter *MAP_DIFFUSE { *MAP_NAMEĀ "build" *MAP_CLASSĀ "Bitmap" *MAP_SUBNO 1 *MAP_AMOUNT 1.0000 *BITMAPĀ "//q4base/textures/katq4dm3/stonedirtMix" *MAP_TYPE Screen *UVW_U_OFFSET 0.0000 *UVW_V_OFFSET 0.0000 *UVW_U_TILING 1.0000 *UVW_V_TILING 1.0000 *UVW_ANGLE 0.0000 *UVW_BLUR 1.0000 *UVW_BLUR_OFFSET 0.0000 *UVW_NOISE_AMT 1.0000 *UVW_NOISE_SIZE 1.0000 *UVW_NOISE_LEVEL 1 *UVW_NOISE_PHASE 0.0000 *BITMAP_FILTER Pyramidal

The important bit of all that needed to get ASE models working properly textured in game is the line of text highlighted bold above. ThatĀ mustĀ be a path to a material reference because ‘naked’ textures don’t work in Quake 4 like they did in Quake 3; all texture images need a shader to even show up in game. This has to be done for all the ‘BITMAP’ references in the file and at the moment there are a lot of them!. For more on this read theĀ prepping models tutorial here.

All material references written to the ASE files for Quake 4 needĀ //q4base/Ā in front of the path; as there are a lot of paths to edit at this early test stage it means checking to make sure it’s not missing, otherwise the model will show up black.

Editing The *.mtl Material File

Not all the textures are sorted out yet so the material although a ‘blend’ material mixes between a full set for the rock surface but only a diffuse for the ground, this means commenting out (using “//” preceding any unwanted text) the unused stages of the ‘dirt’ section of the material. Not doing that usually results in the ‘black render’ error (the model appears black).

The material is as follows;

textures/katq4dm3/stonedirtMix
{
stone
//### TEXTUREĀ 1 -Ā DIRT
{
blend diffusemap
map textures/katq4dm3/dirt.tga
VertexColor
scale 1.5, 1.5
}
//### TEXTUREĀ 2Ā -Ā ROCK FACE
{
blend bumpmap
map addnormals (textures/katq4dm3/rock_plain_local.tga, heightmap( textures/katq4dm3/rock_plain_h.tga, 4 ) ) inverseVertexColor scale 1.2, 1.2 }
{
blend diffusemap map textures/katq4dm3/rock_plain.tga inverseVertexColor scale 1.2, 1.2 }
{
blend specularmap
map textures/katq4dm3/rock_plain_s.tga
inverseVertexColor
scale 1.2, 1.2
}
}

The text highlighted bold above is the material reference that’s placed in the BITMAP section of the ASE file (as mentioned above). For Quake 4 it needs “//q4base/” in front of it, so the full path would be;

//q4base/textures/katq4dm3/stonedirtMix

This will then instruct the game to pull in the material being reference and apply it to the model.

Because this mesh has vertex colours applied to it so it’ll have textures blended over it’s surface it needs to have “inverseVertexColor” and “vertexColor” added to one of the other texture set within the material – in this case the ‘rock’ texture is inverseVertexColor and the dirt is vertexColor; it’s just a question of swapping them around until you have the right texture applied to the right vertex colour. For more information on this read theĀ texture/vertex painting tutorial here.

Z-fighting & Editor/Model Alignment

The screen-shot below shows whatĀ shouldĀ happen when the model is imported into the editor (the model itself is placed in q4base/models/mapobjects/katq4dm3, basically theĀ projects development folder). The pink area that can be seen is the brushwork hull showing through because of ‘z-fighting‘ in the editor – this is because the model surface is sitting on *exactly* the same plane (surface) as the caulk brush so the editor can’t decide which surface it should be rendering when in normal ‘edit’ mode. As a result surfaces like this tend to ‘flicker’ when the camera is moved about as the view tries to render both surfaces at the same time.

This is anĀ none real-time problemĀ and does not show up in game, it’s purely an editor issue. The texture is quite blurry at present in this shot because it’s being rendered 1:1; the resolution is based on what’s being read in from the UV map applied to the model. As mentioned previously this isn’t anything to worry about at this point. What is shown is how the texture follows the flow of the mesh, something that should be watched for when UV mapping the mesh; having texture alignment go all over the place is distracting to the player but more importantly (for ‘creatives’) , it looks unnatural, so you have to be mindful of that.

It should in theory happen naturally based on the UV mapping if it was done in a similar fashion to what was mentioned above about matching UV mapped mesh sections so the textures flow as best they can over different surfaces; it’s not absolutely necessary though.

Z-Fighting indicates surfaces match up correctly

Z-Fight flickering (where two or more surfaces ‘fight’ to be drawn to screen) denotes brush and mesh surfaces being coincidental – there are no gaps between the two

Some exposed brushwork needs to be adjusted to fit the mesh

A couple of areas are shown below that need adjusting because the mesh was shaped beyond the caulk hull. Because the hull is made from basic blocks doing this kind of adjustment is relatively straightforward; another reason for blocking the caulk hull out before doing anything

Or the mesh needs to be adjusted to fit ithin the bounds of the brush hull

Overlapping model and brush structure – a section of the mesh stick up above the caulk hull so one or the other needs to be adjusted else the area will result in a ‘hall of mirrors’ error


Spread the love