Skip to main content

3dqa — free local CLI

Validate and auto-heal 3D assets from the command line. Same deterministic, stateless core as the dashboard and API — but it runs entirely on your machine: $0, offline, no account, no upload, no API key.

Supports .glb .gltf .obj .ply .stl.

Install

pip install 3dqa               # core (linter + repair, numpy + trimesh)
pip install "3dqa[all]"        # + scipy fast path, decimation, UV unwrap/bake

Prefer a single file? The 3dqa.pyz bundle packs the whole engine into one executable zipapp — python 3dqa.pyz lint model.glb (needs numpy + trimesh in the environment; add scipy/xatlas/fast-simplification for the fast path and full heal).

Use

# Audit one asset. Exit code is a CI gate: 0 = PASS, 1 = FAIL, 2 = error.
3dqa lint model.glb --pretty

# Audit a whole export folder (recursed), one line per asset.
3dqa lint ./exports --quiet

# Gate against target engines from a single scan.
3dqa lint ./exports --targets unreal_5,unity_mobile,three_js_web
3dqa lint ./exports --config 3dqa.config.json

# Non-destructively auto-heal — writes <name>_repaired.glb, never touches input.
3dqa heal model.glb
3dqa heal ./exports --out-dir ./healed --targets unity_mobile

# See exactly what WOULD be repaired, writing nothing.
3dqa heal ./exports --dry-run --pretty

# The closed loop: heal, RE-RENDER the healed artifact, RE-RUN the vision pass
# on it, and emit ONE certificate proving it is geometrically AND visually clean.
3dqa verify model.glb --pretty
3dqa verify ./exports --targets unity_mobile --out-dir ./healed --quiet

# Same loop, keyless and free — the mock visual backend proves the wiring at $0.
3dqa verify model.glb --vision mock --dry-run --pretty

# Compact integration schema for a pipeline hook to branch on.
3dqa verify model.glb --compact

# Half the model spend: skip the pre-heal pass when you only need the
# after-verdict and not the before/after attribution.
3dqa verify ./exports --no-baseline

What you get

lint emits a JSON Quality Certificate — a machine-readable pass/fail verdict with a finding per check (poly budget, non-manifold edges, watertightness, normals, UVs, floating debris, appearance) plus optional per-target compatibility.

heal runs the repair loop lint → fix → re-lint and emits a before/after report with fixed / unfixable / introduced lists and a healing efficacy. A fix is only reported as fixed after an independent re-lint of the exported .glb confirms it. Nothing that can’t be safely repaired is hidden.

verify closes the loop. It heals, re-renders the healed artifact headless, re-runs the vision pass on that render, and returns ONE certificate:

verdict        PASS | FAIL | UNVERIFIED
claims         geometrically_clean · visually_clean · target_compatible · closed_loop
attestation    one sentence stating exactly what was proven
visual.delta   resolved / persisted / introduced defect classes, before vs after

It is honest about the case that matters: if healing fixes the math but introduces a visual defect — decimation smearing a texture, an unwrap opening a seam — visual.delta.introduced names it and the verdict is FAIL even though the geometry certificate passes. And if the visual pass could not actually run (no headless GL, --vision none), the verdict is UNVERIFIED, never a silent PASS: a certificate only claims "visually clean" when a render was really audited.

Rendering needs nothing installed

The visual pass renders through three tiers and stops at the first that produces frames: pyrender (offscreen GL), trimesh (pyglet), then a pure-numpy software rasterizer. The last tier needs no GL, no display and no driver, so verify works on a stock laptop or CI runner. The tier that ran is recorded in visual.render.backend — a software render is a real render, but you always know which one you got. It is roughly an order of magnitude slower than GL (measured: 7 views at 1024² in 0.76 s for 1.3k faces, 4.8 s for 82k); lower --resolution if that matters.

--compact emits the integration schema instead of the full certificate:

{"asset_id": "...", "status": "PASSED",
 "repartition_delta": {"initial_defects": ["NORMALS_INVERTED"],
                       "repaired_defects": ["NORMALS_INVERTED"],
                       "residual_visual_delta": 0.0},
 "execution_time_ms": 91.4}

residual_visual_delta is the fraction of visual defect classes still present after healing (0.0 = visually clean). It is null — never 0.00 — when the visual pass could not run, because 0.00 there would assert a cleanliness nobody measured.

Cost

verify runs the vision backend twice — once on the arriving asset, once on the healed one — because the before pass is what lets the certificate say a defect was introduced by healing rather than merely present. Two levers:

Setting Model calls Pixels sent
--resolution 1024 + baseline 2 14.7 MPx
default (512, baseline) 2 3.7 MPx
--no-baseline at 512 1 1.8 MPx

--no-baseline buys that saving with attribution, and says so: delta.baseline becomes "skipped" and every comparative field (resolved, persisted, introduced, regression) is null, not false. The healed asset is still fully audited — you just can no longer tell whether a defect it shows was caused by the heal.

Guarantees

  • Non-destructive: your input file is never modified.
  • Deterministic: same input → same certificate and same repaired bytes.
  • Permissive-licensed: MIT/BSD/Apache-2.0 dependencies only (CI-gated).
  • Stateless & offline: no network, no telemetry, nothing leaves your box.

Exit codes

Code Meaning
0 every asset PASSes (and passes all targets)
1 at least one asset FAILs
2 a load/engine error

For verify, an UNVERIFIED certificate gates like a FAIL (exit 1). Pass --allow-unverified to accept a geometry-only pass on a box with no headless GL.

Metadata

Release files for 3dqa 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for 3dqa 1.0.0
File Size Uploaded
3dqa-1.0.0.tar.gz 50.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for 3dqa 1.0.0
File Interpreter ABI Platform
3dqa-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 105.4 kB

Release files / 3dqa-1.0.0.tar.gz

Download URL 3dqa-1.0.0.tar.gz
Size 50.7 kB
Tags Source
SHA-256 checksum
How to use checksums
a7905ac7512f86896b3e8a31a6be9c2514e9d3c2698df505e711ddbdd2de3a6d
BLAKE2b-256 checksum
How to use checksums
a78a59b1414b8d145d1a16f3cc4114d47f1251c2419ba3092da6e5e9804c5d5c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / 3dqa-1.0.0-py3-none-any.whl

Download URL 3dqa-1.0.0-py3-none-any.whl
Size 54.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e6db905e9a7b9dfb8dcaabeb2001467f09201e76c21a41ad23ea3511f86df40c
BLAKE2b-256 checksum
How to use checksums
d3398cd20bd227f1af1cbc0e63bc909fe9207d04d9f6bb580882068abc0894d2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page