Commit Graph
60 Commits
Author SHA1 Message Date
knsoandClaude Opus 5 50eee9281a fix(world): Bordstein verschwindet beim flachen Blick nicht mehr
Gemeldet: Der Bordstein ist zu sehen, wenn man davor steht und nach unten
schaut, verschwindet aber beim Blick nach oben und aus der Entfernung.

Ursache ist der Tiefenversatz der Beläge. glPolygonOffset rechnet
offset = factor * Tiefensteigung + units * r, und die Tiefensteigung geht
beim streifenden Blick über eine Bodenfläche gegen unendlich. Die Rangfolge
der Beläge steckte im Faktor (Gehweg -9), also zog der Gehwegbelag beim
flachen Blick um ein Vielfaches seines nominellen Versatzes nach vorn und
deckte die 18 cm hohe Bordsteinwand daneben (Versatz 0) vollständig zu. Im
Browser nachgemessen: aus 18 m war die Wand weg, aus zwei Metern und von
oben war sie da; mit Faktor 0 oder -1 kam sie zurück.

Genau davor warnt der Kommentar über POLYGON_OFFSET_ORDER seit Teil 1 ("wächst
die Liste weiter, ist die Stufenhöhe zu entkoppeln"). Das passiert jetzt: Die
Rangfolge tragen allein die Units - sie zählen in der kleinsten auflösbaren
Tiefendifferenz, hängen nicht vom Blickwinkel ab und trennen koplanare Beläge
auf jede Entfernung. Der Faktor ist für alle Beläge derselbe kleine Wert und
hält sie über der Bodenplatte, ohne Geometrie daneben zu überdecken.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 12:41:54 +02:00
knsoandClaude Opus 5 4a91e84bfc Merge branch 'main' into leonida/strassen
Bringt den Stand von main (Animationen, Showroom) in den Straßenzweig,
damit die zusammengeführte Fassung geprüft werden kann, bevor main auf
diesen Stand vorgezogen wird. main ist in einem zweiten Arbeitsverzeichnis
ausgecheckt und kann hier nicht ausgecheckt werden.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 12:09:42 +02:00
knsoandClaude Sonnet 5 2e7b30fd15 fix(world): Gehwegtextur aus Poly Haven statt Kit-Platzhalter
Die Fixwelle hat loadSet() so geaendert, dass eine Textur auch ohne
Normal- und ARM-Karte laedt (Befund 2) - richtig fuer sich, aber dadurch
laedt public/textures/sidewalk_Diffuse.jpg jetzt tatsaechlich. Die Datei
ist keine Betontextur, sondern das Platzhalterbild aus
modular_sidewalk_curb_kit: dunkler Grund, roter Schriftzug "Tru-planar
Sidewalk texture", im Browser geprueft. Vorher fiel das nie auf, weil
loadSet() an der fehlenden Normal-/ARM-Karte scheiterte und auf den
einfarbigen Ersatz zurueckfiel.

TEXTURES.sidewalk zeigt jetzt auf concrete_pavement (Poly Haven, CC0),
denselben Belag wie die Parkwege (curb_Diffuse.jpg ist dagegen eine
echte Betontextur mit Fugen und bleibt beim Kit). uvScale wechselt
von 4 auf 1,8, wie paths schon vormacht - Poly Haven misst die Kachel
mit 1,8 x 1,8 m. Der Kopierschritt fuer sidewalk_baseColor.jpeg entfaellt
in tools/assets/textures.mjs, die Namensnennung in run.py und im Entwurf
nennt fuer den Kit nur noch den Bordstein, und die committete
Platzhalter-Kachel ist aus dem Repository entfernt (der Kit-Ordner des
Nutzers bleibt unangetastet). tests/materials.test.js prueft jetzt die
neue Quelle, nicht mehr den Kit-Slug.

Sichtgeprueft im Browser: Gehwege zeigen helle Betonplatten statt
rotem Schriftzug, keine "Textur ... fehlt"-Warnung in der Konsole.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-18 09:06:40 +02:00
knso 77d53fb170 fix(extract): carriageway[].klasse als irreführendes Feld entfernt
Befund 6, Controller-Entscheidung: carriageway_area() vereinigt das ganze
Straßennetz zu wenigen Zusammenhangskomponenten, und _classified() gab
jeder Komponente die Klasse ihrer breitesten enthaltenen Straße - am
echten Netz trugen dadurch 91,2 % der Fahrbahnfläche "boulevard", auch wo
tatsächlich eine Wohnstraße lag. Kein Verbraucher las das Feld (Browser
und Minimap färben die Fahrbahn einheitlich); die Klasse je Straße steht
weiterhin in edges.

_classified() samt Aufruf aus run.py entfernt, chunk_payload() nimmt
carriageway jetzt als reine Liste von Polygonen statt (poly, klasse)-
Tupeln entgegen, Sortierschlüssel entsprechend auf poly allein verkürzt.
Fixtures in test_emit.py, test_overview.py, tests/geometry.test.js und
tests/streaming.test.js sowie das Chunk-Format im Entwurf nachgezogen;
tests/props.test.js bleibt unverändert, weil dort edges betroffen sind,
nicht carriageway.
2026-09-18 06:54:01 +02:00
knso 3f4fa7f1ed fix(world): Gehweg lädt seine Diffuse-Textur auch ohne Normal- und ARM-Karte
loadSet() lud Diffuse-, Normal- und ARM-Karte in einem gemeinsamen
Promise.all und fiel schon beim Fehlen einer einzigen Datei auf den
einfarbigen Ersatz zurück. modular_sidewalk_curb_kit liefert für den
Gehweg nur sidewalk_Diffuse.jpg (keine Normal-Map, und die
metallicRoughness-Karte ist laut Entwurf eine 605-Byte-Einfarbfläche,
die bewusst nicht übernommen wird) — Folge: 0,298 km² rendern einfarbig
#d8d2c4, bei jedem Laden "Textur sidewalk fehlt", die committete Kachel
blieb ungenutzt.

Nur die Diffuse-Karte ist jetzt Pflicht; Normal- und ARM-Karte werden
einzeln geladen und fallen bei einem Fehler je für sich auf null zurück,
ohne die anderen beiden mitzureißen. Ohne ARM-Karte bleibt roughness auf
0.9 (derselbe Wert wie der bisherige einfarbige Ersatz).

loadSet() ist jetzt exportiert, damit tests/materials.test.js sie mit
einem Attrappenloader ohne echte Dateien prüfen kann: Diffuse allein,
Diffuse+Normal ohne ARM, der volle Satz, und weiterhin der einfarbige
Ersatz, wenn die Diffuse-Karte selbst fehlt.
2026-09-18 06:16:12 +02:00
knsoandClaude Opus 5 a0cd95cceb fix(showroom): Funde der Schlussdurchsicht auf der Testseite behoben
Die Spielfigur wirft jetzt einen Schatten (player.init durchlief applyCharacter
nie); drei stille Fehlerpfade meckern jetzt statt roh abzubrechen (fehlender
Clip fuer die Fingerhaltung, Waffe ohne Griff, mit neuem Test); die
Waffenauswahl im Panel zeigt Beschriftungen statt IDs; der Waffen-Umbau prueft
jetzt die Meshzahl je Datei; stageTransform ist aus main.js nach lineup.js
gezogen und mit dem im Browser gemessenen Fall getestet; slotPosition nimmt
DUMMIES als Argument statt es aus dem Modul zu lesen; dazu Kommentar- und
Entwurfskorrekturen (Docstring, Beckenspur-Test, Frustum-Culling, Port/Kamera/
VIEW_DISTANCE im Entwurf).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 03:19:42 +02:00
knsoandClaude Opus 5 12a77051d6 feat(showroom): Dummy aus Mannequin, Clip, Fingerhaltung und Waffe
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 22:33:35 +02:00
knsoandClaude Opus 5 149ec9c5d9 feat(showroom): Aufstellung der 13 Dummies mit Clips und Waffen
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 22:28:59 +02:00
knsoandClaude Opus 5 4422432998 feat(assets): elf Mocap-Clips als weapons-mocap.glb für das Mannequin
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 22:15:28 +02:00
knsoandClaude Sonnet 5 05e2914ff3 test(world): letzte Verweise auf alte Chunk-Schlüssel entfernen
parkData.test.js prüfte die Fahrzeug-Startpunkte noch gegen c.roads, den es im neuen
Chunk-Format nicht mehr gibt; jetzt gegen c.carriageway, die schärfere Aussage (das Auto
steht auf der Fahrbahn, nicht nur irgendwo im alten, breiteren Korridor). materials.test.js
und props.test.js trugen noch die toten Schlüssel roads/centerlines bzw. einen Kommentar auf
centerlines() — beides Relikte vor dem Straßen-Umbau, ersatzlos entfernt bzw. auf edges umformuliert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-17 22:15:26 +02:00
knsoandClaude Opus 5 aa6cde79d3 feat(assets): Blickrichtung, Drift und Schleifennaht der Mocap-Clips
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 21:46:51 +02:00
knsoandClaude Sonnet 5 62c8e267c4 test(world): Laterne außer Reichweite und markings-Versatz end-to-end abdecken
Ersetzt den zu schwachen Leerlisten-Test für sidewalkLampPoints() durch einen Fall mit
echter, aber für LAMP_VERGE zu weit entfernter Gehwegfläche, und belegt in materials.test.js,
dass applyPolygonOffsets() den eigenen markings-Versatz tatsächlich in ein Materialobjekt
durchreicht.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-17 21:44:42 +02:00
knsoandClaude Opus 5 070bb79593 feat(assets): Mocap-Knochen auf das Mannequin übertragen
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 21:34:38 +02:00
knsoandClaude Sonnet 5 25248b3929 feat(world): Materialien, Kollision und Laternen für die neuen Straßen
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-17 21:26:18 +02:00
knsoandClaude Opus 5 2a60f92539 feat(assets): fünf Waffen aus dem Pack als GLB mit WebP und meshopt
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 21:19:40 +02:00
knsoandClaude Opus 5 e97ef14f78 feat(assets): TGA-Maske, UV-Spiegelung und Längenprüfung für die Waffen
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 21:14:04 +02:00
knsoandClaude Sonnet 5 ca4f7161af feat(world): Fahrbahnmulde, Bordsteinwand und Markierungen bauen
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-17 21:02:14 +02:00
knsoandClaude Haiku 4.5 8f80c020c8 test(world): Bodenplatte-Test absichern und console.log entfernen
Fixrunde 1: Der Test „lässt kein Loch verschwinden" konnte nicht fehlschlagen,
weil er nur position.count prüfte, das vor der Triangulierung gefüllt wird.
Jetzt absichert footprintArea(geo) die tatsächliche Restfläche (18400 m²);
das console.log ist entfernt.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-17 00:05:55 +02:00
knsoandClaude Haiku 4.5 f301d39ea0 test(world): Bodenplatte mit vielen Löchern messen
Erstes Risiko des Entwurfs: die Fahrbahn wird als Loch aus der Bodenplatte
geschnitten, und ShapeUtils.triangulateShape läuft beim Nachladen im
Hauptthread. Der Test hält fest, dass 100 Löcher je Chunk unter 50 ms
bleiben und keines verschwindet.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-16 23:50:34 +02:00
knsoandClaude Sonnet 5 5e445c5a3e test(world): Sperrflächen, Startpunkt und Parkwege gegen die Daten prüfen
Startpunkt und Fahrzeugpunkte stehen jetzt in src/world/spawn.js, damit ein
Datentest sie lesen kann.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 08:49:42 +02:00
knsoandClaude Sonnet 5 b736afb7ff feat(world): Parkwege, Felder, Plätze, Pool und Parkplatz als eigene Schichten
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 08:34:43 +02:00
knsoandClaude Sonnet 5 aa699b1585 fix(test): zwei plattformabhängige Tests unter Windows neutral
GEOS setzt bei entarteten Eingaben je nach Plattform zusätzliche Punkte auf
eine Kante, und fileURLToPath liefert unter Windows Backslashes. Beide Tests
prüfen jetzt, was sie meinen: die Ecken des Rechtecks und den Ort im Baum.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-16 05:43:43 +02:00
knsoandClaude Sonnet 5 237a4ed389 test(world): ersetzte Grundrisse und feste Materialien je Ort strenger prüfen
Behebt Befunde 2-6 aus dem Abschluss-Review: der replaces-Test prüft
jetzt zusätzlich jede Ecke des getroffenen Grundrisses gegen die
Außenmaße plus REPLACED_OVERHANG (5 m), der Verteilungstest vergleicht
als Mengen und bekommt eine Gegenrichtung je Datei, BUMP_BY_PLACE
erzwingt eine Zeile je Ort statt sie mit "?? []" zu verdecken, ein
Gebäude an einer Chunkgrenze bekommt einen Test über zwei Chunks samt
JSDoc-Hinweis, und der Rückwand-Messwert in der Spec nennt Kapselmitte,
Wandfläche und Radius einzeln.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-15 03:57:31 +02:00
knsoandClaude Sonnet 5 190fe9c13c feat(world): Tribüne im Park J6 statt des alten Gebäudekastens
tribuene.glb mit places.mjs aufbereitet (6,3 MB -> 1,7 MB, 69 557 Dreiecke, 14 Primitive, 49 MB Grafikspeicher). PLACES-Eintrag bei (1409,9 | 1051,1), 45° gedreht, lift 0, replaces auf den 18,6 m hohen Kasten. Der Lage-Test übergeht ersetzte Grundrisse und prüft, dass jeder replaces-Punkt genau ein Gebäude unter dem Ort trifft.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 20:36:29 +02:00
knsoandClaude Sonnet 5 ae0f6106bb feat(world): Materialrollen der Tribüne, Asset-Test je Ort
Fest: Sichtbeton, Estrich, Verkleidung, Stahl, Trapezblech, Riffelblech, Verglasung, utility_box_01. Nahflächen: Sichtbeton, Estrich, Verkleidung, Stahl, Sitzschale. Kabel, Kabeldosen, Wandleuchten und Kästen auf 0,25. Der Asset-Test prüft jede Datei aus PLACES gegen ihre eigene Zeile fester Materialien statt gegen die ganze globale Liste, Bump nur beim Hood Yard.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 20:24:09 +02:00
knsoandClaude Opus 5 e33c1817ec feat(world): Gebäude, die ein Ort ersetzt, beim Chunk-Aufbau weglassen
withoutReplacedBuildings filtert die Grundrisse, in denen ein Weltpunkt aus PLACES[].replaces liegt; ChunkStreamer baut die Geometrie daraus, main.js übergibt die Punkte aller Orte. Damit entfallen Kasten, Schatten und Kollision des alten Gebäudes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 20:13:47 +02:00
knsoandClaude Sonnet 5 7e4af1d0bc docs: Hood-Yard-Spec mit Messwerten und Vorwärmen
Wortlaut: die Radien garantieren nur, dass die Chunks unter einem Ort
angefordert sind, solange er in der Szene ist — nicht, dass ihr Boden
schon gebaut ist (ChunkStreamer baut höchstens einen Chunk je Bild).
"geladen" -> "angefordert" im Kommentar über den Radien
(src/world/places.js), über der PlaceLayer-Konstruktion (src/main.js),
im Testnamen (tests/placesSite.test.js) und in der Spec, dort mit
einem Satz zu den paar Bildern nach einem Kartensprung.

Spec zusätzlich: warmUp in den Bullets "Vorbereiten"/"Einsetzen",
robustes Einsetzen (Warnung, kein erneuter Versuch) im Bullet zum
Ladefehler, und ein neuer Messwerte-Bullet in "Fehlerfälle und
Risiken" (+0,4–0,6 ms je Bild, ~130 ms einmaliger Texturupload ohne
warmUp).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 13:43:23 +02:00
knsoandClaude Sonnet 5 fc9e818c79 test(world): entquantisierte Positionen auch für interleaved Attribute
GLTFLoader liefert quantisierte Positionen in echt als
InterleavedBufferAttribute (gemeinsamer Puffer mit Normale/UV), nicht
als eigene BufferAttribute wie im bisherigen Test. dequantizePosition
braucht dafür keine Änderung: es liest nur über das gemeinsame
Attribut-Interface (normalized, getX/getY/getZ, count), das three.js
für beide Klassen implementiert. Der Test läuft grün und schreibt das
fest.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 13:41:46 +02:00
knsoandClaude Sonnet 5 23a0623898 fix(assets): Zielpfad der Aufbereitung unabhängig vom Arbeitsverzeichnis
places.mjs schrieb bisher nach public/models/places/<id>.glb relativ
zu process.cwd() und nahm jede id ungeprüft an. Die neue, exportierte
placeTarget(id) löst den Pfad stattdessen von import.meta.url ab (egal
von wo das Skript aufgerufen wird) und lehnt IDs außerhalb von
[a-z0-9-]+ ab, bevor daraus ein Pfad wird, der aus public/models/
places/ herausführen könnte.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 13:41:18 +02:00
knsoandClaude Sonnet 5 ed5254f88e fix(world): Einsetzen eines Orts gegen Collider-Fehler absichern
#show baute bisher scene.add, bevor player.addCollider lief: wirft
addCollider (z. B. toter Worker), blieb die Wurzel ohne active-Eintrag
in der Szene stehen — sichtbar, aber nie wieder entfernbar — und die
Ausnahme entkam synchron aus update() in die Spielschleife.

