-
Notifications
You must be signed in to change notification settings - Fork 0
MDL
MDL is an internal model format used by Rockstar Games Leeds based loosely on the Quake/Valve model format of the same name; do not confuse it with MDL files used by other video games. This format is used in GTA Liberty City Stories, GTA Vice City Stories, Chinatown Wars, as well as Manhunt 2.
The format is tightly bound to the game platform, such as PSP or PS2. In other words, unlike the DFF format used in previous GTA games before RenderWare was acquired by EA Games, MDL is not cross-platform.
The PSP version of MDL was researched by J-Fox, who also wrote a program that reads the structure of MDL files and renders geometry, UV coordinates, and textures from *.chk files. Like many other tools for GTA: LCS and GTA: VCS, J-Fox did not publicly release this program.
The PS2 version of MDL was researched by AK-73, also known as Alex. He wrote a unique 3D Studio Max script for importing any *.mdl file from the PS2 version. For more information about the script, see the article about the MDL importer.
All *.mdl files have a global header and an Atomic header. The remaining sections of an *.mdl file are strictly platform-specific: PSP or PS2.
0x00 4b: signature "ldm"
0x04 4b: 0
0x08 4b: size of the MDL dump-container
0x0C 4b: size of the data inside the MDL container
0x10 4b: pointer to the Pointer Reallocation table
This table contains pointers to all pointers in the file, so they can be converted
from local pointers to global pointers in memory.
0x14 4b: number of pointers in the Pointer Reallocation table
0x18 4b: pointer to the Methods table
The Methods table is divided into two sections.
0x1C 2b: number of pointers in the first section of the Methods table
Virtual methods. Used only in DTZ.
0x1E 2b: number of pointers in the second section of the Methods table
Rendering methods. Present in MDL and DTZ. Points to a special field in Atomic.
The MDL header is not unique. It is a prebuilt header whose data, after the game loads the MDL and converts every pointer in the file to an absolute value, is transferred into the corresponding fields of the binary IDE inside the DTZ.
0x0 Xb: array of pointers to model Atomics.
The number of pointers, meaning the number of separate models, is defined in the model IDE.
The only difference between the LCS and VCS headers is the larger array of pointers to primary-color materials.
0x0 4b: pointer to Clump
0x4 4b: number of extras
0x8 4b: pointer to an array of pointers to extra model Atomics
0xC 100b: 25 pointers to materials recolored by the primary color
0x70 100b: 25 pointers to materials recolored by the secondary color
0x0 4b: pointer to Clump
0x4 4b: number of extras
0x8 4b: pointer to an array of pointers to extra model Atomics
0xC 120b: 30 pointers to materials recolored by the primary color
0x84 100b: 25 pointers to materials recolored by the secondary color
0x0 4b: pointer to collision data. Usually embedded in the MDL.
0x4 4b: pointer to Clump
0x0 16b: Clump
Contains a sub-section called the Clump-Atomic cycle, used to cycle through all Atomics belonging to this Clump. It is also used to bind an Atomic to a Clump. An equivalent sub-section is present in Atomic.
It is important to note that vehicle extras are loaded separately and do not belong to the model Clump. They do not participate in the Clump-Atomic cycle.
0x0 4b: section ID
0x4 4b: jump to the main frame, or Root Frame
Clump-Atomic cycle sub-section:
0x8 4b: pointer to the Clump-Atomic cycle sub-section of the first Atomic.
If there are no Atomics, this points to itself.
0xC 4b: pointer to the Clump-Atomic cycle sub-section of the last Atomic.
If there are no Atomics, this points to itself.
Contains a sub-section called the Frame-Atomic cycle, used to cycle through Atomics belonging to this Frame. It is also used to bind an Atomic, and therefore geometry, to a Frame. An equivalent sub-section is present in Atomic.
0x0 4b: section type
0x4 4b: offset to the parent frame, or Parent Frame
Frame-Atomic cycle sub-section:
0x8 4b: pointer to the Frame-Atomic cycle sub-section of the first Atomic.
If no Atomics are attached, this points to itself.
0xC 4b: pointer to the Frame-Atomic cycle sub-section of the last Atomic.
If no Atomics are attached, this points to itself.
0x10 64b: matrix4x4: transformation matrix for the Frame and the geometry attached to it,
relative to the parent Frame.
To calculate the global transform of the Frame, multiply this matrix by the
parent Frame matrix.
0x50 64b: matrix4x4: global transformation matrix for the Frame or the geometry attached to it.
In LCS, skinned models usually have an identity matrix here.
0x90 4b: pointer to the lower-level frame, or Child Frame
0x94 4b: pointer to the frame at the same hierarchy level, or Sibling Frame
0x98 4b: pointer to the main frame, or Root Frame
0x9C 4b: bone ID.
Used only for ped models and cutscene objects. In all other cases, this is -1.
0xA0 4b: pointer to bone parameters.
Used only for ped models and cutscene objects.
0xA4 4b: pointer to the frame name
0xA8 4b: model information-node ID.
Used only in vehicle models.
0x0 4b: section type
0x4 4b: offset to the parent frame, or Parent Frame
Frame-Atomic cycle sub-section:
0x8 4b: pointer to the Frame-Atomic cycle sub-section of the first Atomic.
If no Atomics are attached, this points to itself.
0xC 4b: pointer to the Frame-Atomic cycle sub-section of the last Atomic.
If no Atomics are attached, this points to itself.
0x10 64b: matrix4x4: transformation matrix for the Frame and the geometry attached to it,
relative to the parent Frame.
To calculate the global transform of the Frame, multiply this matrix by the
parent Frame matrix.
0x50 64b: matrix4x4: global transformation matrix for the Frame or the geometry attached to it.
In LCS, skinned models usually have an identity matrix here.
0x90 4b: pointer to the lower-level frame, or Child Frame
0x94 4b: pointer to the frame at the same hierarchy level, or Sibling Frame
0x98 4b: pointer to the main frame, or Root Frame
0x9C 4b: alignment
0xA0 4b: bone ID.
Used only for LCS ped models and cutscene objects. In all other cases, this is -1.
In VCS, this field is unused and equals 0.
0xA4 4b: pointer to bone parameters.
Used only for ped models and cutscene objects.
0xA8 4b: pointer to the frame name
0xAC 4b: model information-node ID.
Used only in vehicle models.
0 - simple frame
1 - wheel_rf_dummy
2 - wheel_rm_dummy
3 - wheel_rb_dummy
4 - wheel_lf_dummy
5 - wheel_lm_dummy
6 - wheel_lb_dummy
7 - bump_front_dummy
8 - bump_rear_dummy
9 - wing_rf_dummy
10 - wing_rr_dummy
11 - door_rf_dummy
12 - door_rr_dummy
13 - wing_lf_dummy
14 - wing_lr_dummy
15 - door_lf_dummy
16 - door_lr_dummy
17 - bonnet_dummy
18 - boot_dummy
19 - windscreen_dummy
0 - simple frame
1 - unknown
2 - wheel_rf_dummy
3 - wheel_rm_dummy
4 - wheel_rb_dummy
5 - wheel_lf_dummy
6 - wheel_lm_dummy
7 - wheel_lb_dummy
8 - door_rf_dummy
9 - door_rr_dummy
10 - door_lf_dummy
11 - door_lr_dummy
12 - bump_front_dummy
13 - bump_rear_dummy
14 - wing_rf_dummy
15 - wing_lf_dummy
16 - wing_rr_dummy
17 - wing_lr_dummy
18 - bonnet_dummy
19 - boot_dummy
20 - windscreen_dummy
4b: section type
4b: 0
4b: 1
4b: pointer to Clump:TextureList:String
4b: number of textures
4b: number of textures, repeated
4b: pointer to the inverse bone-matrix table
4b: alignment, AAAAAAAA
4b float: X coordinate of the model bounding sphere
4b float: Y coordinate of the model bounding sphere
4b float: Z coordinate of the model bounding sphere
4b float: radius of the model bounding sphere
4b: model size + material count.
The first 12 bits are the material count, and the remaining 20 bits are the size.
4b: flag used by the game engine to determine which additional vertex-parameter sections
are present in the model, such as normals, prelight, skinning, and UV mapping.
2b: total vertex count in the model
2b: offset to the first tri-strip
12b: 6x2b bounding box:
MinX, MinY, MinZ, MaxX, MaxY, MaxZ as signed shorts.
These are decoded the same way as vertex coordinates, using ScaleFactor and TranslateFactor.
4b float: X coordinate multiplier, ScaleFactorX
4b float: Y coordinate multiplier, ScaleFactorY
4b float: Z coordinate multiplier, ScaleFactorZ
4b float: X coordinate offset, TranslateFactorX
4b float: Y coordinate offset, TranslateFactorY
4b float: Z coordinate offset, TranslateFactorZ
0x0 4b: section type
0x4 4b: pointer to the parent Frame
Frame-Atomic cycle sub-section:
0x8 4b: pointer to the Frame-Atomic cycle sub-section of the next Atomic.
If this is the last Atomic, it points to the Frame-Atomic cycle of the Frame.
0xC 4b: pointer to the Frame-Atomic cycle sub-section of the previous Atomic.
If this is the first Atomic, it points to the Frame-Atomic cycle of the Frame.
0x10 4b: may contain any value
0x14 4b: offset to geometry
0x18 4b: offset to Clump
Clump-Atomic cycle sub-section:
0x1C 4b: pointer to the Clump-Atomic cycle sub-section of the next Atomic.
If this is the last Atomic, it points to the Clump-Atomic cycle of the Clump.
If it is not attached to a Clump, this is 0.
0x20 4b: pointer to the Clump-Atomic cycle sub-section of the previous Atomic.
If this is the first Atomic, it points to the Clump-Atomic cycle of the Clump.
If it is not attached to a Clump, this is 0.
0x24 4b: rendering method ID
0x28 2b: IDE ID, set by the engine. Usually -1 in the file.
0x2A 2b: parameters for breakable or detachable vehicle parts
0x2C 4b: pointer to bone parameters.
Used only for ped models and cutscene objects.
0x30 4b: may contain any value
12b: point3 X Y Z, unused
4b: U multiplier
4b: V multiplier
4b: material color, unused
4b: jump to the beginning of the tri-strips, relative to the geometry section
2b: number of tri-strips in the material
2b: texture number from TextureList
This exists only in *.wrld files. Compared to the *.mdl version, it is compressed for faster reading and to save console memory. Instead of texture names, it contains texture IDs, or hashes.
[2b int] number of materials
[2b int] size of the material section
[4b int] number of materials
[4b float] unknown. Usually 0 for LODs.
[2b int] texture ID
[2b int] tri-strip size.
Requires a logical AND with 0x7FFF, because the first bit is a backface-culling flag.
[2b half float] U multiplier
[2b half float] V multiplier
[2b] unknown, possibly flags
[12b 6x signed int] bounding box
[4b int] tri-strip size.
Must be divided by 2 as integer division.
If the division leaves a remainder of 1, backface culling is enabled for the current tri-strip.
[2b int] texture ID
[2b half float] U multiplier
[2b half float] V multiplier
[2b] unknown, possibly flags
[12b 6x signed int] bounding box
The row can have two possible lengths: 10 bytes or 24 bytes. This is determined using the float in the header. If the float is not 0, the row length is 24 bytes. If the float is 0, the row length is 10 bytes.
[2b int] texture ID
[2b int] vertex count in the tri-strip.
Requires a logical AND with 0x7FFF, because the first bit is a backface-culling flag.
[2b half float] U multiplier
[2b half float] V multiplier
[2b] unknown, possibly flags
[2b] unknown, possibly flags. This section may be absent.
[12b 6x signed int] bounding box. This section may be absent.
[2b int] texture ID
[2b int] vertex count in the tri-strip.
Requires a logical AND with 0x7FFF, because the first bit is a backface-culling flag.
[2b half float] U multiplier
[2b half float] V multiplier
[2b] unknown, possibly flags
[2b] unknown, possibly flags
[12b 6x signed int] bounding box
The bounding-box coordinates are decoded the same way as tri-strip coordinates: divide each integer by 32768, then multiply by the model scaling value.
The U and V multipliers are half-precision floating-point values.
These are MDL files embedded inside a DTZ file. The format does not differ in any way, so the MDL importer can read a DTZ as an MDL and import models from it.
Tri-strips are a series of connected triangles and vertices. They are used in games from this series specifically for fast rendering.
All model geometry is divided into tri-strips. Tri-strip support is also present in GTA: SA DFF files.
Reading the first tri-strip in an MDL begins immediately after the material list. The beginning of a tri-strip is marked by the flag 6C018000. After the flag, the vertex count of the tri-strip is repeated twice. Then comes the technical sector 40404020, which is needed by the engine. It is not important for importing the model.
After that come the actual blocks containing model elements.
Contains all vertex coordinates in the tri-strip. One coordinate is encoded as a signed short, 2 bytes, and is calculated like this:
CoordX = (CoordX as Float) / 32768 * ScaleFactorX + TranslateFactorXY and Z are calculated the same way.
The block size is:
block header, 4 bytes + XYZ, 6 bytes * vertex count in the tri-strip
The geometry block ends with the technical block 50505020, which is needed by the engine. It is not important for importing the model.
Contains all UV-mapping coordinates in the tri-strip. One coordinate is encoded as an unsigned byte, 1 byte. It is calculated by dividing by 255 for models from WRLD/LVZ, or by dividing by 128 for MDL.
The block size is:
block header, 4 bytes + UV, 2 bytes * vertex count in the tri-strip
Contains RGBA vertex prelight data. It is used only in GTA LCS and GTA VCS. It is stored in 16-bit RGBA 5551 format.
The block size is:
block header, 4 bytes + RGBA, 2 bytes * vertex count in the tri-strip
Contains RGBA vertex prelight data. It is used only in Manhunt 2. Each color channel is encoded as one byte. It must be read as BGRA.
The block size is:
block header, 4 bytes + RGBA, 4 bytes * vertex count in the tri-strip
Contains all normal-vector coordinates in the tri-strip. One coordinate is encoded as a signed byte, 1 byte, and is calculated by dividing by 127.
The block size is:
block header, 4 bytes + XYZ, 3 bytes * vertex count in the tri-strip
Contains the vertex-weight table used for animation. Each influence consists of a bone ID and a weight:
bone ID: 1 byte, divide by 4 using integer division
weight: 3 bytes
Each vertex contains 4 bone IDs. In other words, each vertex is controlled by 4 bones during animation.
The block size is:
block header, 4 bytes + ((id_weight, 4 bytes * 4) * vertex count in the tri-strip)
Reading the next tri-strip begins immediately after the tri-strip end flag, 14000006. The total number of tri-strips in the model is also stored in the Clump.
Information will be added later.
This part of the article is unfinished. You can help the project by correcting and expanding it.
The geometry is an array of tri-strips, UV coordinates, prelight, and normals.
The number of vertices in a tri-strip is stored in the material row.
The first tri-strip begins immediately after the material list.
tri-strip size = vertex count * one vertex-array row
In WRLD, one vertex-array row is 10 bytes.
Each next tri-strip begins after the end of the previous one.
One vertex-array row is 10 bytes:
2b: UV.
Coordinates are calculated the same way as on PS2.
2b: VCol.
The prelight calculation is the same as on PS2.
2b: xCoord.
Calculated using WRLD scaling.
2b: yCoord.
Calculated using WRLD scaling.
2b: zCoord.
Calculated using WRLD scaling.
The Manhunt 2 MDL version has a similar structure on all platforms except Wii. It can be easily converted to any other version by simply transforming the format in which the game stores model geometry.
An MDL can contain either one model or several models. The reading principle is described below.
The PS2 and PSP MDL versions have the .DFF extension.
Header 1 has the typical structure used in all files on the engine. It differs only by signature. See the section about the main MDL header structure.
This is a loop that reads each separate model.
Header size: 8 bytes.
4b: jump to the first row of the model-search cycle
4b: jump to the last row of the model-search cycle
Model-search cycle row:
4b: offset to the next sub-model
4b: offset to the previous sub-model
4b: offset to the current sub-model
When jumping to the offset of the current sub-model, the game reads one more intermediate offset, which finally leads to the geometry-reading cycle of the current sub-model.
Header size: 180 bytes.
4b: offset to the list of used textures.
The first texture receives index 0, the second receives index 1, and so on.
4b: number of textures used in the model
4b: offset to bones for the current model.
If this is 0, the model has no attached bones.
4b: unknown
4b: unknown, usually 1
12b: padding
4b: signature, 0x45D454
4b: model size
4b: unknown, usually 0
4b: number of materials in the model
4b: number of polygon indices.
Polygon count = polygon index count / 3.
16b: 4 floats: X, Y, Z, and bounding-sphere radius
12b: 3 floats, usually 1.0, 1.0, 1.0
4b: number of vertices in the model
12b: padding
4b: stride for reading one vertex
44b: unknown data.
Changing or zeroing these bytes has no visible effect in-game.
4b: vertex parameters.
The game uses these parameters to determine which sections are present in the vertices,
such as Normals, VCol, Skin, and so on.
32b: unknown data.
Changing or zeroing these bytes has no visible effect in-game.
Located immediately after the header. Material-row length: 44 bytes.
24b: 6 floats: bounding box
2b: number of polygon indices for the current material.
Polygon count = polygon index count for the current material / 3.
2b: texture ID
2b: number of polygon indices to skip before starting to read the required indices
for the current material.
14b: unknown.
Changing or zeroing these bytes has no visible effect in-game.
The polygon-index table is located immediately after the material list. Each index is 2 bytes. The number of indices is specified in the header.
Unlike DFF, where all vertex parameters are stored in separate tables, the PC-version MDL reads all parameters immediately after the vertex coordinates.
The vertex-row size is determined by the vertex parameters in the header.
Approximate structural order of vertex parameters in the PC-version MDL:
12b: 3 floats: X, Y, Z
20b: skinning:
4 floats [4b] for weights, 4 bytes [1b] for bone IDs
8b: normals:
3 words [2b] for X, Y, Z normal components, then 2b = 0
4b: VCol.
Stored as BGRA, not RGBA.
8b: UV1, 2 floats
8b: UV2, 2 floats.
Usually found in character models. This is the unwrap for bloodstain textures on the body.
File formats:
.anim
.at3
.cam
.chk/.xtx
.col2
.cut
.dtz
.ifp
.img/.dir
.irx
.gxt
.lvz
.mdl
.pss
.raw/.sdt
.scm
.vb
.wrld
Tools:
Apache
Console Texture Explorer (PSP/PS2)
GTA Stories IMG Tool
GTA Stories Texture Viewer
GTA Stories Texture Explorer
GTA Stories RAW Editor
GXT Editor
JPCSP
MDL importer
MF Audio
PCSX2
PPSSPP
Stories WRLD Tool
GTA Stories Map Converter v1.0
UMD Gen
YAIE