Wolfenstein Modloader Buy me a coffeeKaffee spendieren

Wiki / Latest research roundsNeueste Forschungsrunden

TNO Skinned Models: Mesh-Count Rule and a Corpus-Proven Reader

Partly solvedTeilweise gelöst Original page in the GitHub wikiOriginalseite im GitHub-Wiki

In plain wordsIn einfachen Worten

This report decodes the file format of animated character models in Wolfenstein: The New Order, including which header field really gives the number of meshes in a file. The new reader decodes 725 of 755 models exactly to the end of the file, and a second, separately written decoder confirms the result. It also corrects an earlier claim that another count field is always 1. This is offline format research only; the reader is not yet built into the project's model viewer.

  • One hidden count field gives the true mesh count in 755 of 755 files.
  • The other count field is not always 1, as claimed before; it differs on 51 files (6.8%).
  • 725 of 755 models (96%) decode byte-exact; 600 randomly damaged test files were all correctly rejected.
  • A 12-byte part of each vertex is likely the joint weight index, but that is not yet proven.

Dieser Bericht entschlüsselt das Dateiformat animierter Figurenmodelle in Wolfenstein: The New Order, auch welches Header-Feld wirklich die Zahl der Meshes in einer Datei angibt. Der neue Leser dekodiert 725 von 755 Modellen exakt bis zum Dateiende, und ein zweiter, getrennt geschriebener Decoder bestätigt das Ergebnis. Außerdem korrigiert er eine frühere Behauptung, dass ein anderes Zählfeld immer 1 ist. Das ist reine Offline-Formatforschung; der Leser ist noch nicht in den Modellbetrachter des Projekts eingebaut.

  • Ein verstecktes Zählfeld gibt in 755 von 755 Dateien die wahre Mesh-Anzahl an.
  • Das andere Zählfeld ist nicht immer 1, wie früher behauptet; es weicht in 51 Dateien (6,8 %) ab.
  • 725 von 755 Modellen (96 %) werden byte-genau gelesen; 600 zufällig beschädigte Testdateien wurden alle korrekt abgelehnt.
  • Ein 12-Byte-Teil jedes Vertex ist wahrscheinlich der Index für die Gelenk-Gewichte, aber das ist noch nicht bewiesen.

Technical detailsTechnische Details

Der technische Teil ist auf Englisch – so, wie er im Wiki steht. Unterstrichene Begriffe haben eine Erklärung auf Deutsch.

This track (for the first game, The New Order) works out the binary layout of its skinned-character mesh format (.md6mesh/baseModel), including the long-standing puzzle of how many meshes a model file actually contains versus a header field that doesn't reliably say so. The resulting reader decodes 96% of all 755 skinned models in the game byte-exact to the literal end of file, with a clean negative control and, this pass, a second, independently-written decoder that reproduces the same results from scratch. This pass's main job was fixing one mistaken claim from earlier passes (a header field was wrongly said to always equal 1; it doesn't, in under 7% of files) and extending several findings to the full corpus instead of a handful of samples. None of this is runtime-tested since it's pure binary-format research with nothing yet wired into the project's asset viewer.

The mesh-count puzzle, solved

A model file carries two different "mesh count"-looking fields; only one of them is actually reliable. Field B, located by a constraint-propagation scan (not read directly from any single header position), is the true mesh count on 755/755 files, including both known counter-examples where a naive reading would get it wrong (one file with 7 meshes, one with 3) — now independently reproduced by a second decoder sharing no code with the first. Field A (a separate count appearing after a joint-remap table) is not reliably the mesh count and, contrary to an earlier claim carried across two prior passes without ever actually being checked corpus-wide, is not always 1 either — it differs from 1 on 51 of 755 files (6.8%), concentrated on multi-piece player/creature models (hands, wounded characters, a mechanical creature) and destructible multi-part props. It most likely represents a pre-export "meshes before splitting" count rather than the runtime mesh count.

Per-mesh layout

Each mesh's preamble carries explicit vertex-count/triangle-count fields. Two smaller per-mesh flag fields were checked corpus-wide for the first time this pass: one is 1 on 99.6% of meshes, with its only exceptions on destructible/mechanical props (not hair, correcting an earlier guess); a second is 1 on 99.5% of meshes, with its exceptions exclusively on foliage/bush props. A whole-file trailer (materials list) decodes cleanly for every file that reaches it. One 12-byte range inside each vertex is the strongest remaining candidate for a per-vertex joint-weight index — corpus-wide, it is the lowest-entropy of three candidate byte ranges on 99.7% of meshes with enough vertices to test meaningfully, with the handful of exceptions being plausible non-skinned special cases (a rigid propeller, an instrument dial, a flat billboard sprite) rather than counter-evidence. This remains an inference, not a proof — no skeleton joint ID table was actually cross-checked against it, because the skeleton file's own binary joint hierarchy is still undecoded.

Coverage and reliability

  • 725 of 755 (96.0%) skinned models decode byte-exact to the literal end of the file.
  • The remaining ~4% (mostly character/hair/destructible models with extra trailer content) have a known, bounded location but undecoded content.
  • A corpus-wide negative control (random 1–4 byte file mutations, 600 mutated samples across 5 random seeds) produced zero false accepts.

What's needed to use this

Wiring the reader into the project's model viewer would cover 96% of skinned models with roughly half a day to a day of integration work and no further format research. Decoding the remaining ~4% and the skeleton's own joint hierarchy (needed to turn the joint-weight inference above into a proven fact) is separate, open work.

In-game test

Not needed for this pass — pure offline format research, nothing changed that touches a running game. Once the reader is wired into the project's viewer: open a simple prop model (e.g. a compass or combat knife) and check visually that shape and texture look plausible — a one-step visual check, no game launch required.