Der Collider-Handle wird jetzt vor scene.add in einem try/catch
gebaut; schlägt er fehl, bleibt die Szene unverändert, der Ort landet
in this.failed (kein erneuter Versuch) und #show überspringt ihn beim
nächsten Aufruf.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 13:40:28 +02:00
knsoandClaude Sonnet 5 1c24fbf71e feat(world): Orte beim Vorladen vorwärmen
PlaceLayer nimmt jetzt ein optionales warmUp(root) entgegen und ruft es
nach prepareModel, aber vor dem Einsetzen auf. main.js nutzt das, um
Texturen hochzuladen und CSM-Shader zu übersetzen, solange der Ort noch
nicht in der Szene ist — gemessen kostete das sonst rund 130 ms auf
einen Schlag im ersten Bild, in dem der Hof erscheint. Schlägt das
Vorwärmen fehl, wird nur gewarnt; der Ort wird trotzdem eingesetzt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 13:39:50 +02:00
knsoandClaude Sonnet 5 522101c026 fix(world): quantisierte Positionen vor dem Kollisionsaufbau in Float32 wandeln
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 12:42:25 +02:00
knsoandClaude Sonnet 5 ef2001542a feat(world): PlaceLayer lädt vor, setzt ein und nimmt heraus
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 11:26:34 +02:00
knsoandClaude Haiku 4.5 16eb651308 test(world): Lage der Orte gegen Straßen, Gebäude, Palmen, Laternen und Chunk-Radien
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-14 11:15:14 +02:00
knsoandClaude Haiku 4.5 d923f1ba2f feat(assets): Hood Yard aufbereitet (653,6 MB -> 16,2 MB)
2,9 Mio. -> 658 000 Dreiecke, 542 -> 43 Primitive, 105 PNG in 2048 px ->
32 WebP in 1024 px und 37 in 512 px. EXT_materials_bump der Container erhalten.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-14 11:08:26 +02:00
knsoandClaude Haiku 4.5 62dbbe41d2 feat(world): Orte-Liste mit Lage, Radien und Kollisionsmaterialien
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-14 10:59:02 +02:00
knsoandClaude Haiku 4.5 6c291c4106 feat(assets): Aufbereitung für Orte mit Texturgrößen je Material und Vereinfachung
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-14 10:49:31 +02:00
knsoandClaude Opus 5 0ebe8adb8b feat(assets): EXT_materials_bump für gltf-transform
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 10:39:39 +02:00
knsoandClaude Opus 5 f76e97b69d feat(world): HDRI-Himmel „Nowhere Road" mit Umgebungslicht und scharfen Kaskaden-Schatten
- Himmel: 4k-HDRI von Poly Haven (CC0, tools/assets/hdri.mjs) statt Sky-Shader. Kuppel zeigt das Foto
  ab 12°, darunter weiches Band und Dunst in Nebelfarbe; Umgebungslicht und Spiegelungen per PMREM;
  Sonne aus dem Bild gekappt und als Licht übernommen (77°, Stärke 2,5)
