From 2c8ad8fe348fe52c9a957ffffbca06502f8ab319 Mon Sep 17 00:00:00 2001 From: Karim Date: Sun, 5 Jul 2026 20:31:04 +0200 Subject: [PATCH] =?UTF-8?q?Fix:=20Kreise/B=C3=B6gen=20im=20WebGL-Renderer?= =?UTF-8?q?=20sichtbar=20(drawingCircle/drawingArc=20tesselliert;=20Regres?= =?UTF-8?q?sion=20aus=204ac99d3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PENDENZEN.md | 1 + src/plan/glPlan/glPlanCompile.ts | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/PENDENZEN.md b/PENDENZEN.md index e7ac8ae..243353c 100644 --- a/PENDENZEN.md +++ b/PENDENZEN.md @@ -107,6 +107,7 @@ _Nur jüngste Session; ältere Historie siehe `git log` und HANDOVER-Narrative._ +- [x] 2026-07-05 **Fix: gezeichnete/importierte Kreise+Bögen im WebGL unsichtbar** — der WebGL-Compiler (`glPlan/glPlanCompile.ts`, Default-Renderer) dispatchte `polygon`/`line`/`arc`, aber NICHT `drawingCircle`/`drawingArc` → seit `4ac99d3` (Kreise als echtes `drawingCircle`-Primitiv statt 64-Eck-Polygon) fielen sie im GL still raus (SVG-/WASM-Pfad hatten sie, GL nicht). Zweig ergänzt: bildschirm-adaptive Tessellierung wie beim `arc`-Primitiv (Kreis geschlossen + optionale Vollton-Füllung, Bogen a0..a1 offen). tsc + Suite 334 grün. **Nutzer-Report** („zeichne Kreis, bleibt nicht sichtbar"). - [x] 2026-07-05 **Textur-Spike verifiziert erledigt** (`0ca3b1d`) — bei der Backlog-Abarbeitung festgestellt, dass die render3d-Textur-Spike (`RenderStyle::Textured`, Schachbrett, planare Meter-UVs, `MESH_TEXTURED_WGSL` group 1, `spike3d`-`T`-Toggle) bereits vollständig umgesetzt + committet war; `cargo test` 58/59 grün, keine neuen Deps, Alt-Pfad bitgleich. „Als Nächstes"-Eintrag war veraltet → abgehakt; PBR-Restlückenliste (~18–29 PT) in 3D-REST übernommen. - [x] 2026-07-05 **Ribbon-Feinschliff (OCS-Zeile)** — Tabs in die TopBar-Zeile verlegt (`456ebc8`, eine Leiste Chrome+Tabs, Inhalt darunter; Tab-State in App); OCS-Chrome: kleine Wortmarke „dossier." + Quick-Access-Icons für ALLE Datei-/Export-Aktionen statt Burger-Menü, Zeile auf 26px (`4e3b074`); Text-/Font-Formatierung mit der Ansichts-/Zoom-Steuerung auf EINE Leiste gelegt, „Ansichten" als Standard-Tab zuerst + initial aktiv (`fe22cbf`). Alle tsc + 331 Tests grün. Visuelle Abnahme (26px, Icon-Sitz) noch offen. - [x] 2026-07-05 **Ribbon Phase 2: TopBar → „Ansichten"-Tab gemergt** (`85011cb`, Nutzer-Entscheid „voll mergen") — die Ansichts-/Zoom-/Darstellungs-Cluster der TopBar (View-Grid+Kamera, Ebenen-/Zeichnungs-Kombis, Detailgrad, Massstab/Zoom, Darstellungsart) als `ViewRibbonTab` (in `TopBar.tsx`) in den Ansichten-Tab verschoben; App reicht sie als `viewsContent`-Node an `RibbonBar` (analog Layout-Menü). TopBar ist jetzt schmale globale Leiste (Marke/Ressourcen · Text · Datei/Export/Einstellungen · Fensterknöpfe). `TopBarProps` entsprechend verschlankt. Visuelle Feinabstimmung offen. diff --git a/src/plan/glPlan/glPlanCompile.ts b/src/plan/glPlan/glPlanCompile.ts index af2cbd4..add8cce 100644 --- a/src/plan/glPlan/glPlanCompile.ts +++ b/src/plan/glPlan/glPlanCompile.ts @@ -476,6 +476,54 @@ export function compilePrimitivesToGpu( arcPts.push({ x: c.x + prim.r * Math.cos(t), y: c.y + prim.r * Math.sin(t) }); } strokePolyline(arcPts, false, color, strokeMm); + } else if (prim.kind === 'drawingCircle' || prim.kind === 'drawingArc') { + // 2D-Zeichnungs-Kreis/-Bogen (Kreis-/Bogen-Werkzeug ODER DXF-Import). Der + // SVG-Pfad zeichnet sie als glattes /; die WebGL-Ebene kennt + // kein Kreis-Primitiv → hier bildschirm-adaptiv tessellieren (wie 'arc'). + // Kreis = voller Umlauf (geschlossen, optional gefüllt), Bogen = a0..a1 (CCW, + // offen). OHNE diesen Zweig blieben gezeichnete Kreise/Bögen im GL unsichtbar. + const stroke = parseColor(prim.stroke) ?? [0.1, 0.1, 0.1, 1]; + const strokeMm = prim.weightMm || 0.18; + const c = prim.center; + const TAU = Math.PI * 2; + const a0 = prim.kind === 'drawingArc' ? prim.a0 : 0; + const sweep = + prim.kind === 'drawingArc' + ? ((prim.a1 - prim.a0) % TAU + TAU) % TAU || TAU + : TAU; + // Segmentzahl wie im 'arc'-Zweig: Sagitta < ~0.5 px (LOD über pxPerMeter). + let segs: number; + if (pxPerMeter > 0) { + const rPx = prim.r * pxPerMeter; + const theta = rPx > 0.5 ? 2 * Math.acos(1 - 0.5 / rPx) : Math.PI; + segs = Math.min(2048, Math.max(8, Math.ceil(sweep / theta))); + } else { + segs = Math.max(8, Math.ceil((sweep / (Math.PI / 2)) * 16)); + } + const pts: Vec2[] = []; + for (let i = 0; i <= segs; i++) { + const t = a0 + (sweep * i) / segs; + pts.push({ x: c.x + prim.r * Math.cos(t), y: c.y + prim.r * Math.sin(t) }); + } + // Vollton-Füllung nur beim geschlossenen Kreis (Bogen ist offen). + if (prim.kind === 'drawingCircle') { + const fill = parseColor(prim.fill); + if (fill) { + const ring = pts.slice(0, segs); // ohne den doppelten Schlusspunkt + const tris = triangulate(ring); + if (tris.length) { + const base = fillPos.length / 2; + for (const pt of ring) { + const s = toScreen(pt); + fillPos.push(s.x, s.y); + track(pt.x, pt.y); + } + for (const t of tris) fillIdx.push(base + t); + addFillBatch(tris.length, fill); + } + } + } + strokePolyline(pts, prim.kind === 'drawingCircle', stroke, strokeMm); } // Text: bleibt im SVG-Overlay (scharfe Schrift, DOM-Hit-Test). }