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>
This commit is contained in:
knsoandClaude Sonnet 5 committed 2026-09-18 09:06:40 +02:00
1 parent 349212fedf
commit 2e7b30fd15
7 files changed
+30 -14

No files matched your search

@@ -90,6 +90,8 @@ Ein 15-cm-Bordstein hält den Spieler also nicht auf, er ist eine Stufe. Fahrzeu
Zwei Dinge liegen damit fest. Erstens: Das Straßen-Kit taugt nicht für die Fahrbahn — 4,2 m gegen 13,4 m gemessene Korridorbreite, und seine Markierungen sind europäisch (gelbe Randlinien, weiße gestrichelte Mitte), also das Gegenteil des amerikanischen Schemas. Zweitens: Das Bordstein-Kit besteht aus 16 Kästen mit zusammen 351 Punkten; seine Substanz sind die Texturen, nicht die Geometrie. 177 km Bordsteinkante wären in 3-m-Modulen rund 59.000 Einzelteile. Zwei Dinge liegen damit fest. Erstens: Das Straßen-Kit taugt nicht für die Fahrbahn — 4,2 m gegen 13,4 m gemessene Korridorbreite, und seine Markierungen sind europäisch (gelbe Randlinien, weiße gestrichelte Mitte), also das Gegenteil des amerikanischen Schemas. Zweitens: Das Bordstein-Kit besteht aus 16 Kästen mit zusammen 351 Punkten; seine Substanz sind die Texturen, nicht die Geometrie. 177 km Bordsteinkante wären in 3-m-Modulen rund 59.000 Einzelteile.
**Korrektur (Gehwegtextur-Korrektur, 2026-09-18):** Die Zeile „Brauchbar als: Profil und Texturen für Bordstein und Gehweg" gilt nur noch für den Bordstein. `sidewalk_Diffuse.jpg` aus `modular_sidewalk_curb_kit` ist kein Betonbild, sondern das Platzhalterbild des Kits — dunkler Grund, roter Schriftzug „Tru-planar Sidewalk texture", im Browser geprüft. Solange `loadSet()` an der fehlenden Normal- und ARM-Karte scheiterte, fiel der Gehweg auf den einfarbigen Ersatz zurück und niemand bemerkte es; sobald `loadSet()` auch ohne die beiden Beiwerke lädt (s. Abschnitt „Texturen aus dem Kit" unten), kachelt der Schriftzug über die ganze Stadt. Der Gehweg benutzt deshalb `concrete_pavement` von Poly Haven (CC0), dieselbe Textur wie die Parkwege (`TEXTURES.paths`). Der Bordstein bleibt beim Kit — `curb_Diffuse.jpg` ist eine echte Betontextur mit Fugen, im Browser geprüft.
## Entscheidungen des Nutzers ## Entscheidungen des Nutzers
| Frage | Entscheidung | | Frage | Entscheidung |
@@ -203,7 +205,7 @@ Der Schritt überspringt still, was schon da ist, und meldet verständlich, wenn
`sidewalk_metallicRoughness.png` ist eine 605 Byte große Einfarbfläche und wird nicht übernommen; eine Normal-Map für den Gehweg liefert das Kit nicht. `sidewalk_metallicRoughness.png` ist eine 605 Byte große Einfarbfläche und wird nicht übernommen; eine Normal-Map für den Gehweg liefert das Kit nicht.
**Namensnennung:** `manifest.json` und die Zeile im Spiel bekommen „Bordstein und Gehweg: Just8 (Sketchfab, CC BY 4.0)". Das Straßen-Kit wird in dieser Arbeit nicht benutzt und deshalb auch nicht genannt. **Namensnennung:** `manifest.json` und die Zeile im Spiel bekommen „Bordstein: Just8 (Sketchfab, CC BY 4.0)". Das Straßen-Kit wird in dieser Arbeit nicht benutzt und deshalb auch nicht genannt. Der Gehweg kommt seit der Korrektur oben (Abschnitt „Die beiden Kits") von Poly Haven (CC0) und bleibt deshalb wie die übrigen Poly-Haven-Texturen ohne eigene Namensnennung.
## Chunk-Format ## Chunk-Format
@@ -239,7 +241,7 @@ Die Ausgabe bleibt normalisiert und sortiert (Fixrunde 3 aus Teil 1): `shapely.n
|---|---| |---|---|
| `carriageway` | `asphalt_02` mit `ROAD_TINT`, wie die heutige Straße | | `carriageway` | `asphalt_02` mit `ROAD_TINT`, wie die heutige Straße |
| `curb` | `curb` aus dem Kit, mit Normal- und ARM-Karte | | `curb` | `curb` aus dem Kit, mit Normal- und ARM-Karte |
| `sidewalk` | `sidewalk` aus dem Kit | | `sidewalk` | `concrete_pavement` von Poly Haven, s. Korrektur oben („Die beiden Kits") |
| `markings` | unbeleuchtet, Vertexfarben, ohne Textur | | `markings` | unbeleuchtet, Vertexfarben, ohne Textur |
- **Tiefenpuffer:** `POLYGON_OFFSET_ORDER` bekommt `sidewalk` und `lots` zwischen den Belägen und `markings` ganz vorn. `carriageway` und `curb` brauchen keinen Versatz — sie liegen 15 cm tiefer und sind echte Geometrie, keine Auflage. - **Tiefenpuffer:** `POLYGON_OFFSET_ORDER` bekommt `sidewalk` und `lots` zwischen den Belägen und `markings` ganz vorn. `carriageway` und `curb` brauchen keinen Versatz — sie liegen 15 cm tiefer und sind echte Geometrie, keine Auflage.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

+4 -1
View File
@@ -270,7 +270,10 @@ export function buildChunkGeometry(chunk) {
carriageway: flatPolygons((chunk.carriageway ?? []).map((c) => c.poly), carriageway: flatPolygons((chunk.carriageway ?? []).map((c) => c.poly),
{ y: -CARRIAGEWAY_DEPTH, uvScale: 8 }), { y: -CARRIAGEWAY_DEPTH, uvScale: 8 }),
curb: kerbGeometry(chunk.curb ?? [], (chunk.carriageway ?? []).map((c) => c.poly)), curb: kerbGeometry(chunk.curb ?? [], (chunk.carriageway ?? []).map((c) => c.poly)),
sidewalk: flatPolygons((chunk.sidewalk ?? []).map((s) => s.poly), { y: SURFACE_OFFSET, uvScale: 4 }), // Korrektur: derselbe Belag wie paths (concrete_pavement), also auch dasselbe uvScale —
// Poly Haven misst die Kachel mit 1,8 × 1,8 m (s. Kommentar bei paths unten); mit 4 wären
// die Platten um mehr als das Doppelte gestreckt.
sidewalk: flatPolygons((chunk.sidewalk ?? []).map((s) => s.poly), { y: SURFACE_OFFSET, uvScale: 1.8 }),
markings: markingGeometry(chunk.markings ?? [], (chunk.bridges ?? []).map((b) => b.poly)), markings: markingGeometry(chunk.markings ?? [], (chunk.bridges ?? []).map((b) => b.poly)),
lots: flatPolygons((chunk.lots ?? []).map((l) => l.poly), { y: SURFACE_OFFSET, uvScale: 8 }), lots: flatPolygons((chunk.lots ?? []).map((l) => l.poly), { y: SURFACE_OFFSET, uvScale: 8 }),
bridges: extrudePolygons((chunk.bridges ?? []).map((b) => b.poly), bridges: extrudePolygons((chunk.bridges ?? []).map((b) => b.poly),
+6 -2
View File
@@ -13,11 +13,15 @@ export const TEXTURES = {
// Parkplatz im Asphalt der Straßen. Beide lädt createMaterials nicht neu, sondern klont park und carriageway. // Parkplatz im Asphalt der Straßen. Beide lädt createMaterials nicht neu, sondern klont park und carriageway.
field: "leafy_grass", field: "leafy_grass",
parking: "asphalt_02", parking: "asphalt_02",
paths: "concrete_pavement", // helle Betonplatten, auch für die Gehwege aus Teil 2 gedacht paths: "concrete_pavement", // helle Betonplatten, seit Teil 2 auch für den Gehweg (sidewalk unten)
carriageway: "asphalt_02", carriageway: "asphalt_02",
lots: "asphalt_02", // Parkplätze und Vorplätze: derselbe Asphalt wie die Fahrbahn lots: "asphalt_02", // Parkplätze und Vorplätze: derselbe Asphalt wie die Fahrbahn
curb: "curb", // modular_sidewalk_curb_kit (Just8, CC BY 4.0), s. tools/assets/textures.mjs curb: "curb", // modular_sidewalk_curb_kit (Just8, CC BY 4.0), s. tools/assets/textures.mjs
sidewalk: "sidewalk", // Korrektur: sidewalk_Diffuse.jpg aus modular_sidewalk_curb_kit ist keine Betontextur, sondern
// das Platzhalterbild des Kits (roter Schriftzug "Tru-planar Sidewalk texture" auf dunklem
// Grund, im Browser geprüft) - das Kit taugt deshalb nur für den Bordstein. Derselbe Wert wie
// TEXTURES.paths, s. Entwurf Abschnitt "Die beiden Kits".
sidewalk: "concrete_pavement",
// Ruling 56: eine Brücke ist in den Daten dasselbe Straßenstück, nur über Wasser — dieselbe // Ruling 56: eine Brücke ist in den Daten dasselbe Straßenstück, nur über Wasser — dieselbe
// Textur wie die Fahrbahn, sonst zeigt jeder Straße-Brücke-Übergang eine Farbnaht. // Textur wie die Fahrbahn, sonst zeigt jeder Straße-Brücke-Übergang eine Farbnaht.
bridges: "asphalt_02", bridges: "asphalt_02",
+6 -2
View File
@@ -105,9 +105,13 @@ describe("Schichten aus Teil 2", () => {
expect(MATERIAL_KEYS).not.toContain("roads"); expect(MATERIAL_KEYS).not.toContain("roads");
}); });
it("nimmt Bordstein und Gehweg aus dem Kit", () => { it("nimmt den Bordstein aus dem Kit, den Gehweg aus den Betonplatten von Poly Haven", () => {
// Korrektur: sidewalk_Diffuse.jpg aus dem Kit ist ein Platzhalterbild (roter Schriftzug),
// keine Betontextur (im Browser geprüft) - der Gehweg benutzt deshalb denselben Belag wie
// die Parkwege, nicht den Kit-Slug.
expect(TEXTURES.curb).toBe("curb"); expect(TEXTURES.curb).toBe("curb");
expect(TEXTURES.sidewalk).toBe("sidewalk"); expect(TEXTURES.sidewalk).toBe("concrete_pavement");
expect(TEXTURES.sidewalk).toBe(TEXTURES.paths);
expect(TEXTURES.carriageway).toBe("asphalt_02"); expect(TEXTURES.carriageway).toBe("asphalt_02");
expect(TEXTURES.lots).toBe("asphalt_02"); expect(TEXTURES.lots).toBe("asphalt_02");
}); });
+9 -6
View File
@@ -24,10 +24,14 @@ for (const slug of SLUGS) {
} }
} }
// Bordstein und Gehweg kommen aus modular_sidewalk_curb_kit (Just8, CC BY 4.0). Der Ordner // Der Bordstein kommt aus modular_sidewalk_curb_kit (Just8, CC BY 4.0). Der Ordner gehört dem
// gehört dem Nutzer und liegt nicht im Repo — das Skript darf deshalb nicht von ihm abhängen, // Nutzer und liegt nicht im Repo — das Skript darf deshalb nicht von ihm abhängen, sondern
// sondern überspringt den Schritt mit einer verständlichen Meldung, wenn er fehlt. Die vier // überspringt den Schritt mit einer verständlichen Meldung, wenn er fehlt. Die drei erzeugten
// erzeugten Dateien sind versioniert, danach braucht niemand mehr den Ordner. // Dateien sind versioniert, danach braucht niemand mehr den Ordner.
// Korrektur: sidewalk_baseColor.jpeg (-> sidewalk_Diffuse.jpg) ist raus. Die Datei war das
// Platzhalterbild des Kits, keine Betontextur (roter Schriftzug "Tru-planar Sidewalk texture",
// im Browser geprüft) - der Gehweg benutzt jetzt concrete_pavement von Poly Haven, s.
// src/world/materials.js.
// Über CURB_KIT umstellbar, damit der Fall "Kit fehlt" geprüft werden kann, ohne den Ordner // Über CURB_KIT umstellbar, damit der Fall "Kit fehlt" geprüft werden kann, ohne den Ordner
// des Nutzers zu verschieben. // des Nutzers zu verschieben.
const KIT = `${process.env.CURB_KIT ?? "modular_sidewalk_curb_kit"}/textures`; const KIT = `${process.env.CURB_KIT ?? "modular_sidewalk_curb_kit"}/textures`;
@@ -37,7 +41,6 @@ const KIT_MAPS = [
{ from: "CurbMat_baseColor.jpeg", to: "curb_Diffuse.jpg" }, { from: "CurbMat_baseColor.jpeg", to: "curb_Diffuse.jpg" },
{ from: "CurbMat_normal.png", to: "curb_nor_gl.jpg" }, { from: "CurbMat_normal.png", to: "curb_nor_gl.jpg" },
{ from: "CurbMat_metallicRoughness.png", to: "curb_arm.jpg" }, { from: "CurbMat_metallicRoughness.png", to: "curb_arm.jpg" },
{ from: "sidewalk_baseColor.jpeg", to: "sidewalk_Diffuse.jpg" },
]; ];
async function importCurbKit() { async function importCurbKit() {
@@ -53,7 +56,7 @@ async function importCurbKit() {
continue; continue;
} }
// 1024 wie alle übrigen Texturen: die 2048er des Kits wären für ein 15 cm hohes // 1024 wie alle übrigen Texturen: die 2048er des Kits wären für ein 15 cm hohes
// Wandband und einen Gehwegbelag Verschwendung. // Wandband Verschwendung.
await sharp(`${KIT}/${from}`).resize(1024, 1024).jpeg({ quality: 90 }).toFile(target); await sharp(`${KIT}/${from}`).resize(1024, 1024).jpeg({ quality: 90 }).toFile(target);
console.log(`${to} erzeugt`); console.log(`${to} erzeugt`);
} }
+1 -1
View File
@@ -170,7 +170,7 @@ def main() -> None:
"attribution": "Kartenkacheln: GTA VI Map (CC BY 4.0) — https://map.gtadb.org, YANIS v15. " "attribution": "Kartenkacheln: GTA VI Map (CC BY 4.0) — https://map.gtadb.org, YANIS v15. "
"Wahrzeichen: rolux/gtamaplib-vc (Unlicense). " "Wahrzeichen: rolux/gtamaplib-vc (Unlicense). "
"Flamingo Park: © OpenStreetMap-Mitwirkende (ODbL). " "Flamingo Park: © OpenStreetMap-Mitwirkende (ODbL). "
"Bordstein und Gehweg: Just8 (Sketchfab, CC BY 4.0).", "Bordstein: Just8 (Sketchfab, CC BY 4.0).",
}) })
print(render_map(OUT, OUT), "->", OUT) print(render_map(OUT, OUT), "->", OUT)