Commit graph

7 commits

Author SHA1 Message Date
slyphax
4e973795f6 Malen: echter weicher Übergang am Pinselrand (Misch-Schicht statt Streuung)
Sly 25.10.: „weich“ soll ein Textur-Verlauf am Pinselrand sein, nicht fleckig;
gerade Strichkanten wirkten weiter hart (1-m-Übergang).
- Format (optional, alte Karten gültig): materials_b_r8_b64 (zweites Material
  je Punkt) + materials_w_r8_b64 (Anteil 0–255); ohne Mischung fallen die
  Felder weg. V15 prüft Länge/IDs/Paarigkeit.
- TerrainField.apply_material_brush_mix: innen voll, außen Smoothstep-Anteil;
  nur verstärken, nie abschwächen; Gras drübermalen mischt zurück.
- Shader: Top-2 aus 4 Nachbarpunkten × (a, b) mit Anteilen → nur noch 2
  Albedo-Fetches; Warp bleibt.
- Pinsel/Live-Vorschau, Spiegeln, Symmetrie-Analyse/-Anwenden, Resize,
  Anheben, Undo (terrain-Snapshot) tragen die Misch-Schicht mit.
- Streu-Rand (vorheriger Commit) entfernt.
- Tests: test_mal_fein 30/30 (Verlauf fällt weich, nie abschwächen,
  zurückmischen, Kodierung), Editor-Suite unverändert grün bis auf die
  bekannten Umgebungs-Tests; Kette Editor → Server → Client per
  run_map_download_e2e 15/15 mit gemischter Karte.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 00:43:26 +02:00
slyphax
4a7b99ee3e Malen: Regler „Kante hart ↔ weich“ + Pinsel ab 1 m
Sly 25.10.: harte Kanten an Strichrändern, Pinsel auf 1 m, Regler für die
Kantenschärfe.
- apply_material_brush(…, weichheit): im äußeren Anteil des Radius wird
  gestreut ausgedünnt (fester Hash je Punkt → deterministisch, Nachmalen
  füllt nicht auf); der Shader macht daraus einen ausfransenden Übergang.
  Kein Formatwechsel (ein Material je Punkt bleibt).
- Panel: Regler 0–100 % (Default 40 %), nur im Malen-Modus; Pinselgröße ab 1 m.
- test_mal_fein 26/26 (Dichte fällt nach außen, deterministisch, 1-m-Pinsel),
  test_terrain_mirror an die Tool-Weichheit angepasst.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 00:30:16 +02:00
Hermes (godot-vr)
e505329a42 Terrain B (t_234490cf): Pinsel-Position == Cursor-Position — Ray→Terrain-Mapping gefixt
Root-Cause 1 (Spiegelung): terrain_mesh.gd positionierte die Mesh-Vertices
gespiegelt (+0.5 − index·cell in X UND Z), während ALLE anderen Verbraucher
der Heightmap der Dokument-Konvention folgen (Index 0 = −X/−Z-Ecke):
SvmapDocument.terrain_height_at, TerrainField.height_at/apply_brush und der
Match-Client (svmap_terrain.gd). Der Renderer war der einzige Ausreißer —
der Pinsel-Strahl traf das gerenderte Mesh punktgespiegelt um die Map-Mitte
(Sly-Befund: Erhöhung erschien an ganz anderer Stelle). Fix: Vertices auf
−size*0.5 + index*cell (identisch zum Client), Normalen-Vorzeichen angepasst
(n ∝ (−∂h/∂x, 1, −∂h/∂z)); Winding bleibt gültig (180°-Rotation erhält die
Orientierung, Kreuzprodukt-Normale weiter nach unten = Frontseite).

Root-Cause 2 (Tangenten-Graze): Ein Strahl, der exakt auf eine Hügelkuppe
zielt, grast die gewölbte Oberfläche — f(t) bleibt minimal knapp über 0 und
steigt danach wieder, obwohl weiter hinten (VERDECKT hinter dem Hügel) noch
ein Vorzeichenwechsel an der Basis-Ebene lag. Der March lief durch und der
Pinsel sprang auf den verdeckten Basis-Punkt meterweit weg. Fix in
TerrainField.raycast: Regel 'erster sichtbarer Oberflächen-Kontakt gewinnt' —
kommt f innerhalb des Bandes (½ March-Schritt) an die Oberfläche und entfernt
sich der Strahl wieder, wird das Graze-Minimum lokal per Ternärsuche
verfeinert und als Treffer zurückgegeben. Echter Treffer (f ≤ 0) gewinnt
weiterhin immer; betrifft auch Bauen-Werkzeug und Spawn-Zonen (gleiche
Raycast-Routine).

Tests (test_terrain.gd, 64 → 86 Checks): Neue Gruppe 'Ray→Terrain-Mapping'
mit simulierter Kamera (SubViewport, schief + steil): exakter Screen-Punkt
(unproject) → project_ray → raycast → asserted Treffer-Zelle == Cursor-Zelle
(< 1 Zelle) auf Mitte/Innenraum/Corner/Kanten; Brush-Stroke am Treffer mit
Höhen-Änderungs-Zentrum == erwarteter Zelle; erhabenes Terrain (Strahl trifft
NEUE Oberfläche, y = Hügelhöhe); Mesh-Vertices komplett gegen die
Dokument-Konvention asserted (Root-Cause-Regression). Hügel-Normalen-Checks
auf die korrigierte Konvention umgestellt (lehnt jetzt −X/−Z).

