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>
9.0 KiB
name, description
| name | description |
|---|---|
| placing-editor-models | 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 mitreplaces(Weltpunkte), wenn an der Stelle schon ein Gebäudekasten aus den Chunk-Daten steht, - einer aufbereiteten
.glb, - je einer Zeile in
SOLID_BY_PLACEundBUMP_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
- Modell vermessen, die
.mtlignorieren: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.
- Stelle holen: Planquadrat → Weltbox (
parseChunkName,chunkOrigininsrc/world/coords.js), dann ein Fenster von etwa 150 × 50 m:Straßenränder, Flächen und Laternen daraus ablesen.node .claude/skills/placing-editor-models/scripts/site-data.mjs <x0> <x1> <y0> <y1> <scratch>/site.json- Ersetzt der Ort ein Gebäude: Steht in
site.jsonunterbuildingsein Grundriss an der Stelle, den der Ort ersetzen soll, dessen Mitte alsreplaces: [[x, y]]in denPLACES-Eintrag. DerChunkStreamerlässt ihn dann weg (withoutReplacedBuildings). Den Ort nicht um den Kasten herum verschieben, nichtcorrections.tomlvorschlagen. Vorlage:docs/superpowers/specs/2026-09-14-tribuene-design.md.
- Ersetzt der Ort ein Gebäude: Steht in
- 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.
- Vergleichsbild rendern und per
SendUserFileschicken: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.
- Dann genau eine Frage mit
- Materialrollen festlegen.
NEAR_MATERIALSundSIMPLIFY_RATIOS(places.mjs) sowieSOLID_MATERIALS(places.js) sind global und nach Namen geordnet.- Neue Namen gegen die Listen abgleichen. Hat derselbe Name eine andere Rolle (etwa
grassals 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.
- Neue Namen gegen die Listen abgleichen. Hat derselbe Name eine andere Rolle (etwa
- 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
- Aufbereiten:
node tools/assets/places.mjs <quelle.glb> <id>. Aus dem Bericht dieboundsinPLACESübernehmen;gpuMBund die Dreieckszahl mit dem Nutzer abgleichen, wenn sie deutlich über dem Hood Yard liegen (231 MB, 658 000). - Tests:
tests/placesSite.test.jsprüft jedenPLACES-Eintrag von selbst, beireplacesauch, ob der ersetzte Grundriss noch an der Stelle liegt.tests/placesAsset.test.jsläuft überdescribe.each(PLACES). Für den neuen Ort je eine Zeile ergänzen:SOLID_BY_PLACE(feste Materialien seiner Datei) undBUMP_BY_PLACE(Materialien mit Bump, sonst[]).
- 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.finishmessen, mit und ohne Ort. - Vorwärmen: Texturzähler am Startpunkt ablesen.
- 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.