dayz-p3d-audit
DayZ P3D Audit — Complete Model & Mod Validator
Validates .p3d model files, config.cpp, model.cfg, and .rvmat materials against DayZ engine requirements. Built from production debugging where models rendered correctly but had zero collision, missing animations, or broken textures.
Preflight gate
Per the L2 rule (_shared/dayz-conventions.md), every DayZ skill that does work gates on /dayz-preflight first. The audit reads .p3d files which can live anywhere, but the moment you point it at P:\ paths or a built mod, an unmounted P-drive silently produces wrong results. Run /dayz-preflight before this skill.
The three py3d gates cannot go red for geometry (SP-227-py3d-gates-cannot-go-red)
A clean validate(), a passing save(verify=True), or a diff that reports equal is not evidence that the geometry is correct. Those checks only prove internal count consistency. When declaring a model verified, say whether vertex order was compared against debinarized vanilla or whether it was tested in-game.
validate()does not detect GLOBAL winding inversion. The winding check is relative to the Visual LOD. If every LOD is inverted (Blender Z-up to Y-up; this skill, PART 5 item 1),validate()returns an empty list and exit 0. If only Visual is inverted, it accuses healthy collision LODs (ERR_WINDING_INVERTED). The message ofpy3d_dayz-1.8.0, the wheel pinned until 2026-10-02, tells you to runface.vertices.reverse()on every face of each one (it warns against avertices[1]/[2]swap, which turns a quad into a crossed face); following that instruction still breaks them. From 1.9.0 (the pin from 2026-10-02 to 2026-10-03; 1.10.1 since), the message names the Visual LOD it compares against, says the two LODs disagree, not which one is wrong, and gives the winding steps for both, which leave a part that reads right as it is (py3d README, "Winding"). [OFFLINE MEASURED 2026-10-02] Onbuild_multilod_v2_p3d(py3d tests) afterblender_to_dayz(), with the Visual LOD turned inside-out, faces and normals together, the finding named the three healthy collision LODs; following the 1.8.0 instruction wound all 6 faces of each box outward and traded the finding forERR_WINDING_VS_NORMALSon each, and negating their normals as well leftvalidate()empty with every LOD wound outward: the silent-broken state. Read the finding as "Absolute winding check" rule 6 says. (Corrected 2026-10-02: this item said it "suggests swapping vertices on every face; following that instruction reaches the silent-broken state". The 1.8.0 message namesface.vertices.reverse()and warns against the swap; on a healthy collision LOD that still breaks the LOD, andvalidate()goes quiet only once the LOD's normals are negated too.)save(verify=True): _verify_against does not compare geometry. It looks at counts, selection names and mass sum. Points(0,0,0)vs(99,99,99)still verify OK.python -m py3d diff: py3d diff total: 0 does not prove geometric equality. The same pair reportstotal: 0, exit 0.
[DESIGN] Discriminating signal on a vanilla-scale LOD set: edge coherence (neighbors traverse the shared edge in opposite directions) and cross(e1,e2) . declared_normal in the same space.