MDL file format (FSX)
| This page is a work-in-progress. Generic message - Please note some detail may possibly be missing or incorrect. |
This document describes the structure of FsX MDL files. This document is mainly useful for people who want to read or decode these MDL files in a tool.
Compared to the Fs2004 MDL format there are quite a few changes. One of the biggest is that aircraft and scenery MDL files now have the same format. At the moment the knowledge in this document mainly comes from evaluating simple scenery objects, so it is certainly not yet complete. If you have anything to add, please do so.
MDL sections
The MDL file uses the RIFF format, this means that the file consists of different sections. Each section starts with a four character label, followed by the size of the content in bytes (this size is thus without the length of the header itself). The table below shows how the different section can be nested.
| Name | Description | Parent section |
| RIFF | General RIFF section (covers entire file) | None |
| MDLH | MDL header | RIFF |
| MDLG | Object GUID | RIFF |
| MDLN | Object friendly name | RIFF |
| SMAP | Unknown | RIFF |
| PARA | Parameters Block | RIFF |
| CRAS | Object crashbox | RIFF |
| BBOX | Object boundingbox | RIFF |
| RADI | Object radius | RIFF |
| MDLD | Exterior Node Root | RIFF |
| TEXT | Texture list | MDLD |
| MATE | Material list | MDLD |
| INDE | Triangle index list | MDLD |
| VERB | Vertex buffer list | MDLD |
| VERT | Vertex list | VERB |
| TANS | Tangent Space list (?) | VERB |
| BMAP | Bone Map (?) | VERB |
| SKIN | Skin weight list (?) | VERB |
| TRAN | Static transformation matrices | MDLD |
| AMAP | Animation Map | MDLD |
| SCEN | Scenegraph Node Root | MDLD |
| SGAL | Scenegraph Animation Linkage | MDLD |
| SGVL | Scenegraph Visibility Linkage | MDLD |
| SGJC | Scenegraph Joint Constraints | MDLD |
| SGBR | Scenegraph Bone Reference | MDLD |
| LODT | LOD table | MDLD |
| LODE | LOD Entry | LODT |
| PART | Part list | LODE |
| ANIB | Animation Block | MDLD |
| PLAL | Platform List | MDLD |
| PLAT | Platform | PLAL |
| REFL | Attachpoint List | MDLD |
| REFP | Attach point | REFL |
The main RIFF section itself has one additional parameter, this is a four character string that indicates the type of RIFF MDL file. For an FsX MDL file the value should always be MDLX.
The following subsection show more details about the content of these different sections.
MDLH
This the FS MDL object header. It seems to contain of an integer that always has the value of 123456 and a float of value 10. The purpose of these parameter is unknown.
MDLG
This section stores the object GUID. The GUID is stored in the following parts:
unsigned long data1 unsigned short data2 unsigned short data3 unsigned char data4[8]
In hexadecimal form the GUID is then written as:
{data1-data2-data3-data4[0:1]-data4[2:7]}
MDLN
This section contains a string with the friendly name of the object.
SMAP
Unknown at the moment.
PARA
This is the ParamsBlock section, containing parameter block data.
CRAS
This section stores the crashtree of the object. It has first two unknown integer values, then there are 3 float values giving the front lower left corner of the object, then 3 float values giving the length, height, and width, then another unknown integer, and then the branches of the tree, which are all integer values (instead of bytes which had been used in FS2004). If the value of a cell is -1 the cell is solid, if it is -2 the cell is free, every other value is the offset of the octet of the next lower node in the branch.
BBOX
This section stores the bounding box of the object in the following format:
float xmin float ymin float zmin float xmax float ymax float zmax
RADI
This section stores the radius of the object as a float.
MDLD
This section contains the actual data defining the object.
TEXT
This section contains the list of all textures of the object. Each texture is given as a 64 character string. Unlike the Fs2004 format no additional parameters are stored in the texture list, only the texture name.
MATE
This section contains a list of all materials of the object. Each material is defined by a 120 byte long record. The definition of this record is given below:
int material_flags int material_flags_2 int diffuse_texture_index int detail_texture_index int bumpmap_texture_index int specular_texture_index int emissive_texture_index int reflection_texture_index int fresnel_texture_index float diffuse_color_R float diffuse_color_G float diffuse_color_B float diffuse_color_A float specular_color_R float specular_color_G float specular_color_B float specular_color_A float specular_power float detail_map_scale float bump_map_scale float reflection_scale float precipitation_offset float specular_bloom_floor float ambient_light_scale float (?) int source_blend int destination_blend int alpha_test_function float alpha_test_threshold float final_alpha_multiply
material_flags is a bitmask:
0x00000001: material is specular 0x00000002: material has a diffuse texture (diffuse color is only used as a fallback) 0x00000004: material has a bumpmap texture 0x00000008: material has a specular texture 0x00000010: material has a detail texture 0x00000020: material has a reflection texture 0x00000040: Use global environment map as reflection 0x00000080: material has an emissive texture (for night) 0x00000100: material has a FresnelRamp texture: Reflection 0x00000200: material has a FresnelRamp texture: Diffuse 0x00000400: material has a FresnelRamp texture: Specular 0x00000800: Apply offset to start of Precipitation 0x00001000: Take into account Precipitation 0x00002000: Blend environment by inverse of diffuse alpha 0x00004000: Blend environment by specular map alpha 0x00008000: Assume vertical normal 0x00010000: Z-Write alpha 0x00020000: No Z Write 0x00040000: Bloom material by copying 0x00080000: Bloom material modulating by alpha 0x00100000: Volume shadow 0x00200000: No shadow 0x00400000: Z-Test Alpha 0x01000000: Set final alpha value at render time 0x04000000: Skinned mesh 0x08000000: Allow bloom 0x10000000: Allow emissive bloom 0x20000000: Blend diffuse by diffuse alpha 0x40000000: Blend diffuse by inverse of specular map alpha 0x80000000: Prelit vertices
material_flags_2 is a bitmask:
0x00000001: Blend constant 0x00000002: Force Texture Address Wrap 0x00000004: Force Texture Address Clamp 0x00000008: Double sided 0x00000010: Emissive Mode: AdditiveNightOnlyUserControlled 0x00000040: Emissive Mode: MultiplyBlend 0x00000080: Emissive Mode: MultiplyBlendUserControlled 0x00000100: Emissive Mode: Additive 0x00000200: Emissive Mode: AdditiveUserControlled
The source_blend and destination_blend parameters seem to use the following enumeration:
1 zero 2 once 3 srcColor 4 invSrcColor 5 srcAlpha 6 invSrcAlpha 7 destAlpha 8 invDestAlpha 9 destColor 10 invDestColor
The alpha_test_function parameter seems to use the following enumeration:
1 never 2 less 3 equal 4 lessEqual 5 greater 6 notEqual 7 greaterEqual 8 always
The z_write_alpha parameter has a value of 1 (float) when it is enabled (TRUE).
INDE
This section contains of a lot of triangles, each given by three short values. These values are the indices of the vertices to use. In the PART list an offset is specified for these indices, so the first vertex of a part seems to be zero always.
VERB
This section gives the vertex buffer of the object.
VERT
This section contains a list of vertices of the object. Each vertex is given by a 32 byte record. The definition of this record is given below:
float position_x float position_y float position_z float normal_x float normal_y float normal_z float texture_mapping_x float texture_mapping_y
Multiple VERT sections followed by correspondent TANS and optional BREF / SKIN sections can be defined inside VERB buffer.
TANS
This section contains tangent space list data for correspondent VERT section. The first parameter of this list is UINT, which represents tangent space list index within VERB buffer (0x00000000 for first section, 0x00000001 for second and so on). Then for each vertex in correspondent VERT section two vectors are given that define a plane that is tangent to the vertex (these vectors are defined as three floats). This data only seems to be set for textured polygons, untextured polygons have null vectors defined here.
BMAP
This section contains bone map reference data for correspondent VERT section. The first parameter of this list is UINT, which represents bone map index within VERB buffer. The rest represents bone reference data. Format isn't investigated yet.
SKIN
This section contains skin weights list reference data for correspondent VERT section. The first parameter of this list is UINT, which represents skin weight list index within VERB buffer. The rest represents skin weight data for each(?) vertex in correspondent VERT section. Format isn't investigated yet.
TRAN
This section stores the static transformation matrices. Each matrix is defined by 16 floats. For a definition of these matrices see the DirectX SDK.
VISL
Unknown at the moment.
VISC
Unknown at the moment.
AMAP
This section contains animation map data.
SCEN
Unknown at the moment.
SGAL
This is the scenegraph animation linkage section.
SGVL
This is the scenegraph visibility linkage section.
SGJC
This scenegraph section contains IK joint constraint data.
SGBR
This is the scenegraph bone reference section.
LODT
This section defines the LOD table of the object. It is followed by a LODE section for each LOD level in the object.
LODE
This section defines a LOD level for the object. It contains an int that indicates the value of this LOD. The default value if only one LOD is used in the object is 100. This section is followed by a PART section for each part in this LOD level.
PART
This section defines an object part. The part definition contains the following parameters:
int type (1 = Triangle List, 2 = Triangle Fan, 3 = Triangle Strip) int scenegraph_reference int material_index int vertex_buffer_index int vertex_offset int vertex_count int index_offset int index_count int mouse_rectangle_ref (?)
vertex_buffer_index tells which VERT structure inside the VERB section is to be used.
The index_offset and index_count are given in indices, so it should be divided by three to get a triangle offset and count.
ANIB
Animation block section. Data type is uint8.
PLAL
Platform list. Contains a number of PLAT entries.
PLAT
Platform:
int surface 0=CONCRETE, 1=GRASS, 2=WATER, 3=GRASS_BUMPY 4=ASPHALT, 5=SHORT_GRASS, 6=LONG_GRASS, 7=HARD_TURF 8=SNOW, 9=ICE, 10=URBAN, 11=FOREST 12=DIRT, 13=CORAL, 14=GRAVEL, 15=OIL_TREATED 16=STEEL_MATS, 17=BITUMINUS, 18=BRICK, 19=MACADAM 20=PLANKS, 21=SAND, 22=SHALE, 23=TARMAC 24=WRIGHT_FLYER_TRACK int scenegraph_reference int number_of_vertices (usually 3) int (x, y, z) * number_of_vertices ...
REFL
Attachpoint list. Contains a number of REFP entries.
REFP
Attachpoint:
int scenegraph_reference int name_length byte name (zero-terminated)