meshcheck vs. gltf-validator
The Khronos glTF validator answers "is this a valid glTF 2.0 file?" meshcheck answers "is this asset usable in a real pipeline?" Two different questions.
The Khronos glTF Validator is the reference tool for one precise question: is this a spec-conformant glTF 2.0 file? It checks the JSON against the schema, verifies accessor bounds and buffer views, flags undefined references and disallowed values. If it passes, your file is legal glTF that any conformant loader will parse.
meshcheck answers a different question: is this asset usable in the pipeline you’re about to drop it into? Triangle budgets, texture memory, UV overlap, transform scale, watertight geometry, whether it renders to visible pixels at all. A file can be flawless glTF and still be unshippable — the two properties are unrelated.
We run the validator; we don’t replace it
meshcheck does not reimplement spec conformance. Our SPEC-001 check shells out to the Khronos
gltf-validator binary and maps its errors and warnings into the report verbatim. If the validator says
your file is malformed, SPEC-001 fails and we surface exactly what it found. We build on Khronos, not
against it — the comparison here is about coverage, not correctness of the spec check itself.
Where the tools diverge is everything past conformance. The validator is done once the file is legal glTF. meshcheck’s other eight check families start there.
A file that passes spec and fails the pipeline
Consider Duck__flip_faces.glb — the Khronos sample Duck with its triangle winding order reversed on a
portion of the mesh. Flipping winding is a modeling defect, not a spec violation: the file is still
structurally valid glTF 2.0. Here is the Khronos validator’s own verdict on it:
{
"issues": {
"numErrors": 0,
"numWarnings": 0,
"numInfos": 0,
"numHints": 3,
"messages": [
{
"code": "BUFFER_VIEW_TARGET_MISSING",
"message": "bufferView.target should be set for vertex or index data.",
"severity": 3,
"pointer": "/meshes/0/primitives/0/attributes/POSITION"
}
]
}
}
Zero errors, zero warnings. Three severity-3 hints about an unset bufferView.target — advisory, not a
failure. By the validator’s measure this file is fine, and meshcheck agrees: SPEC-001 passes.
Now the same file through meshcheck on the pc profile:
{
"verdict": "fail",
"summary": { "errors": 1, "warnings": 3, "info": 13, "skipped": 4 },
"checks": [
{
"id": "GEO-003",
"name": "Inconsistent winding / flipped normals",
"category": "geometry",
"severity": "error",
"status": "fail",
"measured": { "face_count": 4212, "flipped_face_count": 422, "flipped_pct": 10.018993 },
"threshold": { "flipped_pct": 5.0 },
"message": "10.018993% of faces disagree with their shell's winding (> 5%)"
}
]
}
GEO-003 measures winding agreement between adjacent faces per shell. 422 of 4,212 faces (10.018993%)
disagree with their neighbours — past the 5% default threshold, so the check fails and the report rolls up
to fail. In an engine that culls back-faces those triangles render inside-out or vanish. The validator
has no opinion on this because winding order is not a spec concern. meshcheck does, because a real renderer
does.
Reproduce it yourself against the corpus fixture:
# meshcheck's own CLI (crates/meshcheck-corpus)
meshcheck-corpus check corpus/broken/Duck__flip_faces.glb --profile pc
# or the hosted API — same report, SPEC-001 runs the bundled validator
curl -X POST https://api.meshcheck.dev/v1/validate \
-H "X-Api-Key: mc_live_..." \
-F file=@Duck__flip_faces.glb \
-F profile=pc
Coverage, side by side
The validator’s domain is the SPEC column. meshcheck runs that same check and adds eight more families.
| Family | meshcheck checks | Khronos gltf-validator |
|---|---|---|
| SPEC — spec conformance | SPEC-001 spec conformance (runs the validator), SPEC-003 references resolvable, SPEC-004 file size vs budget |
This is the validator’s domain — we wrap it |
| GEO — geometry integrity | GEO-002 open boundaries (holes), GEO-003 flipped winding, GEO-007 floating debris |
Not applicable |
| XFM — transforms & scale | XFM-001 real-world scale sanity, XFM-002 pivot placement |
Not applicable |
| UV — texture coordinates | UV-002 UV overlap, UV-004 texel stretch, UV-005 island padding |
Not applicable |
| MAT — materials & textures | MAT-001 texture resolution vs budget, MAT-002 estimated GPU texture memory |
Not applicable |
| PERF — performance budget | PERF-001 triangle count, PERF-003 draw-call estimate |
Not applicable |
| RND — render checks | RND-001 renders without error, RND-002 visible pixels |
Not applicable |
| TOP — topology & surface structure | TOP-001 quad reconstructibility, TOP-004 hard-edge share |
Not applicable |
VIS — vision (/inspect) |
VIS-001 prompt match, VIS-002 texture-artifact scan |
Not applicable |
“Not applicable” is not a knock on the validator — it is a tool for spec conformance and it does that job well. It just does not measure triangle budgets, UV layout, transform scale, topology quality, or whether the thing renders, because those are out of scope for a conformance checker. That gap is the reason meshcheck exists.
The one direct peer that reaches past conformance into surface structure is the
Khronos glTF Asset Auditor, a commerce-profile
library (not a hosted API) that ships a beveled-edge — hard-edge — check the base validator lacks.
meshcheck’s TOP-004 uses the same 90° threshold and edge convention as the Khronos glTF Asset
Auditor’s hard-edge check; meshcheck additionally reports a length-weighted share so a million tiny edges
don’t drown one long hard seam. It also welds coincident positions by a configurable tolerance
(weld_tolerance) so seams a viewer reads as continuous surface aren’t miscounted as hard edges.
When to reach for which
- Use gltf-validator when you need to know a file is legal glTF 2.0 — writing an exporter, debugging a loader, or gating on spec conformance alone. It is the authority, and it is free and offline.
- Use meshcheck when a spec-valid file still has to survive a real pipeline: an AI generator’s output, a marketplace ingest gate, an agent deciding whether to accept or regenerate an asset. You get the spec check and the budget, geometry, UV, transform, topology, and render measurements, as one machine-readable report.
Every meshcheck check is a deterministic measurement — same file, same profile, same report, byte for byte.
The one exception is /inspect (the VIS family), which asks a vision model a semantic question and is
labelled deterministic: false. See the Checks reference for the full catalog.