Files
gta6/.claude/skills/placing-editor-models/SKILL.md
T
knsoandClaude Sonnet 5 71011e27e2 docs(skills): Projekt-Skill kennt replaces und den Asset-Test je Ort
Behebt Befund 1 aus dem Abschluss-Review: der Skill war seit den
Tribüne-Tasks veraltet - er kannte weder replaces noch die
Materialzeilen je Ort in SOLID_BY_PLACE/BUMP_BY_PLACE. Ersetzt statt
angehängt, an den drei Stellen, wo man danach sucht: Überblick
(Ein-neuer-Ort-Liste), Schritt 2 (Stelle holen) und Schritt 8 (Tests),
dazu zwei Fallstricke-Zeilen für die roten Ausgangszustände.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-15 03:57:37 +02:00

100 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: placing-editor-models
description: Use when a model built in the three-d-stage editor (GLB export, often sent with a .mtl) should be placed 1:1 at a real-world spot in the Leonida world — "setz das an die Stelle aus dem Satellitenbild", a yard, kiosk or building next to a park or street in a Planquadrat — or when an entry in src/world/places.js has to move, look different or collide differently.
---
# Editor-Modelle in Leonida platzieren
## Überblick
Der Ablauf bleibt der des Hood Yard: Brainstorming mit der Lagefrage am Vergleichsbild → kurze Spec → Plan → Umsetzung mit Subagenten und Reviews → Browserprüfung → Gesamt-Review → Abschluss. Vorlage: `docs/superpowers/specs/2026-09-14-hood-yard-design.md` und `docs/superpowers/plans/2026-09-14-hood-yard.md`.
Neu gebaut werden muss nichts. Orte-Schicht (`src/world/places.js`), Aufbereitung (`tools/assets/places.mjs`), Bump-Erweiterung, Tests und das Vorwärmen in `main.js` gibt es schon. Ein neuer Ort besteht aus:
- einem `PLACES`-Eintrag, optional mit `replaces` (Weltpunkte), wenn an der Stelle schon ein Gebäudekasten aus den Chunk-Daten steht,
- einer aufbereiteten `.glb`,
- je einer Zeile in `SOLID_BY_PLACE` und `BUMP_BY_PLACE` (`tests/placesAsset.test.js`).
Die eigentliche Arbeit sind die Lage, die Materialrollen und die Prüfung im Spiel.
**Pflicht-Skills in dieser Reihenfolge:** superpowers:brainstorming, superpowers:writing-plans, superpowers:subagent-driven-development, superpowers:finishing-a-development-branch.
## Schon entschieden, nicht neu fragen
| Punkt | Festlegung |
|---|---|
| Maßstab | 1:1, three-d-stage baut in Metern; `PLACES` hat kein `scale` |
| Lage | `at` = Welt-x/-y (Minimap), `rotation` in Grad gegen den Uhrzeigersinn, Norden oben |
| Höhe | Mit Bodenplatte (flaches Teil über die ganze Grundfläche): `lift = 0,06 − t`, t = Höhe, auf der die übrigen Gruppen stehen (Hood Yard: 0,34, obwohl `ground` wegen Bordsteinen bis 0,5 reicht → −0,28). Bei 0 cm flackert der Boden, ein Podest wird zur Stolperkante. Ohne Bodenplatte: `lift = 0` |
| Radien | Vorladen 600 m, einsetzen 250 m, herausnehmen 450 m; `tests/placesSite.test.js` prüft den Chunk-Abstand |
| Aufbereitung | nur `tools/assets/places.mjs`: die gltf-transform-CLI verwirft `EXT_materials_bump`. Ergebnis < 30 MB, die Quelle kommt nie ins Repo |
| Kollision | über Materialnamen (`SOLID_MATERIALS`); Pflanzen und Kleinteile durchlässig, Stämme fest |
| Arbeitsweise | eigener Arbeitsbaum, wenn im Hauptordner fremde Änderungen liegen |
## Ablauf
1. **Modell vermessen**, die `.mtl` ignorieren:
```bash
node .claude/skills/placing-editor-models/scripts/measure-model.mjs ~/Downloads/<name>.glb <scratch>/model.json
```
- Dreiecke zählt das Skript je Knoten; die Summe über die Meshes unterschätzt bei three-d-stage stark.
- Außerdem zeigt es Bump-Materialien, Außenmaße und Baugruppen.
- **Bodenplatte suchen:** eine flache Gruppe, die x und z der Außenmaße abdeckt. Gibt es keine, ist `lift = 0`.
- **t bestimmen:** t ist das kleinste y-Minimum der übrigen Gruppen, also die Höhe, auf der sie stehen. Nicht das y-Maximum der Plattengruppe, darin stecken oft Bordsteine und Wege. Dann gilt `lift = 0,06 − t`.
- Die Wurzel-Verschiebung ist nur ein Hinweis, nicht die Plattendicke.
2. **Stelle holen:** Planquadrat → Weltbox (`parseChunkName`, `chunkOrigin` in `src/world/coords.js`), dann ein Fenster von etwa 150 × 50 m:
```bash
node .claude/skills/placing-editor-models/scripts/site-data.mjs <x0> <x1> <y0> <y1> <scratch>/site.json
```
Straßenränder, Flächen und Laternen daraus ablesen.
- **Ersetzt der Ort ein Gebäude:** Steht in `site.json` unter `buildings` ein Grundriss an der Stelle, den der Ort ersetzen soll, dessen Mitte als `replaces: [[x, y]]` in den `PLACES`-Eintrag. Der `ChunkStreamer` lässt ihn dann weg (`withoutReplacedBuildings`). Den Ort nicht um den Kasten herum verschieben, nicht `corrections.toml` vorschlagen. Vorlage: `docs/superpowers/specs/2026-09-14-tribuene-design.md`.
3. **Satellitenbild einhängen:**
- **Anker:** ein Punkt, der im Bild und in den Chunk-Daten eindeutig ist (Feldecke, Kreuzung), möglichst nah am Ziel. Echte Stadt und Spielkarte weichen voneinander ab.
- **Maßstab:** Meter pro Pixel aus Autos (~4,5 m) oder Feldmarkierungen schätzen, mit ±15 % Unsicherheit rechnen.
4. **Vergleichsbild** rendern und per `SendUserFile` schicken:
```bash
tools/extract/.venv/bin/python .claude/skills/placing-editor-models/scripts/render-site.py --site site.json --model model.json --at X Y --satellite <bild> --anchor-px PX PY --anchor-world AX AY --mpp 0.15 --out lage.png
```
- Dann genau **eine** Frage mit `AskUserQuestion`: „wie im Bild“ oder die zwei naheliegenden Verschiebungen.
- Ist die echte Anlage länger oder kürzer als das Modell, die Ausrichtung (Mitte, Anfang, Übergang zwischen Bauteilen) ausdrücklich zur Wahl stellen.
5. **Materialrollen festlegen.** `NEAR_MATERIALS` und `SIMPLIFY_RATIOS` (`places.mjs`) sowie `SOLID_MATERIALS` (`places.js`) sind global und nach Namen geordnet.
- Neue Namen gegen die Listen abgleichen. Hat derselbe Name eine andere Rolle (etwa `grass` als begehbare Fläche statt als Halme), dem Nutzer vorlegen und nicht still teilen.
- Anteile beim Vereinfachen, nach gezeichneten Dreiecken: Bäume mit mehr als 300 000 → 0,15; Gras und Büsche → 0,5; Kleinteile → 0,25; Gebäude, Boden und Zäune nie.
6. **Spec und Plan** kurz halten, nur was neu ist:
- **Spec:** Befund (Tabelle aus Schritt 1), Lage-Tabelle mit Abständen zu Straße, Feldern und Laternen, Materialrollen, Budget.
- **Plan-Tasks:**
- Materiallisten
- Aufbereitung und Asset-Test
- `PLACES`-Eintrag und Lage-Test
- Browserprüfung
7. **Aufbereiten:** `node tools/assets/places.mjs <quelle.glb> <id>`. Aus dem Bericht die `bounds` in `PLACES` übernehmen; `gpuMB` und die Dreieckszahl mit dem Nutzer abgleichen, wenn sie deutlich über dem Hood Yard liegen (231 MB, 658 000).
8. **Tests:**
- `tests/placesSite.test.js` prüft jeden `PLACES`-Eintrag von selbst, bei `replaces` auch, ob der ersetzte Grundriss noch an der Stelle liegt.
- `tests/placesAsset.test.js` läuft über `describe.each(PLACES)`. Für den neuen Ort je eine Zeile ergänzen: `SOLID_BY_PLACE` (feste Materialien seiner Datei) und `BUMP_BY_PLACE` (Materialien mit Bump, sonst `[]`).
9. **Browserprüfung** nach `browser-checks.md`:
- Lage prüfen.
- Kollision: Kapsel steht auf der Platte, eine Wand stoppt sie, Pflanzen sind durchlässig.
- Drei Blicke als Bilder an den Nutzer.
- Kosten mit `gl.finish` messen, mit und ohne Ort.
- Vorwärmen: Texturzähler am Startpunkt ablesen.
10. **Gesamt-Review, Abnahme durch den Nutzer, Branch abschließen.**
## Fallstricke
| Symptom | Ursache | Gegenmittel |
|---|---|---|
| Dreieckszahl viel kleiner als gezeichnet | three-d-stage benutzt Meshes mehrfach | je Knoten zählen (`measure-model.mjs`) |
| Wellblech, Relief oder Rillen flach | gltf-transform-CLI verwirft `EXT_materials_bump` | nur `places.mjs` |
| Figur läuft durch Wände, steht bei y 0,75 statt auf der Platte | meshopt-Positionen sind quantisiert, der Collider-Bau klemmt sie auf ±1 | Orte immer über `prepareModel`/`PlaceLayer` einsetzen; im Browser prüfen, dass feste Meshes Float32 haben |
| Boden flackert im Ort | Plattenoberkante auf y 0 | `lift` für +6 cm |
| Laterne oder Palme steht im Ort | Requisiten entstehen je Chunk, Laternen bis 16 m neben der Mittellinie, auch aus Nachbarchunks | Site-Test, Lage verschieben |
| Ort schwebt nach einem Minimap-Sprung kurz über dem Meer | der Streamer baut einen Chunk pro Frame | hingenommen (Ruling Hood Yard) |
| Asset-Test rot, „verteilt SOLID_MATERIALS …“ oder eine fehlende Zeile | Ort ohne Zeile in `SOLID_BY_PLACE`/`BUMP_BY_PLACE` | Zeile für den Ort ergänzen (Schritt 8) |
| Site-Test „in keinem Gebäude“ rot | der Ort soll ein vorhandenes Gebäude ersetzen | `replaces` mit der Mitte des Grundrisses setzen (Schritt 2), statt den Ort zu verschieben |
| `preview_start` findet den Server nicht | liest nur `.claude/launch.json` des Hauptordners | Nutzer fragen, Arbeitsbaum kurz verlassen, Eintrag setzen, zurück, am Ende entfernen |
| Befehle im Arbeitsbaum verweigert | Isolationswache mag keine Variablen als Befehl oder Skriptpfade mit Leerzeichen | Pfade ausschreiben; statt `review-package` drei Befehle: `git log --oneline A..B >`, `git diff --stat A..B >>`, `git diff -U10 A..B >>` in eine Datei |
| Draw-Call- und Dreieckszahlen zu optimistisch | `renderer.info` wird nach den Schattenstufen zurückgesetzt | `gl.finish`-Messung (`browser-checks.md` §8) |
| Ruckler beim ersten Erscheinen | Vorwärmen lief nicht | am Startpunkt muss `renderer.info.memory.textures` die Texturen des Orts schon enthalten |
| Seite friert nach einem Browser-Hook ein | Ausnahme im `onBeforeRender`-Hook beendet die Zeichenschleife | `window.__probe ??= {}`, nach Vite-Reload neu einrichten |
Werkzeuge: `scripts/` (Vermessung, Kartendaten, Vergleichsbild, Screenshot-Dekodierung); Browser-Ausschnitte: `browser-checks.md`.