- Schatten: CSM mit vier Stufen (25/100/350/1000 m, je 2048²), Schutznetz für beleuchtete Materialien,
  Normal-Bias 1,5 Texel je Stufe gegen Streifen auf doppelseitigen Materialien (Figur, Autos)
- Startfigur wirft Schatten, Palmen und Laternen empfangen Schatten, Wasser als ruhige See
- Debug-Panel: Sonne, Himmelslicht, Himmelshelligkeit; Namensnennung um das HDRI ergänzt

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 15:38:44 +02:00
knsoandClaude Sonnet 5 dd5ced505b fix(ui): Landeplatz nur auf ganzem Kollisionsboden, Trackpad-Zoom, Fokus und Ladefehler der Minimap
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 12:47:51 +02:00
knsoandClaude Haiku 4.5 3b09482e6a fix(ui): Downtown-Bezugspunkt statt Downtown-Kern, leere Standortanzeige ausblenden
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-13 11:47:44 +02:00
knsoandClaude Haiku 4.5 c278f62cff feat(ui): Kartenmathematik für die Minimap
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-13 10:47:02 +02:00
knsoandClaude Haiku 4.5 f0f7692f14 fix(coords): Chunk-Namen korrekt für Float-Indizes und Newlines
- chunk_name: Reject float/bool indices like JavaScript (Number.isInteger)
- parse_chunk_name: Use fullmatch instead of match($) to reject strings with trailing newlines
- Add invalidIndices fixture cases to catch these edge cases in both languages

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-13 09:49:53 +02:00
knsoandClaude Haiku 4.5 2f63779363 feat(coords): Chunk-Namen als Planquadrat A1 bis L12
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-13 09:26:59 +02:00
knsoandClaude Sonnet 5 5c8df78246 fix(world): Flackernden Boden behoben (Tiefenpuffer-Versatz je Schicht, Brücke angehoben)
Downtown aus der Luft: Boden, Stadtfläche, Park, Strand und Straße lagen 1-2 cm
auseinander (geometry.js: SURFACE_OFFSET=0.02 für alle drei Flächen gleich,
ROAD_OFFSET=0.03), bei 150-300 m Kameraabstand unter der Auflösung eines
24-Bit-Tiefenpuffers (~1,3 cm bei 150 m, ~5 cm bei 300 m, gemessen mit dem alten
Nahwert 0.1) — Strand/Park/Stadtfläche lagen zusätzlich exakt aufeinander und
fighteten unabhängig von der Entfernung. Die Brückenoberkante lag exakt auf der
Bodenoberkante (beide y=0).

