Commit Graph

21 Commits

Author SHA1 Message Date
karim 1407c68232 Nordstern-3D: Fenster/Tueren als echte Boolean-Loecher in EINEM Wandkoerper
Bisher zerlegte emitWall eine Wand um jede Oeffnung in Pfeiler/Bruestung/Sturz-
Teilquader -> sichtbare Segment-Naehte im 3D, Oeffnung war semantisch kein Loch,
und versetzt uebereinanderliegende Fenster liessen sich gar nicht abbilden. Neu:
im 3D-Pfad (layered=true) EIN RWall pro Schicht-Band ueber die volle Achse mit
allen Oeffnungen als rechteckige holes; render3d stanzt sie per achsparalleler
Rechteck-Gitter-Zerlegung der Langseiten aus und setzt 4 Laibungsquads je Loch.
holes und openings schliessen sich im Emitter gegenseitig aus. Tuer = Loch bis
zum Wand-zBottom. Schnitt-Pfad (layered=false) segmentiert unveraendert weiter
(wallSegmentOwners bleibt synchron, toSection.ts unangetastet).

Zusatz: trimWallTopForCeilings (Deckentrim, e4b8df6) gilt jetzt NUR im 3D-Pfad
(layered=true, Z-Fighting-Vermeidung) und wird im Schnitt-Pfad uebersprungen -
der Schnitt braucht die volle Wandhoehe fuer seine schichtweise Prioritaets-
Subtraktion (Kontrolle von Schichteinzug/Bodenaufbau am Wand-Decken-Anschluss).

