VTX
VTX is the extension for Source's proprietary mesh strip format. It stores hardware optimized material, skinning and triangle strip/fan information for each LOD of each mesh in the MDL. Currently it is found in .sw.vtx (Software), .dx80.vtx (DirectX 8.0) .dx90.vtx (DirectX 9.0) and .xbox.vtx (XBox) flavours.
Header
#define OPTIMIZED_MODEL_FILE_VERSION 7
// this structure is in <mod folder>/src/public/optimize.h struct FileHeader_t { // file version as defined by OPTIMIZED_MODEL_FILE_VERSION (currently 7) int version; // hardware params that affect how the model is to be optimized. int vertCacheSize; unsigned short maxBonesPerStrip; unsigned short maxBonesPerTri; int maxBonesPerVert; // must match checkSum in the .mdl long checkSum; int numLODs; // garymcthack - this is also specified in ModelHeader_t and should match // this is an offset to an array of 8 MaterialReplacementListHeader_t's // (one for each LOD) int materialReplacementListOffset; int numBodyParts; int bodyPartOffset; // offset to an array of BodyPartHeader_t's };
Data Structure
Data is read through a series of offsets which vary depending on how many textures the model uses, bodygroups, submodels and LoD. Each group of offsets will lead to a 25 byte block that contains all the face/triangle information to draw the mesh. For example, if the model has 3 LoD levels and the mesh uses 2 textures per mesh then there will be 6 separate mesh references.
The 25 byte block contains the following data:
Offset | Datatype | Size (bytes) | Description |
---|---|---|---|
0 | uInt32 | 4 | Number of vertexes |
4 | uInt32 | 4 | Offset to vertex number table |
8 | uInt32 | 4 | Number of vertexes to draw faces |
12 | uInt32 | 4 | Offset to sequence to draw faces |
16 | uInt32 | 4 | Unknown offset reference (possibly related to vertex faces) |
20 | uInt32 | 4 | Offset to (unknown) reference |
24 | byte | 1 | Unknown |

Vertex Number Table
This offset will lead to a table containing 9 byte blocks which contain the ID of the vert from the VVD file. The first 4 bytes are unknown but are usually 00 01 02 00 although can be different. The next 2 bytes contain the vert number. The remaining 3 bytes are unknown (maybe LoD related). This data needs to be stored into an array with the key starting at 0 to be read correctly.
Vertex Sequence
This offset will lead to a table containing 2 byte blocks which contain the order of verts to draw the faces correctly. The 16-bit int contains the array key.
Face Draw Order
The draw sequence can be constructed with the following statement done using PHP.
//$vert_seq contains the 16-bit int keys. //$vert_data contains the 16-bit int vert number extracted from the 9 byte block. //$faces contains the sorted vert numbers to draw the faces. foreach($vert_seq as $vid) { array_push($faces, $vert_data[$vid]); }
The array $faces now contains the keys of the vertexes to be read from the VVD data assuming it is also stored in an array.
Decompile Example Script
Here is a link to a PHP script that will decompile a model can convert the reference mesh to SMD plain text. It will also partially re-construct a QC. It is not complete and does not work correctly on models with bodygroups, submodels and/or LoD. This script will only run on a Linux PHP server but the code can be modified to work on a Windows PHP server. Recommended for advanced users with programming/scripting knowledge only.