Vier Änderungen, freigegebener Entwurf:
- Kamera-Nahwert 0.1 -> 0.5 m (src/main.js): fünffache Tiefenauflösung auf jede
  Entfernung, far bleibt 2500.
- src/world/materials.js: POLYGON_OFFSETS/POLYGON_OFFSET_ORDER, eine feste,
  streng zunehmend negative Stufe je Schicht (Boden 0, Stadt -1, Park -2, Strand -3,
  Straße -4, für Faktor und Units gleich) — wirkt im Tiefenpuffer selbst, hält die
  Rangfolge deshalb auf jede Entfernung, unabhängig vom geometrischen Abstand.
  applyPolygonOffsets() ist eine separate, reine Funktion, damit sie ohne
  createMaterials()/Texturladen testbar ist und beweisbar nur diese fünf Materialien
  trifft (Brücken/Gebäude/Wasser/Meeresboden bleiben unberührt).
- Strand, Park und Stadtfläche bekommen dabei je eine eigene Stufe, statt sich wie
  bisher (SURFACE_OFFSET) eine zu teilen.
- src/world/geometry.js: Brückendeck-Oberkante jetzt BRIDGE_OFFSET (=SURFACE_OFFSET,
  0.02 m) statt 0 — derselbe Größenordnungsentscheid wie bei den Flächen, klein genug
  für einen unbemerkten Schritt, groß genug für die Tiefenpuffer-Auflösung bei 300 m.

