diff --git a/README.md b/README.md index 9e18b20..e705368 100644 --- a/README.md +++ b/README.md @@ -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