Suite: 7 Editor-Suiten 463 Checks grün + Export 21/0 + GUI-Smoke 20 grün.
2026-10-16 17:27:19 +00:00
Hermes godot-vr
23ede45efd M2-Karte t_603ec1a8: Terrain-Texturen (Gras/Sand/Fels) + Pinselgroessen. svmap v2: optionale Material-Schicht materials_r8_b64 (uint8/res², 0=Gras/1=Sand/2=Fels), V15-Validierung (Laenge+ID-Range), Legacy-v1 laedt mit Default Gras, gespeichert wird immer v2. TerrainField: Mode.PAINT + apply_material_brush (Kreis, crisp, Hoehe unangetastet). terrain_tool: 4. Pinsel-Modus Malen (Palette Gras/Sand/Fels, Rechtsklick malt Gras zurueck), Ring in Materialfarbe; ganzer Strich = EIN ActionHistory-Eintrag (terrain-Block-Snapshot deckt Hoehe+Material ab). main.gd: Palette-Panel (nur im Malen-Modus), drei Pinselgroessen-Presets Klein(4m)/Mittel(12m)/Gross(32m) + freier Slider, deutsche Labels. terrain_mesh: Vertex-Farben aus Material-Schicht x Hoehe-Shading (KEIN Custom-Shader, Quest-3-Perf-Vertrag — Entscheidung gegen Splattmap in DECISIONS.md). Tests: test_terrain +3 Gruppen (Material-Pinsel, Mal-Stroke-Undo byte-identisch, v2/V15+Legacy) -> 53 Checks; Suite 231 Checks gruen. 2026-10-15 15:42:05 +00:00
Hermes (godot-vr)
0a0ca65846 Terrain: apply_brush — fehlender z += 1 im äußeren Loop ergänzt (Endlosschleife beim Pinsel-Auftrag, 3 hängende Headless-Runs) 2026-10-15 10:58:53 +00:00
Hermes (godot-vr)
10fdb4914c Terrain: Parse-Fixes — PackedFloat32Array hat kein .min()/.max() (_min_h/_max_h), stray y += 1 in apply_brush entfernt, Default-Resolution 129 (Editor-MVP-Limit) 2026-10-15 10:36:06 +00:00
Hermes (godot-vr)
30379bcc7b M2-Karte t_9aba04f1: Terrain-Werkzeug — Höhenfeld heben/senken/glätten (Pinsel + Undo)
TerrainField (src/svmap/terrain_field.gd): Höhenfeld-Mathematik auf dekodiertem
PackedFloat32Array — Pinsel mit Kosinus-Falloff (RAISE/LOWER/SMOOTH, zweiphasiges
3x3-Glättung), R16-Encode (uint16 LE row-major), ray-march+Bisektion-Cursor auf
dem GELÄNDE (nicht Basis-Ebene). EDITOR_MAX_RESOLUTION=129 (Editor-MVP-Perf-Limit,
Format bleibt 17-513 für Interop).

TerrainMeshView (src/viewport/terrain_mesh.gd): Höhenfeld als ArrayMesh mit
Höhen-Farbverlauf (Vertex-Farben); update_heights schreibt Vertices live neu
während des Strichs (res 129 = 16,6k Punkte, flott). Ersetzt die flache
Boden-Plane in map_view_builder (rebuild + rebuild_terrain_from_doc + update_terrain).

TerrainTool (src/editor/terrain_tool.gd): Pinsel-Modus im Viewport — Linksklick-
Ziehen formt (Heben/Senken/Glättten nach Panel-Wahl), Rechtsklick-Ziehen das
Gegenteil (kein Umschalten nötig). Pinsel-Ring (Torus) folgt dem Cursor auf dem
Terrain, farbcodiert pro Modus. GANZER Strich = EIN ActionHistory-Eintrag
(snapshot terrain VOR dem Strich, commit NACH dem Encode). Range-Expansion:
min/max_height_m weiten sich automatisch auf, wenn der Pinsel drüber hinaus will
(sonst wäre Senken auf flacher Map unmöglich) — Spannweite ≤ 500 m (V6), Undo
stellt die Range mit zurück. Doc wird nur ZUM Strich-Ende verändert.

main.gd: Werkzeug-Button 'Terrain formen' (groß, deutsch), Terrain-Panel mit
Heben/Senken/Glättten-Buttons + Pinsel-Größe/Stärke-Slider mit Live-Werten,
Modus-Wechsel objects<->terrain (Bibliothek-Klick wechselt zurück, ESC beendet),
interaction.gd ruht im Terrain-Modus. Performance-Zähler in der Statusleiste:
Terrain-Grid + Dreiecke (+ % vom Quest-3-Budget 524.288) + Editor-FPS.
Demo-Hook --terrain-demo [ordner]: 5 Szenarien inkl. Undo-Roundtrip als PNGs.

Neue Maps: res 129 (vorher 257) — erfüllt das Editor-MVP-Perf-Limit automatisch.
2026-10-15 10:30:42 +00:00