TDD: Rangfolge/Kein-Teilen-Regeln sind rein und zuerst als fehlschlagende Tests
geschrieben (tests/materials.test.js, 5 neue), ebenso die Brückenanhebung
(tests/geometry.test.js, 1 neu) — beide zunächst rot, dann grün. 65 -> 71 Tests,
alle grün.

Browser-Verifikation (Downtown, Chunk 2_9, gleiche Kameraposition vorher/nachher):
das zuvor durchgängig zackige/zerstückelte Straßen-/Flächenbild ist jetzt glatt und
durchgängig lesbar. Ego-Perspektive dicht an einer Gebäudewand zeigt mit near=0.5
kein sichtbares Durchsehen. Details, Screenshot-Pfade und offene Punkte (Brücken-
Nahaufnahme nicht separat bestätigt) im Bericht:
.superpowers/sdd/2026-09-12-leonida-vice-slice/schichten-report.md

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 09:01:36 +02:00
knsoandClaude Sonnet 5 ad9bf63b36 fix(props): Straßenlaternen auf glaubwürdige Höhe skaliert, Fuß auf den Boden gehoben
street_lamp_02.glb ist nur 1,657 m hoch (per gltf-transform inspect gemessen:
bboxMax.y 1.26478 - bboxMin.y -0.39258) und ihr Fuß liegt unter dem Ursprung.
#buildLamps setzte das Modell bisher unskaliert auf y=0 — der Fuß steckt im Boden,
und 1,66 m ist ohnehin zu klein neben 10-18 m hohen Palmen und 10-28 m breiten
Straßen dieser Karte. Poly Havens eigene Angabe ("1.7m tall") bestätigt, dass die
Rohgröße korrekt gemessen ist — der Fehler liegt in der Verwendung dieser Rohgröße
in diesem Maßstab, nicht in der Messung selbst.

