MAP (file format)
This page covers all major variants of the MAP file format, beyond that which is used by GoldSrc, to provide a comprehensive overview of the file format as a whole and explain why compatibility isn't trivial.
The MAP file format is a plain-text file format used by GoldSrc, id Tech 2, id Tech 3, and id Tech 4, which stores entities and level geometry in a format which can be understood by the map compilers (and in the case of id Tech 4, the game itself). Source's VBSP also has residual support for compiling from MAP files.
At its core, the format consists of several entities, each of which is optionally capable of storing one or more brushes, (only in ) patch meshes, and (only in ) displacements.
Variants
Header text | Supported by | Information |
---|---|---|
Quake I (Legacy) | Most tools, except Hammer 4.x | The original format. |
Quake I (Valve220) | All GoldSrc tools, most modern Quake Engine tools, and Hammer 4.x | Variant of the Quake 1 (Legacy) format with additional texture UV precision. Introduced by Worldcraft 2.0; now standard. |
Quake II (Legacy) | All Quake II Engine tools, and most id Tech 3 tools | Variant of Quake 1 (Legacy) format which optionally stores three additional WAL metadata flags. |
Quake II (Valve220) | J.A.C.K., NetRadiant-Custom, and TrenchBroom | Variant of Quake 2 (Legacy) format with Valve220-style UVs. Introduced by J.A.C.K.; now standard. |
Quake III (Axial Projection) | All id Tech 3 tools | Variant of Quake 2 (Legacy) format with support for patch meshes (analogous to displacements, but use Bézier curves instead of an array of vertices).
While Quake 3 MAP files can technically store both standard brushes and brush primitives, map editors usually require selecting one or the other to write the file as. The Quake 3 MAP format still supports the metadata flags from Quake 2, including on patch meshes and brush primitives, although only the detail flag (0x08000000) is ordinarily used; this information is instead usually stored in the material definitions. |
Quake III (Brush Primitives) | Most id Tech 3 tools, except Q3Radiant and TrenchBroom | |
Quake III (Valve220) | J.A.C.K., NetRadiant-Custom, TrenchBroom | Variant of Quake 3 format with Valve220-style UVs. Introduced by J.A.C.K.; not yet standard. |
Doom 3 (Axial Projection) | All id Tech 4 tools | Variant of Quake 3 format which can store patch meshes and brush primitives differently [Elaborate?].
Like Quake 3, a map can technically store both standard brushes and brush primitives, but editors write the files as one or the other. Standard brushes are generally considered deprecated in favor of brush primitives. |
Doom 3 (Brush Primitives) | Most id Tech 4 tools, except TrenchBroomBFG | |
Doom 3 (Valve220) | TrenchBroomBFG | Variant of Doom 3 format with Valve220-style UVs for standard brushes. Introduced by TrenchbroomBFG; not standard. |
Source (Valve400) | None | Variant of Quake I Valve220 format with support for displacements. |
Doom Eternal | idStudio | Variant of Doom 3 brush primitives format with additional metadata (Converter). |
Entities
KeyValues
Geometry
Brushes
In most versions of the format, brushes are stored as a set of planes, rather than a set of vertices. Each plane is defined via three points, and the intersection of these planes determines where edges and vertices lay. Due to this, brushes cannot be concave, and a missing face will result in other faces continuing infinitely, causing compiler errors.
Quake I
A simple 6-sided brush in the original Quake 1 format would look like this:
{ ( -16 -64 -16 ) ( -16 -63 -16 ) ( -16 -64 -15 ) mmetal1_2 -0 -0 -0 1 1 ( -64 -16 -16 ) ( -64 -16 -15 ) ( -63 -16 -16 ) mmetal1_2 -0 -0 -0 1 1 ( -64 -64 -16 ) ( -63 -64 -16 ) ( -64 -63 -16 ) mmetal1_2 0 0 0 1 1 ( 64 64 16 ) ( 64 65 16 ) ( 65 64 16 ) mmetal1_2 0 0 0 1 1 ( 64 16 16 ) ( 65 16 16 ) ( 64 16 17 ) mmetal1_2 -0 -0 -0 1 1 ( 16 64 16 ) ( 16 64 17 ) ( 16 65 16 ) mmetal1_2 -0 -0 -0 1 1 }
Each plane can be summed up like so:
( x1 y1 z1 ) ( x2 y2 z2 ) ( x3 y3 z3 ) TEXTURENAME Uoffset Voffset rotation Uscale Vscale
( x1 y1 z1 ) ( x2 y2 z2 ) ( x3 y3 z3 )
is the set of three points in 3D space that define the plane.TEXTURENAME
is the name of the texture (or in later engines, the material) that appears on the face. This is case insensitive, and never includes a file extension.Uoffset Voffset
offsets the UV coordinates of the plane, resulting in shifting the texture on the U and/or V axis. These are projected onto the face using axial projection.rotation
stores the rotation of the texture.Uscale Vscale
stores the texture scale. 1 means the texture is displayed at 1 texel per quake unit.
Valve220
The original Quake MAP format uses axial projection to apply textures onto faces. This results in undesirably stretched textures on slanted surfaces. To rectify this, Valve came up with the Valve220 format, which stores the texture offsets as 1-dimensional arrays, instead of singular numbers, as so:
( x1 y1 z1 ) ( x2 y2 z2 ) ( x3 y3 z3 ) TEXTURENAME [ Ux Uy Uz Uoffset ] [ Vx Vy Vz Voffset ] rotation Uscale Vscale
- The first three values of each texture offset array are the normal vectors of the U and V axes.
- The third value is the offset itself, like the axial projection format.
rotation
value should match the orientation of the UV normal vectors. Not doing so will result in editor bugs, compiler errors, and/or invalid brushes!A simple 6-sided brush in the Quake 1 format using Valve220 projection would look like this:
{ ( -16 -64 -16 ) ( -16 -63 -16 ) ( -16 -64 -15 ) mmetal1_2 [ 0 -1 0 -0 ] [ 0 0 -1 -0 ] -0 1 1 ( -64 -16 -16 ) ( -64 -16 -15 ) ( -63 -16 -16 ) mmetal1_2 [ 1 0 0 -0 ] [ 0 0 -1 -0 ] -0 1 1 ( -64 -64 -16 ) ( -63 -64 -16 ) ( -64 -63 -16 ) mmetal1_2 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 ( 64 64 16 ) ( 64 65 16 ) ( 65 64 16 ) mmetal1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 ( 64 16 16 ) ( 65 16 16 ) ( 64 16 17 ) mmetal1_2 [ -1 0 0 -0 ] [ 0 0 -1 -0 ] -0 1 1 ( 16 64 16 ) ( 16 64 17 ) ( 16 65 16 ) mmetal1_2 [ 0 1 0 -0 ] [ 0 0 -1 -0 ] -0 1 1 }
The Valve220 format was introduced for Half-Life, and is required for GoldSrc compilers. Since the BSP format used by all IdTech engine games store UV coordinates that are at least as accurate as Valve220 (and sometimes moreso), the Valve220 format has mostly supplanted the legacy axial projection format by mappers, as many modern compilers for IdTech engines support Valve220.
The worldspawn keyvalue pair "mapversion" "220"
indicates that a MAP file uses Valve220 texture projection. Map converters and decompilers that output to Valve220 should add the KV if it is not already present.
Quake II
Quake II's format optionally allows for three additional values to be stored as the
( x1 y1 z1 ) ( x2 y2 z2 ) ( x3 y3 z3 ) path/texturename Uoffset Voffset rotation Uscale Vscale SurfaceFlag ContentsFlag Value
These represent the same values as in a WAL file, and are stored as Base 10 integers (unlike in code, where they are usually declared in hexadecimal form). These values are optional, however. If not present, the compilers will use the values stored in the WALs themselves.
A brush in the original Quake II format could look like this:
J.A.C.K. introduced a modified version of the format which uses Valve220 notation, as such:
( x1 y1 z1 ) ( x2 y2 z2 ) ( x3 y3 z3 ) path/texturename [ Ux Uy Uz Uoffset ] [ Vx Vy Vz Voffset ] rotation Uscale Vscale SurfaceFlag ContentsFlag Value
A brush in this modified version of the format could therefore look like this:
Most modern editors (ex: ) and compilers (ericw-tools, KMBSP 1.14, q2tools220) support this modified format.
Since the Quake II MAP format is largely unchanged from the Quake I format, it can be converted to the older format without losing any geometry by simply stripping the extra flags. This can be done either with ericw-tools (maputil.exe --strip_extended_info input.map
) or by opening the file in J.A.C.K. using a game profile configured for the Quake I/Hexen II or Half-Life/TFC "Map Type". It is not necessary to do any conversions to go from Quake I to Quake II.
If using the Quake I format as an intermediary for porting to Source, these additional steps are not necessary.
Brush primitives
GtkRadiant and its forks allow storing brushes as "brush primitives" (brushdef) instead of standard brushes. This method allows for more control over brush texture alignment than standard brushes. Additionally, unlike standard brushes, the texture UVs of brush primitives are normalized to a 0 to 1 range, so texture scale is independent of texture resolution.
A map can be converted between standard brushes and brush primitives using maputil from ericw-tools. To convert to brush primitives:
To convert to regular brushes, using Valve220 texture projection:
Note that conversion requires the tools to be able to access the textures to properly convert UV coordinates; if maputil cannot find a given texture, it will assume a 64x64 resolution. If a map makes use of textures from PK3 files or materials from .shader files that don't match the name of a texture, it may be preferable to use NetRadiant-Custom to convert the map instead[How?], to preserve proper UV coordinates.
Patch meshes
Patch meshes are stored in the MAP file as a set of Bézier curves, which dictate how the mesh is automatically tessellated at runtime.
Displacements
MAP files can store Source 1 displacements[How?], as VBSP still supports for compiling MAP files. The "mapversion" keyvalue should be 400. Some forks of Q3Map2 also support compiling these displacements into Quake III BSPs.
See also
- VERC/MAP file format - casual explanation of the Quake 1 Valve220 MAP format
- VMF
- RMF
External links
- Quake Map Format
- Quark Documentation - Discusses the way the MAP file format stores brush faces and Bézier curves