VTX: Difference between revisions
m (Added note about header size. Error possibly due to the removal of inline code) |
(Rewrote the page with all missing information covered, and added extra clarification. Removed the dead links) |
||
Line 3: | Line 3: | ||
It is currently found in <code>.sw.vtx</code> (Software), <code>.dx80.vtx</code> (DirectX 8.0) <code>.dx90.vtx</code> (DirectX 9.0) and <code>.xbox.vtx</code> (XBox) flavors. ''[[Left 4 Dead]]'' and ''[[Left 4 Dead 2]]'' originally used ''just'' .VTX files, as of the Sacrifice update for these two games they now use the <code>.dx90.vtx</code> for the Mac OSX and re-used the .VTX only for ''Portal 2''. | It is currently found in <code>.sw.vtx</code> (Software), <code>.dx80.vtx</code> (DirectX 8.0) <code>.dx90.vtx</code> (DirectX 9.0) and <code>.xbox.vtx</code> (XBox) flavors. ''[[Left 4 Dead]]'' and ''[[Left 4 Dead 2]]'' originally used ''just'' .VTX files, as of the Sacrifice update for these two games they now use the <code>.dx90.vtx</code> for the Mac OSX and re-used the .VTX only for ''Portal 2''. | ||
=File Structure= | |||
==Header== | ==Header== | ||
<source lang="cpp"> | <source lang="cpp"> | ||
// this structure is in <mod folder>/src/public/optimize.h | // this structure is in <mod folder>/src/public/optimize.h | ||
struct FileHeader_t | struct FileHeader_t | ||
Line 16: | Line 15: | ||
int vertCacheSize; | int vertCacheSize; | ||
unsigned short maxBonesPerStrip; | unsigned short maxBonesPerStrip; | ||
unsigned short | unsigned short maxBonesPerTri; | ||
int maxBonesPerVert; | int maxBonesPerVert; | ||
// must match checkSum in the .mdl | // must match checkSum in the .mdl | ||
int checkSum; | |||
int numLODs; // | int numLODs; // Also specified in ModelHeader_t's and should match | ||
// | // Offset to materialReplacementList Array. one of these for each LOD, 8 in total | ||
int materialReplacementListOffset; | int materialReplacementListOffset; | ||
//Defines the size and location of the body part array | |||
int numBodyParts; | int numBodyParts; | ||
int bodyPartOffset; // offset | int bodyPartOffset; | ||
}; | |||
</source> | |||
This is the header structure for the current VERSION7 .vtx file | |||
===Body array=== | |||
The body array is a list of <b>BodyPartHeader_t</b> objects. | |||
Size is specified by: <b>numBodyParts</b>. | |||
Location is specified by <b>bodyPartOffset</b>. This is relative to the header, which is alwasy 0x0 and can therefore the offset can allways be treated as a static address. | |||
==BodyPartHeader_t== | |||
<source lang="cpp"> | |||
struct BodyPartHeader_t | |||
{ | |||
//Model array | |||
int numModels; | |||
int modelOffset; | |||
}; | |||
</source> | |||
===Model array=== | |||
The model array is a list of <b>ModelHeader_t</b> objects. | |||
Size is specified by: <b>numModels</b>. | |||
Location is specified by <b>bodyPartOffset</b>. This is a relative offset, from the start of the <b>BodyPartHeader_t</b> object. | |||
==ModelHeader_t== | |||
<source lang="cpp"> | |||
// This maps one to one with models in the mdl file. | |||
struct ModelHeader_t | |||
{ | |||
//LOD mesh array | |||
int numLODs; //This is also specified in FileHeader_t | |||
int lodOffset; | |||
}; | }; | ||
</source> | </source> | ||
===LOD Mesh Array=== | |||
The LOD mesh array is a list of <b>ModelLODHeader_t</b> objects. | |||
Size is specified by: <b>numLODS</b> | |||
Location is specified by <b>lodOffset</b>. This is again a relative offset, from the start of the <b>Modelheader_t</b> object. | |||
==ModelLODHeader_t== | |||
<source lang="cpp"> | |||
struct ModelLODHeader_t | |||
{ | |||
//Mesh array | |||
int numMeshes; | |||
int meshOffset; | |||
float switchPoint; | |||
}; | |||
</source> | |||
===Mesh array=== | |||
The mesh array is a list of <b>MeshHeader_t</b> objects. | |||
Size is specified by: <b>numMeshes</b>. | |||
Location is specified by <b>meshOffset</b>. Relative offset from the start of the <b>ModelLODHeader_t</b> object. | |||
===Switch Point=== | |||
The point at which the engine should switch to this LOD mesh is defined by <b>switchPoint</b>. | |||
==MeshHeader_t== | |||
<source lang="cpp"> | |||
struct MeshHeader_t | |||
{ | |||
int numStripGroups; | |||
int stripGroupHeaderOffset; | |||
unsigned char flags; | |||
}; | |||
</source> | |||
===Strip Group Array=== | |||
The strip group array is a list of <b>StripHeader_t</b> objects. | |||
Size is specified by: <b>numStripGroups</b> | |||
Location is specified by <b>stripGroupHeaderOffset</b>. Relative from <b>MeshHeader_t</b> object. | |||
===Flags=== | |||
The unsigned char <b>flags</b> value can be read from this table: | |||
{| class="standard-table" | {| class="standard-table" | ||
! | ! Value | ||
! | ! Meaning | ||
|- | |- | ||
| | |0x01 || STRIPGROUP_IS_FLEXED | ||
|- | |- | ||
| | |0x02 || STRIPGROUP_IS_HWSKINNED | ||
|- | |- | ||
| | |0x04 || STRIPGROUP_IS_DELTA_FLEXED | ||
|- | |- | ||
| | |0x08 || STRIPGROUP_SUPPRESS_HW_MORPH | ||
|} | |} | ||
==StripHeader_t== | |||
<source lang="cpp"> | |||
// A strip is a piece of a stripgroup which is divided by bones | |||
struct StripHeader_t | |||
{ | |||
//Indices array | |||
int numIndices; | |||
int indexOffset; | |||
//Vertices array | |||
int numVerts; | |||
int vertOffset; | |||
short numBones; | |||
unsigned char flags; | |||
int numBoneStateChanges; | |||
int boneStateChangeOffset; | |||
}; | |||
</source> | |||
===Indices array=== | |||
The indices array is a list of <b>unsigned short</b> indices. | |||
Size is specified by: <b>numIndices</b>. | |||
Location is specified by <b>indexOffset</b>. Relative from <b>StripHeader_t</b> object. | |||
< | ===Vertices array=== | ||
/ | The vertex array is a list of <b>Vertex_t</b> objects. | ||
Size is specified by: <b>numVerts</b>. | |||
</ | |||
Location is specified by <b>vertOffset</b>. Relative from <b>StripHeader_t</b> object. | |||
=== | ===Vertex_t=== | ||
<source lang="cpp"> | |||
struct Vertex_t | |||
{ | |||
// these index into the mesh's vert[origMeshVertID]'s bones | |||
unsigned char boneWeightIndex[3]; | |||
unsigned char numBones; | |||
unsigned short origMeshVertID; | |||
// for sw skinned verts, these are indices into the global list of bones | |||
// for hw skinned verts, these are hardware bone indices | |||
char boneID[3]; | |||
}; | |||
</source> | |||
<b>origMeshVertID</b> defines the index of this vertex that is to be read from the linked .VVD file's vertex array | |||
==See also== | ==See also== |
Revision as of 09:41, 2 December 2017
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.
It is currently found in .sw.vtx
(Software), .dx80.vtx
(DirectX 8.0) .dx90.vtx
(DirectX 9.0) and .xbox.vtx
(XBox) flavors. Left 4 Dead and Left 4 Dead 2 originally used just .VTX files, as of the Sacrifice update for these two games they now use the .dx90.vtx
for the Mac OSX and re-used the .VTX only for Portal 2.
File Structure
Header
// 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
int checkSum;
int numLODs; // Also specified in ModelHeader_t's and should match
// Offset to materialReplacementList Array. one of these for each LOD, 8 in total
int materialReplacementListOffset;
//Defines the size and location of the body part array
int numBodyParts;
int bodyPartOffset;
};
This is the header structure for the current VERSION7 .vtx file
Body array
The body array is a list of BodyPartHeader_t objects.
Size is specified by: numBodyParts.
Location is specified by bodyPartOffset. This is relative to the header, which is alwasy 0x0 and can therefore the offset can allways be treated as a static address.
BodyPartHeader_t
struct BodyPartHeader_t
{
//Model array
int numModels;
int modelOffset;
};
Model array
The model array is a list of ModelHeader_t objects.
Size is specified by: numModels.
Location is specified by bodyPartOffset. This is a relative offset, from the start of the BodyPartHeader_t object.
ModelHeader_t
// This maps one to one with models in the mdl file.
struct ModelHeader_t
{
//LOD mesh array
int numLODs; //This is also specified in FileHeader_t
int lodOffset;
};
LOD Mesh Array
The LOD mesh array is a list of ModelLODHeader_t objects.
Size is specified by: numLODS
Location is specified by lodOffset. This is again a relative offset, from the start of the Modelheader_t object.
ModelLODHeader_t
struct ModelLODHeader_t
{
//Mesh array
int numMeshes;
int meshOffset;
float switchPoint;
};
Mesh array
The mesh array is a list of MeshHeader_t objects.
Size is specified by: numMeshes.
Location is specified by meshOffset. Relative offset from the start of the ModelLODHeader_t object.
Switch Point
The point at which the engine should switch to this LOD mesh is defined by switchPoint.
MeshHeader_t
struct MeshHeader_t
{
int numStripGroups;
int stripGroupHeaderOffset;
unsigned char flags;
};
Strip Group Array
The strip group array is a list of StripHeader_t objects.
Size is specified by: numStripGroups
Location is specified by stripGroupHeaderOffset. Relative from MeshHeader_t object.
Flags
The unsigned char flags value can be read from this table:
Value | Meaning |
---|---|
0x01 | STRIPGROUP_IS_FLEXED |
0x02 | STRIPGROUP_IS_HWSKINNED |
0x04 | STRIPGROUP_IS_DELTA_FLEXED |
0x08 | STRIPGROUP_SUPPRESS_HW_MORPH |
StripHeader_t
// A strip is a piece of a stripgroup which is divided by bones
struct StripHeader_t
{
//Indices array
int numIndices;
int indexOffset;
//Vertices array
int numVerts;
int vertOffset;
short numBones;
unsigned char flags;
int numBoneStateChanges;
int boneStateChangeOffset;
};
Indices array
The indices array is a list of unsigned short indices.
Size is specified by: numIndices.
Location is specified by indexOffset. Relative from StripHeader_t object.
Vertices array
The vertex array is a list of Vertex_t objects.
Size is specified by: numVerts.
Location is specified by vertOffset. Relative from StripHeader_t object.
Vertex_t
struct Vertex_t
{
// these index into the mesh's vert[origMeshVertID]'s bones
unsigned char boneWeightIndex[3];
unsigned char numBones;
unsigned short origMeshVertID;
// for sw skinned verts, these are indices into the global list of bones
// for hw skinned verts, these are hardware bone indices
char boneID[3];
};
origMeshVertID defines the index of this vertex that is to be read from the linked .VVD file's vertex array