lampFit(minY, maxY, targetHeight) leitet Skalierung und Fuß-Anhebung aus der
gemessenen bbox her; STREET_LAMP_HEIGHT = 4.0 m als benannte Zielgröße (Mitte des
für dekorative Straßenlaternen üblichen 3-6-m-Bereichs). load() wendet beides auf
die Modellwurzel an, bevor die Teil-Matrizen (Mast, Glas) eingesammelt werden, damit
#buildLamps() unverändert bleiben kann.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 05:14:11 +02:00
knsoandClaude Sonnet 5 b273bb09cc fix(world): Chunk-Streaming, Auffangnetz und Schatten folgen dem Fahrzeug
playerCapsule.position ist beim Fahren nicht die Weltposition, sondern der lokale
Sitzplatz-Offset (syncMountedPlayer hängt die Kapsel an vehicleGroup und überschreibt
ihre .position mit driverSeatPosition * scale). main.js trieb Streaming, isReadyAt,
das Auffangnetz, lastSafe und den Schattenwurf trotzdem ausnahmslos damit an — die
Welt hörte beim Fahren auf nachzuladen.

src/player.js bündelt "wo ist der Spieler gerade" in playerPosition()/
playerIsGrounded(): Fahrzeugposition (vehicleGroup.position) und Radkontakt, wenn
eines aktiv ist, sonst Kapsel und das vorhandene getIsOnGround(). Zusätzlich über
getControllerMode() abgesichert, nicht nur getActiveVehicle() — Letzteres wird beim
Aussteigen vom Controller nie zurückgesetzt (nur destroy() tut das), im Browser
nachgewiesen: nach einem erzwungenen Ausstieg lieferte getActiveVehicle() weiterhin
das verlassene Fahrzeug, obwohl controllerMode schon wieder 0 war.

