MDLParser
Simple and modern library for parsing the Source engine model formats
Loading...
Searching...
No Matches
MDLParser

>[!WARNING] >All Source Engine file format parsers have been merged into a single monorepo: https://github.com/TAServers/source-parsers.

>Updates will only be made to this new repository, while the individual repositories (such as this one) will remain archived to avoid breaking existing projects.

MDLParser

Simple and modern library for parsing the Valve model format.

Documentation: https://taservers.github.io/MDLParser/

See also: https://github.com/TAServers/BSPParser and https://github.com/TAServers/VTFParser.

What's included

  • Classes for parsing and abstracting the MDL, VVD and VTX file formats for the Source engine.
  • Helper functions to simplify accessing the disparate but related data in all three files (see below).
  • Enums, limits and structs with almost 100% coverage* of the formats.
  • Runtime errors for issues when parsing the data due to corruption or a bug in the parser.

*Much of the MDL data is not currently parsed or exposed. These can be used to either implement your own more complex or specialised parser, or to easily extend - and hopefully PR - the MdlParser::Mdl class.

Example

The following minimal example shows how you can easily and safely traverse the interconnected structure of the three files using the accessor helpers:

#include "MDLParser.hpp"
// Load from a file on disk, an API, or somewhere in memory
const auto mdlData = ...;
const auto vtxData = ...;
const auto vvdData = ...;
// Parse the data (you should wrap this in a try/catch)
const MdlParser::Mdl mdl(mdlData);
const MdlParser::Vtx vtx(vtxData, mdl.getChecksum());
const MdlParser::Vvd vvd(vvdData, mdl.getChecksum());
// You can construct all three with or without checksums,
// but passing one in will automatically check it against the header before parsing
// const Vtx vtx(vtxData);
// const Vvd vvd(vvdData);
// For each body part (body group) pair...
mdl,
vtx,
[&](const MdlParser::Mdl::BodyPart& mdlBodyPart, const MdlParser::Vtx::BodyPart& vtxBodyPart) {
// For each model pair...
mdlBodyPart,
vtxBodyPart,
[&](const MdlParser::Mdl::Model& mdlModel, const MdlParser::Vtx::Model& vtxModel) {
// Only using the highest LoD here
const MdlParser::Vtx::ModelLod& vtxLod = vtxModel.levelOfDetails[0];
// For each mesh pair...
mdlModel,
vtxLod,
[&](const MdlParser::Mdl::Mesh& mdlMesh, const MdlParser::Vtx::Mesh& vtxMesh) {
// For each strip group...
for (const MdlParser::Vtx::StripGroup& stripGroup : vtxMesh.stripGroups) {
// For each vertex...
MdlParser::Accessors::iterateVertices(
vvd,
mdlModel,
mdlMesh,
stripGroup,
[&](
const MdlParser::Structs::Vtx::Vertex&,
const MdlParser::Structs::Vvd::Vertex& vvdVertex,
const MdlParser::Structs::Vector4D& tangent
) {
// ...
}
);
}
}
);
}
);
}
);
Definition: mdl.hpp:13
Definition: vtx.hpp:14
Definition: vvd.hpp:12
void iterateMeshes(const Mdl::Model &mdlModel, const Vtx::ModelLod &vtxModel, const std::function< void(const Mdl::Mesh &, const Vtx::Mesh &)> &iteratee)
Definition: accessors.cpp:38
void iterateModels(const Mdl::BodyPart &mdlBodyPart, const Vtx::BodyPart &vtxBodyPart, const std::function< void(const Mdl::Model &, const Vtx::Model &)> &iteratee)
Definition: accessors.cpp:30
void iterateBodyParts(const Mdl &mdl, const Vtx &vtx, const std::function< void(const Mdl::BodyPart &, const Vtx::BodyPart &)> &iteratee)
Definition: accessors.cpp:24
Definition: mdl.hpp:68
Definition: mdl.hpp:18
Definition: mdl.hpp:42
Definition: vtx.hpp:115
Definition: vtx.hpp:74
std::vector< StripGroup > stripGroups
Definition: vtx.hpp:78
Definition: vtx.hpp:89
Definition: vtx.hpp:104
std::vector< ModelLod > levelOfDetails
Definition: vtx.hpp:108
Definition: vtx.hpp:47