README: record what actually works, and the measured mesh-quality floor

The status list still said the pipeline was unwired. It runs end to end now:
proj conditioning (all four extractors at corr 1.00000000), the NAF branch without
natten, the full 32^3 -> refine -> 64^3 cascade at silhouette IoU 0.969, cleanup,
and the MODELBEAST operator. Textures remain the one open item.

Also records the decimation table, because the floor is a real constraint and not
obvious: 500k faces is effectively lossless (IoU 0.965) but ~214k cannot be beaten,
and reaching it costs fidelity (0.823). Cause is the ~180k boundary edges the dual
grid emits for open surfaces - quadric decimation will not collapse them at any
setting, and o_voxel's remesh ran >20min on 214k faces before being killed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
m3ultra 2026-08-03 16:52:09 +10:00
parent 26ae88dea8
commit 2ede6655d9

View File

@ -81,7 +81,43 @@ Weights: 24.04 GB across 19 files (1.3B DiTs at 512/1024 + shape/tex decoders).
structure stage: image -> ss_flow -> latent -> ss_dec -> 64^3 occupancy grid
- [x] `shape_dec` / `tex_dec` — both load complete (292/292, 284/284) and run.
**Behaviourally** checked only; see the verification note below
- [ ] End-to-end pipeline wiring (image encoder -> flows -> decoders -> mesh export)
- [x] **Proj conditioning** — camera back-projection, an exact `grid_sample`
equivalent, and DINOv3 (torch/MPS). All four extractor stages diffed against
upstream at correlation 1.00000000
- [x] **NAF high-res branch without natten** — natten is unusable on Apple Silicon
(no `libnatten`; `flex-fna` is CPU-only, rejects asymmetric head dims, and was
OOM-killed at 512). Replaced by an exact reduction to a clamped 9x9 low-res
neighbourhood, verified against natten at 7.15e-07
- [x] **The full cascade** — 32^3 -> LR SLAT -> coord refinement -> 64^3 HR SLAT ->
Flexible Dual Grid at 1024^3 -> GLB, at **silhouette IoU 0.969**
- [x] **Mesh cleanup** — weld, strip floaters, iterative decimation (500k faces at
IoU 0.965; ~214k is a hard floor, see below)
- [x] **MODELBEAST operator** `pixal3d_mlx` (geometry only)
- [ ] Texture stage (tex SLAT + o_voxel PBR bake) — the GLB is currently untextured
## Running it
```bash
python scripts/image_to_mesh.py IMAGE -o out.glb --target-faces 500000
```
Exits non-zero below `--min-iou` (default 0.85): a run that completes with a
reconstruction that does not track the input has failed, even though nothing raised.
### Mesh quality, measured
| face budget | result | silhouette IoU |
|---|---|---|
| raw decoder output | 7,996,876 | 0.969 |
| 500,000 | 499,984 | **0.965** |
| 200,000 / 100,000 / 20,000 | 214,322 (floor) | 0.823 |
**~214k is a hard floor.** The Flexible Dual Grid emits ~180,000 boundary edges for
open surfaces and quadric decimation will not collapse those — no `target_reduction`
or `agg` setting changes it, and a single `fast_simplification` call additionally
refuses to reduce past ~4.4% of its input (hence the iterative loop). Going lower
needs a remesh; o_voxel's ran >20 minutes on 214k faces before being killed, so it is
not currently a practical route. **500k is effectively lossless — use that.**
## Model status