From 01cb63e7f1173c2c9d4e8cb771a1d1b390aefc29 Mon Sep 17 00:00:00 2001 From: Kenso Grimm Date: Fri, 18 Sep 2026 02:18:38 +0200 Subject: [PATCH] =?UTF-8?q?feat(showroom):=20Griffe=20der=20f=C3=BCnf=20Wa?= =?UTF-8?q?ffen=20im=20Browser=20eingepasst?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 --- .../specs/2026-09-17-animationen-design.md | 22 +++++++++++++++++++ src/showroom/lineup.js | 13 ++++++----- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/docs/superpowers/specs/2026-09-17-animationen-design.md b/docs/superpowers/specs/2026-09-17-animationen-design.md index 5a0745e..9040418 100644 --- a/docs/superpowers/specs/2026-09-17-animationen-design.md +++ b/docs/superpowers/specs/2026-09-17-animationen-design.md @@ -234,6 +234,28 @@ node tools/assets/weapons.mjs -> public/models/weapons/ - **Ansicht:** Nahaufnahme von der Seite und von oben an einer Stelle des Clips, an der die Hand ruhig die Waffe hält. - **Ziel:** Das Griffstück liegt in der Handfläche, der Lauf zeigt entlang der Hand nach vorn, und die Waffe steckt nicht im Unterarm. - **Vorgehen:** Das Pack verspricht für Pistole, M4, 870, L96 und AK47 (Option 2) denselben Griffpunkt. Zuerst wird die Pistole eingepasst, ihr Wert ist dann der Startwert der übrigen. Jede Waffe bekommt trotzdem ihren eigenen Eintrag. +- **Befund (gemessen, Plan-Task 9):** Startwert `[0, 0, 90]` bringt die Längsachse der Waffe zwar korrekt auf die + Knochenachse der Hand (im Browser mit einem Vektorvergleich Fingerrichtung/Waffen-X bestätigt, Punktprodukt 1), + aber der Handknochen selbst sitzt am Handgelenk — ohne Positionsversatz reicht die Waffe deshalb bis in den + Unterarm. Mit `position.y = 0,09` (≈ halbe Handlänge, in Richtung der Finger) rutscht der Griffpunkt in die + Handfläche. Dieser Wert passt für alle fünf Waffen unverändert: + - Pistole, AK47, M4, 870 Shotgun: `position: [0, 0.09, 0]`, `rotation: [0, 0, 90]`. + - L96: gleiche Position, aber `rotation: [0, 0, -90]`. Ihre Bounding-Box liegt seitenverkehrt zu den anderen vier + (Länge und Höhe tauschen die Seite, an der der Ursprung sitzt) — 180° zusätzliche Drehung um die eigene + Querachse gleicht das aus. Über den ganzen Clip geprüft (AK47, Anfang/Mitte/Ende von `idle_loadGun-Rifle_tk04`): + Griff bleibt an der Hand. +- **Hand je Clip:** An allen acht Waffen-Dummies hält die rechte Hand (`hand_r`) die Waffe, die Vorgabe `hand: "r"` + stimmt. Bei „Pistole/Gewehr nachladen" sieht man das am Bewegungsablauf: Die rechte Hand bleibt vorn auf Höhe der + Waffe, während die linke zum Magazin greift und beide Hände sich kurz treffen, wenn das Magazin eingesetzt wird. + Bei „Schuss in den Kopf" führt ebenfalls die rechte Hand die Pistole zum Kopf. +- **Maske und Normalmap:** An der AK47 im Browser geprüft (Nahaufnahme mit Holzschaft und Metall-Receiver im selben + Bild plus Punktproben aus der `metallicRoughness`-Textur per Raycast/UV): Holz liegt bei Rauheit ≈ 0,85 und + Metallwert ≈ 0,22, der Receiver bei Rauheit ≈ 0,97 und Metallwert ≈ 0,69 — Metall ist also deutlich metallischer + als Holz, die Kanäle sind nicht vertauscht. Beide Flächen wirken unter dem bedeckten Himmel der Seite eher matt, + weil die Rauheit auf beiden hoch ist (beim Receiver sogar am höchsten) — das liest sich wie ein mattes, + parkerisiertes Finish, nicht wie ein vertauschter Kanal. Die Normalmap ist nicht flach (Mittelwert nahe + `(128, 128, 255)` mit echter Streuung an den Randwerten von Blau) und liegt korrekt ohne Farbraum vor. Kein + Tausch nötig. ## Tests diff --git a/src/showroom/lineup.js b/src/showroom/lineup.js index 1afd302..67fc630 100644 --- a/src/showroom/lineup.js +++ b/src/showroom/lineup.js @@ -7,11 +7,14 @@ * sind im Browser mit dem Panel eingepasst (Plan-Task 9); das Pack verspricht für alle fünf denselben Griffpunkt. */ export const WEAPONS = { - pistol: { label: "Pistole", url: "./models/weapons/pistol.glb", grip: { position: [0, 0, 0], rotation: [0, 0, 0] } }, - ak47: { label: "AK47", url: "./models/weapons/ak47.glb", grip: { position: [0, 0, 0], rotation: [0, 0, 0] } }, - m4: { label: "M4", url: "./models/weapons/m4.glb", grip: { position: [0, 0, 0], rotation: [0, 0, 0] } }, - shotgun870: { label: "870 Shotgun", url: "./models/weapons/shotgun870.glb", grip: { position: [0, 0, 0], rotation: [0, 0, 0] } }, - l96: { label: "L96", url: "./models/weapons/l96.glb", grip: { position: [0, 0, 0], rotation: [0, 0, 0] } }, + pistol: { label: "Pistole", url: "./models/weapons/pistol.glb", grip: { position: [0, 0.09, 0], rotation: [0, 0, 90] } }, + ak47: { label: "AK47", url: "./models/weapons/ak47.glb", grip: { position: [0, 0.09, 0], rotation: [0, 0, 90] } }, + m4: { label: "M4", url: "./models/weapons/m4.glb", grip: { position: [0, 0.09, 0], rotation: [0, 0, 90] } }, + shotgun870: { label: "870 Shotgun", url: "./models/weapons/shotgun870.glb", grip: { position: [0, 0.09, 0], rotation: [0, 0, 90] } }, + // Das Pistolenmaß passt auch hier (Griffpunkt, Position), aber die L96 sitzt im Modell um 180° um ihre + // Querachse gedreht (Länge und Höhe ihrer Bounding-Box liegen seitenverkehrt zu AK47/M4/Shotgun) — deshalb + // -90° statt 90° in Z. + l96: { label: "L96", url: "./models/weapons/l96.glb", grip: { position: [0, 0.09, 0], rotation: [0, 0, -90] } }, }; export const MOTIONS_URL = "./models/motions/weapons-mocap.glb";