Im Browser mit von Hand angetriebenem tick()/player.update() verifiziert (die
automatisierte Vorschau drosselt requestAnimationFrame auf ~2 Hz): Fahrzeug 227
Einheiten bewegt, playerPosition() folgte exakt, vier neue Chunks luden nach
(Netzwerk-Log bestätigt), sichtbar andere Umgebung nach der Fahrt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 05:13:54 +02:00
knsoandClaude Opus 5 0ece90e2ec fix(ui): Höhe-Regler nachführen, Teleport-Warnfrist, SUV-Abstimmung
Der Höhe-Regler las den Höhenfaktor nur beim Bau des Panels und zeigte
nach einem Figurenwechsel weiter den alten Wert; beim nächsten Ziehen
überschrieb er die korrekt gesetzte Größe mit einem Sprung (Ruling 68).

Der Teleport hielt den Spieler notfalls unbegrenzt still. Er bekommt
dieselbe einmalige Warnung nach 15 s wie der Spawn, mit Frist je Sprung
statt modulweit (Ruling 69).

Der SUV bekommt metalness und roughness zurück, die der Kommentar
darüber als unverändert zusicherte (Ruling 70).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 04:14:01 +02:00
knsoandClaude Sonnet 5 182db238c6 fix: Retargeting auf absolute Rotation umgestellt (Ruling 67)
Beide Verfahren an allen drei Figuren durchprobiert statt vermutet:
Delta hielt Superhero Male/Female bei Idle_Loop und Walk_Loop in voller
T-Pose (upperarm_l weicht 70° von ual.glbs eigener Ruhepose ab, gegen
den A_TPose-Referenzclip gemessen — die Ruhepose-Differenz ist selbst
schon eine Pose, nicht der Bauartunterschied im Gradbereich, für den
Delta gedacht ist). Absolute liefert für beide einen sauberen Gang ohne
Schulterverdrehung; für Mannequin sind Delta und Absolute ohnehin
identisch (sourceRest===targetRest). Ein Verfahren trägt für alle drei.

retargetClips() behält "delta" als Voreinstellung (die im Auftrag
wörtlich vorgegebene Formel, weiterhin getestet); CHARACTERS trägt das
Messergebnis für dieses Projekt ein.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 03:40:24 +02:00
knsoandClaude Sonnet 5 d30aae68a1 feat: Figurenauswahl, Autos, Debug-Panel und Namensnennung
Task 11: Figuren (Mannequin/Superhero Male/Female) mit auf ual.glb
retargeteten Animationen, Frisuren, vier SUVs auf angehefteten Chunks,
ein lil-gui-Debug-Panel (Figur/Frisur/Höhe/Hitbox/Chunk-Grenzen/
Kartenbild/Nebel/Wahrzeichen-Sprung) und die verpflichtende
Namensnennung fürs HUD (Kartenkacheln, Wahrzeichen, SUV, Texturen,
Palme, Figuren — jede Quelle mit ihrer eigenen Lizenz).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 03:04:49 +02:00