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).
This commit is contained in:
2026-07-04 15:08:41 +02:00
parent 6c2e9a4282
commit 7775648861
8 changed files with 499 additions and 17 deletions
+47
View File
@@ -53,6 +53,20 @@ interface WebModelRendererLike {
extent_m: number,
spacing_m: number,
): void;
/** Live-Schnitt ein-/ausschalten (Rust-seitig, `web::set_section_plane`).
* `active=false` hebt den Schnitt auf. `p*` = Punkt auf der Ebene, `n*` =
* Ebenennormale = Blickrichtung (world-Meter, Y-up; nur vertikale Ebenen).
* Kappt das Modell per Shader-`discard` und fuellt die Schnittflaeche mit der
* Diagonalschraffur (Caps). Wirkt erst beim naechsten `render`. */
set_section_plane(
active: boolean,
px: number,
py: number,
pz: number,
nx: number,
ny: number,
nz: number,
): void;
/**
* Auswahl-Hervorhebung setzen: ein LineList-Vertex-Array (interleaved
* `[px,py,pz, r,g,b, ...]`, world-Meter, je 2 Vertices = 1 Linie), das die
@@ -187,6 +201,38 @@ export function useWasm3dRenderer(
[],
);
/**
* Live-Schnitt setzen/aufheben (Overlay-Umschalter im Viewport, s.
* Wasm3DViewport.tsx). `active=false` zeigt das Modell wieder komplett.
* `point` = Punkt auf der Schnittebene, `normal` = Ebenennormale =
* Blickrichtung (world-Meter, Y-up; nur vertikale Ebenen sinnvoll). Wirkt
* erst beim nächsten `render`.
*/
const setSectionPlane = useCallback(
(
active: boolean,
point: [number, number, number],
normal: [number, number, number],
) => {
const r = rendererRef.current;
if (!r) return;
try {
r.set_section_plane(
active,
point[0],
point[1],
point[2],
normal[0],
normal[1],
normal[2],
);
} catch (e) {
console.warn("render3d set_section_plane fehlgeschlagen:", e);
}
},
[],
);
/**
* Auswahl-Hervorhebung setzen (Umriss-Linien des gewählten Bauteils, immer
* obenauf) — reicht das fertige LineList-Vertex-Array 1:1 an
@@ -274,6 +320,7 @@ export function useWasm3dRenderer(
setRenderStyle,
applyViewPreset,
setGroundGrid,
setSectionPlane,
setHighlightLines,
ready,
failed,