Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,18 @@ qtmesh cloud list [--json] # list cloud projects
qtmesh cloud upload model.fbx [--name Hero] [--include "*.png,*.fbx"] [--exclude "*.tmp"]
# [--no-scan] [--no-confirm] [--json]
qtmesh cloud delete <project-id> # delete a cloud project
# PS1 runtime ripper (#431, experimental; needs -DENABLE_PS1_RIP=ON + the beetle rip fork in PS1Cores/):
qtmesh ps1 capture game.cue --bios scph1001.bin --frames 600 -o out.gltf # boot, capture one frame, export a scene
qtmesh ps1 capture game.cue --bios scph1001.bin --scene 5s --tracked-only --smooth --drop-slivers -o out.glb # 5s scene + cleanup toggles (#428)
qtmesh ps1 capture game.cue --bios scph1001.bin --scene 5s --rigid-animation -o out.gltf # #429 rigid animation: author per-object node tracks (in-editor preview; node tracks don't export to glTF/FBX yet)
qtmesh ps1 capture game.cue --bios scph1001.bin --script inputs.json -o out.gltf # reproducible input: [{"frame":60,"button":"start"}, ...]
qtmesh ps1 capture game.cue --bios scph1001.bin --auto-input -o out.gltf # mash Start/Cross to get past menus (no script)
qtmesh ps1 dump-vram game.cue --bios scph1001.bin --frames 300 -o vram.png # snapshot the GPU VRAM mirror to PNG
# On Linux the libretro core needs a GL context — run headless under Xvfb:
# xvfb-run -a qtmesh ps1 capture game.cue --bios scph1001.bin -o out.gltf
```

CLI mode is activated by: (1) invoking via the `qtmesh` symlink, (2) passing `--cli`, or (3) using a recognized subcommand (`info`, `fix`, `convert`, `anim`, `validate`, `lod`, `pose`, `turntable`, `isometric`, `scan`, `material`, `hdri`, `light`, `pack-textures`, `normal-from-height`, `atlas`, `atlas-apply`, `memory`, `analyze`, `vertex-cache`, `decimate`, `optimize`, `uv`, `retopo`, `skin`, `rig`, `segment`, `generate3d`, `cloud`) as the first argument. Use `--verbose` to see Ogre/engine debug output. Use `--no-telemetry` to permanently opt out of anonymous usage data collection.
CLI mode is activated by: (1) invoking via the `qtmesh` symlink, (2) passing `--cli`, or (3) using a recognized subcommand (`info`, `fix`, `convert`, `anim`, `validate`, `lod`, `pose`, `turntable`, `isometric`, `scan`, `material`, `hdri`, `light`, `pack-textures`, `normal-from-height`, `atlas`, `atlas-apply`, `memory`, `analyze`, `vertex-cache`, `decimate`, `optimize`, `uv`, `retopo`, `skin`, `rig`, `segment`, `generate3d`, `ps1`, `cloud`) as the first argument. Use `--verbose` to see Ogre/engine debug output. Use `--no-telemetry` to permanently opt out of anonymous usage data collection.

If Xcode SDK is updated, clear CMake cache (`rm build_local/CMakeCache.txt`) and reconfigure.

Expand Down Expand Up @@ -318,6 +327,9 @@ Three singletons manage core state. All run on the main thread. Access via `Clas
- **Static parsers** (`src/PS1/`): `PS1TMD`, `PS1TIM`, `PS1RSD`, `PS1PLY`, `PS1MAT` for known PlayStation mesh/texture formats.
- **Runtime extraction** (`src/PS1/runtime/`, epic #412): `ENABLE_PS1_RIP` (OFF by default). When ON, `PS1RipManager` runs an `EmuCore` host from `<app>/PS1Cores/` on a worker thread: prefer `qtmesh_ps1core_libretro` (loads `beetle_psx_qtmesh_libretro` (rip fork, tried first) / `mednafen_psx_libretro` / beetle from `PS1Cores/`, system libretro paths, or `QTMESH_PS1_LIBRETRO_CORE`) for real ISO playback; fall back to `qtmesh_ps1core_stub` for CI. Live VRAM + RAM GP0 scan feed phases 2–3 when using libretro. Install helper: `scripts/install-ps1-libretro-core.sh`. Session UI: **Tools → Experimental → PS1 Runtime Ripper…** (`PS1RipSessionWindow`, `EmuViewport`). Design doc: `src/PS1/PS1_RIP_DESIGN.md`. CI enables the flag on Linux test builds only. Sentry breadcrumbs use category `ps1.rip`.
- **In-core rip capture** (#813–#817 — the path that extracts real models from retail games, incl. custom engines): a vendored fork of beetle-psx-libretro (`fernandotonon/beetle-psx-libretro`, branch `qtmesh-rip`, artifact `beetle_psx_qtmesh_libretro.*`, all changes behind `HAVE_QTMESH_RIP`) exposes a versioned C ABI (`rip/qtmesh_rip_abi.h`, vendored byte-identical at `src/PS1/runtime/libretro/qtmesh_rip_abi.h`). The fork records every GTE RTPS/RTPT transform (object-space vertex + exact rotation matrix + precise outputs) into a 65536-entry ring and rides PGXP's value tracking (`PGXP_value::rip_tag`: kept on pure moves, dropped on any recompute/splice) so each GP0 vertex word arrives with per-vertex provenance (`qtmesh_rip_vertex_shadow`: PGXP precise x/y, view depth, GTE record index). Host: `LibretroHost` optionally resolves the 3 `qtmesh_rip_*` symbols; `LibretroEmuCore` registers trampolines (ABI-version-checked, refused on mismatch), mirrors the armed flag into the core each frame, and unregisters before unload; `RipperHooks` buffers tracked draws until the frame's GTE record flush and resolves per-vertex provenance tiers (`GteTracked`/`DepthOnly`/`None`, with a record-vs-shadow coordinate backstop). While the in-core stream is active the heuristic RAM GP0/GTE passes are suppressed (TMD/HMD model-space scanners stay on); attribution `gp0_incore` outranks `gp0_hook`; in-core cap 16384 prims/frame with overflow breadcrumb. `MeshReconstructor` consumes the tiers (#816): tracked verts land exact model-space coords, prims group on real record matrices, instances carry `rot`/`trWorld`/`hasMatrix`. Build the fork via `scripts/build-ps1-rip-core.sh` (pinned commit) or `-DENABLE_PS1_RIP_CORE_BUILD=ON`; `QTMESH_PS1_RIP_INCORE=0` A/Bs back to RAM heuristics. Status bar: `in-core hooks: active` + `tracked N% · depth M%`. Zero-ROM CI conformance: `tests/fake_rip_core/` + `InCoreRipCapture_test.cpp` drive the full chain through the real plugin trampolines. Golden metric bars incl. the custom-engine `retail-c` scene: `src/PS1/golden_captures.md`.
- **Capture cleanup (#428)**: `Ps1NormalizerSettings` opt-in toggles applied during reconstruction — `cleanupWeldNormals` (weld coincident verts + smooth normals), `cleanupRemoveZeroArea` (drop collinear/duplicate-vertex sliver triangles via `MeshReconstructor::applyZeroAreaTriangleCull`), plus the existing `spikeEdgeFactor` degenerate-span cull. Surfaced as the ripper toolbar "Smooth" / "Drop slivers" checkboxes, MCP `ps1rip_capture` `smooth`/`remove_zero_area`, CLI `--smooth`/`--drop-slivers`; `ps1.rip.cleanup.*` breadcrumbs. ScanEngine flags dirty captures via `ps1-rip-zero-area` (Warning) + `ps1-rip-degenerate-uv` (Info) rules. T-junction resolution from the issue is deferred (weld covers the common coincident-vertex case).
- **Rigid animation capture (#429)**: `Ps1AnimationExtractor` (Ogre-free, unit-tested) groups a scene capture's per-frame `gteRecords` into one matrix track per moving object (identity = seq-contiguous same-matrix run → object-space vertex-set hash; keys ordered by frame). `PS1RipMeshBuilder::authorRigidAnimation` matches each track to its capture node by first-frame world translation and authors an `Ogre::NodeAnimationTrack` via `NodeAnimationManager` so the ripped motion plays in the viewport. **In-editor preview only** — node-transform tracks don't yet round-trip through the glTF/FBX exporter (skeletal only). Opt-in via `Ps1NormalizerSettings::captureRigidAnimation` (ripper "Rigid anim" toggle / MCP `rigid_animation` / CLI `--rigid-animation`); scene capture only; best on a static-camera scene (GTE matrices are View×Model). `ps1.rip.anim` breadcrumb.
- **Headless CLI (#431)**: `qtmesh ps1 capture|dump-vram` (`CLIPipeline::cmdPs1`) drives `PS1RipManager` on its worker thread, pumping the Qt event loop (no `exec()`), then exports via `MeshImporterExporter::sceneExporter`. JSON input scripts (`[{frame,button}, ...]`) + `--auto-input` for reproducible/unattended captures; `initOgreHeadless()` so the reconstructor has a scene; Xvfb on Linux. MCP parity was already the `ps1rip_*` tool set.

### Mesh Import/Export

Expand Down
2 changes: 1 addition & 1 deletion src/AppLaunchHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ bool isCliSubcommand(const QString& arg)
QStringLiteral("skin"), QStringLiteral("rig"), QStringLiteral("segment"),
QStringLiteral("generate3d"),
QStringLiteral("morph"),
QStringLiteral("nodeanim"), QStringLiteral("cloud"),
QStringLiteral("nodeanim"), QStringLiteral("ps1"), QStringLiteral("cloud"),
};
return kSubcommands.contains(arg);
}
Expand Down
Loading
Loading