RWall.holes / WallInput.holes additiv (#[serde(default)]). Pflicht-Testfaelle:
zwei ueberlappende, hoehenversetzte Fenster in einem Koerper; Tuer-Loch bis Boden
ohne untere Laibung. cargo test 56 gruen, vitest 230 (+3), build:engine3d + tsc
sauber.
2026-07-04 22:17:21 +02:00
karim 03f0c402b5 Nordstern-3D: Live-Schnittebene mit schraffierten Schnittflaechen
Der 3D-Viewport kann das Modell jetzt live an einer vertikalen Ebene
aufschneiden (Overlay-Button 'Schnittebene', MVP: Ebene durch die
Modellmitte, Blick +Y):
- Globals um section_plane vec4 erweitert (xyz=Normale, w=-n*p; Enable
  in mode.y); MESH_/GRID_WGSL discarden Fragmente vor der Ebene
  (world_pos als neuer Varying) - Flaechen, Kanten, Grid, Highlight.
- section_fill.rs (neu): build_cut_caps ruft cut_section und trianguliert
  jedes (u,v)-Rechteck zurueck in Weltkoordinaten ([x,y,z,u,v]).
- CAP_WGSL: prozedurale 45-Grad-Diagonalschraffur aus (u,v) in Modell-
  Metern (fwidth-AA), Tinte auf Papier wie die 2D-Konvention; eigene
  cap_pipeline (CullMode::None, Depth-Bias Richtung Kamera gegen
  Z-Fighting), gezeichnet nach den Flaechen, nicht geclippt.
- web.rs cached walls/slabs; set_section_plane(active, p, n) aktualisiert
  Uniform + Caps; set_model baut Caps bei aktivem Schnitt neu.
- useWasm3dRenderer.setSectionPlane + Toggle in Wasm3DViewport.

Bekannte Luecken (dokumentiert): Oeffnungen im 3D-Solid nicht ausgespart
(cut_section spart aus -> Mismatch bei Schnitt durchs Fenster; wird mit
dem Boolean-Loecher-Slice geloest), nur vertikale Ebenen, ein globales
Muster (per-Bauteil = Stufe 2). cargo 56 Tests + naga-WGSL-Validierung,
222 vitest gruen, WASM neu gebaut (pkg3d gitignored).
2026-07-04 15:08:41 +02:00
karim fabf97a402 Nordstern-3D: Auswahl-Highlight (orange Outline, immer sichtbar)
Ein selektiertes Bauteil wird jetzt im 3D-Viewport mit einer orangen
Umrisslinie markiert, die dank No-Depth-Pipeline auch hinter Wänden
durchscheint (klare Selektions-Rückmeldung). Zusammen mit Objekt-Info
(numerisch) und Attribute-Panel ist die 3D-Auswahl damit vollständig.

- Engine: set_highlight_lines(vertices) + highlight_pipeline
  (LineList, depth_compare Always, kein Depth-Write), als letzter
  Draw-Call obenauf. Reuse der Grid-Linien-Infrastruktur.
- TS: selectionHighlightLines() baut die Quader-/Prisma-Kanten der
  Auswahl in Akzentfarbe; App berechnet sie per useMemo aus der
  Store-Auswahl und reicht sie durch.
2026-07-04 06:26:29 +02:00
karim 6ef57b6b6b Nordstern-3D: View-Styles wireframe + hidden-line + schönere Schattierung
- Neue set_render_style(style)-Methode: shaded/white/wireframe/hidden
  (textured fällt vorerst auf shaded zurück, bis die Textur-Pipeline
  steht). Voll durchverdrahtet vom TopBar-Darstellungs-Dropdown zum
  Nordstern-Viewport (setRenderStyle statt nur setWhiteMode).
- Feature-Edge-Extraktion (edges.rs): Kanten aus dem Mesh, dedupliziert
  + Crease-Erkennung (nur Silhouette/Knickkanten, keine Triangulierungs-
  Diagonalen) → sauberes Architektur-Drahtgitter. Reuse der Grid-
  LineList-Pipeline.
- wireframe = nur Kanten; hidden = flach-weisse Flächen (Depth-Bias) +
  sichtbare Kanten obenauf (klassischer Hidden-Line-Look).
- Grundschattierung: dezentes Gegenlicht (Fill-Light), damit abgewandte
  Flächen nicht mehr in Schwarz absaufen.
2026-07-04 06:05:11 +02:00
karim 85a721f03b Nordstern-3D: Boden-Referenzraster + bessere Kamera-Steuerung
- Boden-Grid-Fläche auf y = baseElevation des aktiven Geschosses,
  ein-/ausschaltbar (Overlay-Button im Viewport, State in viewSlice
  grid3dVisible). Eigene LineList-Pipeline in der Engine (grid.rs,
  GRID_WGSL, geteilte View-Projection/Depth mit der Mesh-Pipeline),
  neue set_ground_grid(visible, elevation, extent, spacing)-Methode.
  Minor-Linien dezent, jede 5. als Major betont.
- Kamera-Steuerung überarbeitet (vorher nur Mitte=Orbit, Pan auf
  Shift+Mitte versteckt): Links=Orbit, Mitte/Rechts=Pan (bewegen),
  Rad=Zoom zum Cursor. Laptop-freundlich, konsistent mit der
  2D-Plan-Navigation (dort Mitte=Pan).
2026-07-04 05:54:16 +02:00
karim fd890a0d74 Nordstern: Geo-Kontext-Meshes (Terrain/Import) rendern
Bisher zeigte nur three.js importierte Gebaeude/DXF-Meshes und das
Terrain-TIN (Project.context). Neuer MeshInput-Typ + Kontext-Mesh-Pfad
in render3d (Flat-Normalen, doppelseitig gegen unbekanntes Winding),
projectToModel3d speist project.context jetzt in beide Renderer
(nativ + WASM) ein. Nebenbei: fehlendes layers-Feld in demo_walls()
behoben, das den native3d-Feature-Build zuvor schon brach.
2026-07-04 04:38:00 +02:00
karim 7b58745855 Nordstern: Iso-Praeset auf echte orthografische Projektion korrigiert
CameraPreset::Iso war faelschlich als Perspective definiert; three.js
zeigt bei Iso bereits korrekt orthografisch (parallele Projektion, wie
bei einer echten Isometrie definiert). Front/Top/Side/Iso sind jetzt
konsistent orthografisch, nur Perspective bleibt perspektivisch.
2026-07-04 04:24:02 +02:00
karim 0c82d01cd9 Schnitt: Wandquerschnitte an den gemitterten Fussabdruck koppeln
Der Schnitt-Extraktor schnitt die Wand-Cut-Polygone bisher gegen
achsparallele Einzelwand-Rechtecke ohne Eckverschneidung — an einer
Wandecke ueberlappten dadurch zwei Querschnitte. mesh.rs exponiert jetzt
den gemitterten Fussabdruck (wall_mitered_footprints, dieselbe Gehrung wie
das 3D-Mesh) als geteilte Wahrheit; section.rs bildet die Cut-Polygone
gegen diesen Fussabdruck. Die achsparallele Naeherung fuer Verdeckung/
Projektionskanten bleibt bewusst unveraendert.
2026-07-03 23:52:33 +02:00
karim 3aee2e05ee render3d: Wandverschneidung an Ecken + sichtbare Schichten
mesh.rs berechnet die Ecken-Verschneidung jetzt selbst (portiert aus dem
Web-Kern computeJoins/clippedBand): Wandenden werden per Rundungs-Key
gruppiert, ueber Hoehen-Ueberlappung geclustert (gestapelte Geschosse mit
gleichem Grundriss verschneiden sich NICHT), und Zweier-Cluster ueber die
gemeinsame Gehrungslinie geschnitten. T-/X-Stoesse und freie Enden bleiben
stumpf, wie im Web-Kern. Endkappen-Normalen geometrisch aus dem Kreuzprodukt.

WallInput bekommt optional layers (WallLayer{thickness,color}, serde-default,
rueckwaertskompatibel): jede Schicht wird als eigenes Band ueber dieselbe
gehrte Grundflaeche extrudiert und materialgefaerbt. toWalls3d.ts loest die
WallType-Schichten je Wand auf (hexToRgb) und reicht sie durch.

39/39 Rust-Tests (7 neue: Gehrung, T-Stoss, freies Ende, Schichten, Kombi).
2026-07-03 21:45:01 +02:00
karim 17523d422c Engine-3D-Presets ueber die TopBar + orthografisch (Top/Front/Seite), Iso korrekt
Die Kamera-Presets liefen zuvor als Viewport-Overlay mit eigenen JS-yaw/pitch-
Winkeln, rein perspektivisch (Iso falsch, keine Parallelprojektion). Jetzt
haengt der Engine-Viewport am app-weiten view3d-State (TopBar-CameraMenu, wie
three.js) und nutzt die vorhandene Rust-preset_camera:

- web.rs: set_view_preset(preset) + model_bounds/fit; Front/Top/Side echt
  orthografisch, Iso/Perspektive perspektivisch - wie das native Fenster.
  default_fov() pub(crate), damit Fit denselben FOV nutzt.
- useWasm3dRenderer: applyViewPreset; render(null) ueberschreibt die
  Preset-Kamera nicht.
- Wasm3DViewport: konsumiert view3d/renderMode als Props (Overlay + lokaler
  Umschalter entfernt, wasm3dOverlay.css geloescht); Orbit bleibt frei
  (Preset = Sprung, kein Lock), three.js-Verhalten gespiegelt.
- Viewport3D-Switcher reicht view3d/renderMode an den Engine-Viewport durch
  (kein three.js-Szenencode angefasst).
2026-07-03 21:13:53 +02:00
karim b6d14ca2b2 Engine-3D: Kamera-Presets + Weiss-Modus im render3d-Viewport
Der Engine-3D-Viewport (render3d/wgpu) war reines Ansehen (Orbit/Zoom). Jetzt:

- Kamera-Presets als Overlay: Top/Unten/Vorne/Hinten/Links/Rechts/Iso.
  Richtungen exakt wie der three.js-Pfad (applyView3d); framen die aktuelle
  Modell-Bounding-Box (fitTargetDist) und springen auf den Preset-Winkel,
  danach Orbit/Pan/Zoom weiter frei. Rein JS.
- Render-Modus Schattiert/Weiss: mode-Uniform in Globals (WGSL/Rust),
  Weiss = beleuchtetes Clay-Grau; wasm-Binding set_render_mode_white,
  durchgereicht via useWasm3dRenderer.
- Overlay-CSS self-contained (wasm3dOverlay.css), Theme-aware.

three.js unangetastet. Auswahl/Grips/Zeichnen + Wireframe/HLR bewusst noch
offen (naechste Scheibe).
2026-07-03 20:56:56 +02:00
karim 96628c5aaa render3d: 4× MSAA im wgpu-Renderer — glatte 3D-Kanten
Multisampled Farbtarget (SAMPLE_COUNT=4) + resolve_target in die Surface-View je
Frame; Depth-Textur-sample_count synchron auf 4; MSAA-/Depth-Textur werden bei
Resize gemeinsam neu erzeugt; multisample.count=4 auf der Render-Pipeline. Nur
gpu.rs — mesh/section/openings unberührt.

Gates: cargo check (window) + wasm32 --features web grün, cargo test 32/32,
--features render 33/33.
2026-07-03 19:23:21 +02:00
karim 5a10ea5404 render3d: Öffnungen im 3D-Vollkörper (mesh.rs) — geteilte Zerlegung mit section.rs
- openings.rs (neu): split_range_by_voids() — die bisher nur in section.rs
  liegende Pfeiler/Brüstung/Sturz-Zerlegung, herausgezogen als koordinaten-
  neutraler Helfer. section.rs und mesh.rs teilen jetzt EIN Öffnungsmodell.
- section.rs: wall_cut_rectangles delegiert den Sortier-/Rechteck-Teil an
  openings::split_range_by_voids (plane-spezifisches Clipping bleibt lokal).
- mesh.rs: extrude_wall emittiert nicht mehr einen Vollblock je Wand, sondern
  Teilkörper (Pfeiler in voller Höhe + Brüstung/Sturz je Öffnung) → echtes Loch;
  Tür (sill==0) lässt die Brüstung weg und reicht bis zum Boden. Ohne Öffnung
  exakt EIN Block, byte-identische Geometrie zu vorher (Alt-Tests unverändert grün).

Gates: cargo test 32/32 (29+3 neue), wasm32 --features web check grün, nativ grün.
2026-07-03 18:47:40 +02:00
karim 056ca2c288 Schnitt/Ansicht: SectionOutput aus render3d an die Zeichenebenen anbinden
- render3d/web.rs: GPU-freies WASM-Binding cut_section_json(model_json, p, n)
  → JSON {cutPolygons, visibleEdges, hiddenEdges} in (u,v)-Metern.
- src/plan/toSection.ts (neu): SectionOutput-Typen, sectionPlaneFromLevel()
  leitet die Schnittebene aus linePoints/directionSign ab, computeSection()
  flacht über projectToModel3d ab und ruft das Binding.
- src/engine/engine3d.ts (neu): geteilter memoisierter pkg3d-Loader, damit
  3D-Viewport und Schnittpfad EINE mod.default()-Init teilen.
- generatePlan.ts: generateSectionPlan() übersetzt SectionOutput in
  bestehende Primitive (Cut = polygon mit Poché-Schraffur, sichtbare Kante =
  line solid, verdeckte Kante = line dashed) — keine neue Primitive-Art nötig.
- App.tsx: SectionPlanView ersetzt den Stub für Ebenen vom Typ Schnitt/Ansicht;
  rendert dasselbe PlanView, mit lokalisierten Hinweisen (lädt/keine Linie/Fehler).
- i18n de/en: section.*-Schlüssel.
- Öffnungen erscheinen korrekt (Brüstung/Sturz-Teilrechtecke) über die
  projectToModel3d-Teilkörper-Zerlegung.

Gates: tsc -b 0, build grün (WASM = eigener Lazy-Chunk), render3d cargo test 29/29,
wasm32 --features web check grün.
2026-07-03 18:37:49 +02:00
karim b4c4a2cc6b wgpu 22 → 29, glyphon 0.6 → 0.11: requestDevice-Shim entfällt
glyphon 0.11 ist die neueste zu wgpu 29 passende Version (wgpu 30 existiert
bereits, glyphon pinnt aber ^29). Das 22er-Limit maxInterStageShaderComponents
wird von 29 nicht mehr in requiredLimits gesendet — src/engine/requestDeviceShim.ts
komplett entfernt, beide Hook-Importstellen (useWasmPlanRenderer, useWasm3dRenderer)
angepasst. pollster 0.3→0.4, naga 22→29 mitgezogen. Alle Draw-/Text-Pfade
(draw_sequence, glyphon ColorMode::Web, widthScreen-Polylinien, Headless/Golden)
unverändert funktionsfähig.

Verifiziert: cargo check nativ (render2d/render3d/src-tauri) grün, cargo test
render2d 17/17 + Golden bit-exakt, render3d 29/29, wasm32 --features web für
beide grün, npx tsc -b + npm run build grün.
2026-07-03 18:17:41 +02:00
karim 76029dbf68 render3d-Schnitt: Öffnungen — Brüstung/Sturz-Teilpolygone und Durchblick
WallInput bekommt openings (from/to/sill/height, serde-default). Der Cut
durch eine Öffnung liefert mehrere einfache Rechtecke (Brüstung, Sturz,
Leibungen) statt Lochpolygon — kompatibel zu render2d::FillPolygon. Der
Verdeckungstest behandelt Öffnungen als Durchblick (u-Zuordnung exakt im
Elevationsfall, konservativ undurchsichtig bei kantennaher Ausrichtung);
Fensterrahmen-Kanten werden als projizierte Kanten ausgegeben. Tests
26 auf 29, Beweis-SVG mit Fenster + dahinterliegender Wand neu generiert
(sichtbares Band exakt im Fensterausschnitt). mesh.rs (3D-Vollkoerper)
beruecksichtigt Öffnungen weiterhin nicht — dokumentierte Luecke.
2026-07-03 08:36:35 +02:00
karim 54211b1443 render3d: Schnitt-Modul — Cut-Polygone + sichtbare/verdeckte Kanten aus Prismen
Analytische Eigen-Engine-Alternative zum OCCT-HLR-Spike: Schnittebene
(Punkt+Normale) gegen extrudierte Fussabdruck-Prismen; Cut-Polygone in
(u,v)-Schnittkoordinaten mit Komponenten-Referenz (spaetere Schraffur),
Projektion der dahinterliegenden Kanten mit Verdeckungstest, getrennt
visible/hidden. SectionOutput serde-serialisierbar (Meter). 26 Tests,
Example section_svg schreibt docs/welle-c-hlr-spike/section-engine-proof.svg
(L-Wand+Bodenplatte: Poché, durchgezogene sichtbare, gestrichelte verdeckte
Kanten). Offene Punkte in docs/design/engine-section-pipeline.md.
2026-07-03 08:13:57 +02:00
karim c8a4188618 render3d im Browser: WASM/WebGPU-3D-Viewport hinter ?engine=wasm
Feature web (wasm-bindgen) + cdylib analog render2d; WebModelRenderer
mit Canvas-Surface, set_model (walls/slabs wie der native Push) und
set_camera. Projektion liefert bereits [0,1]-Clip-Z, math.rs unveraendert.
wgpu-22-requestDevice-Shim in src/engine/requestDeviceShim.ts geteilt.
Neuer Hook useWasm3dRenderer + Wasm3DViewport (Orbit/Pan/Zoom wie three.js-
Sicht); Viewport3D dispatcht per ?engine=wasm bzw. localStorage, three.js
bleibt Default. Build-Script build:engine3d (wasm-pack, src/engine/pkg3d).
Verifiziert headful per scripts/probe-engine3d.mjs (37 % Geometrie-Pixel);
headless praesentiert Chromium keine WebGPU-Frames (auch bei render2d).
2026-07-03 07:41:37 +02:00
karim 919bc67bfa 3D: Geschossdecken als extrudierte Polygone + hemisphärisches Licht
Deckenplatten (SlabInput) werden im render3d aus dem Grundriss-Umriss per
Ear-Clipping trianguliert und über die Deckendicke extrudiert (Deckel/Boden/
Mantel mit robust nach außen orientierten Normalen). Payload erweitert auf
{ walls, slabs } — blanke Wand-Arrays bleiben kompatibel. Beleuchtung auf
hemisphärisches Ambient (Himmel/Boden) + Directional-Sonne umgestellt, dezente
Kantenbetonung, hellerer Hintergrund (#f5f5f5). Beispiel-Geschossdecke im EG.
2026-07-02 21:08:34 +02:00
karim bda256d3a4 Native wgpu-Viewports (2D+3D) im Tauri-Prozess: echtes Modell + gehrte Ecken
- native.rs: EINE winit-EventLoop hostet 2D- und 3D-Fenster (winit erlaubt nur
  eine Loop pro Prozess) — loest den RecreationAttempt-Panic zweier Loops; ersetzt
  native2d.rs/native3d.rs. Feature-gegated (native2d/native3d, einzeln oder zusammen).
- render2d/render3d laden das ECHTE Modell aus assets/native2d_scene.json bzw.
  native3d_walls.json (Demo-Szene als Fallback); initialer Ausschnitt/Kamera aus
  den Modell-Grenzen gerahmt, initialer Redraw + gesetzte Fenstergroesse.
- TS-Konverter toRenderScene/toWalls3d + scripts/dump-native-scene erzeugen die
  JSON aus sampleProject/generatePlan (npm run dump:native).
- render2d: Scene.polylines fuer zusammenhaengende Umriss-/Zeichnungslaeufe →
  Gehrung statt Stumpfkappen an Wandecken/2D-Geometrien; MITER_LIMIT 4→8
  (deckungsgleich mit SVG stroke-miterlimit:8 und WebGL2).
- native3d-Feature + render3d-Pfad-Dep in der Tauri-Crate.
2026-07-02 08:54:26 +02:00
karim 48bbcaed1e Nativer 3D-wgpu-Renderer (render3d, M0+M1): Wand-Extrusion, Kamera, Licht
Eigenstaendige Crate wie render2d (render/window-Stufung, serde-only Mesh-
schicht headless testbar). Wand-Extrusion (Band via Links-Normale, Quader mit
nach aussen zeigenden Normalen), handgerechnete Mat4 (perspektiv+ortho, wgpu-
Clip-Z [0,1], 5 Kamera-Presets), Directional-Light + Tiefenpuffer + Backface-
Culling. Orbit-Spike (cargo run --features window --bin spike3d). Plus Port-
Briefing mit M2..M9-Milestones (three.js-Viewport-Bestandsaufnahme).
2026-07-02 00:29:02 +02:00