Akkumulierten grünen Arbeitsstand landen (Basis für Weiterarbeit)

Bündelt den über mehrere Sessions gewachsenen, uncommitteten Stand in
einem Basis-Commit, damit Folge-Features isoliert darauf aufsetzen.
Verifikation: tsc --noEmit sauber, vitest 600/600 grün.

Enthalten (Details in PENDENZEN.md -Liste / HANDOVER.md):
- truck-Integration: Profil-Extrusion + Verjüngung + Boolean-CSG (csgrs),
  Crate src-tauri/trucksolid, Werkzeug `extrude`, ExtrudedSolid-Modell.
- kernel2d-Port nach Rust/WASM (Phasen 1–5, Diff-Harness).
- render3d 3D-Live-Schnitt = 2D-Schnitt: geschichteter Bodenaufbau,
  Prioritäts-Verschneidung (section_boolean.rs), einstellbare
  Schichttrennlinien, per-Hatch-Strichstärke, relativeToWall-Orientierung.
- Interop-Export IFC4/STL/OBJ (Loch-Ausschnitt wallMeshCut), Schnellexport.
- Projektdatei .obp + OS-Lock (lock.rs, LockConflictDialog).
- Layout-Blätter (Modell/Editor/Panel/PDF), Ausschnitte, Override-Engine,
  Tragwerk-Stützen (Column), BIM-Tree-Panel.
- Bauteil-Typsystem (Tür/Fenster/Treppe-Typen), Betontreppe mit schräger
  Laufplatte, Text-/Textbox-Werkzeug, Mess-Werkzeug, 2D/3D-Griffe für
  Öffnungen/Treppen, Snap-Symbol-Restyle.
This commit is contained in:
2026-07-09 00:57:29 +02:00
parent 889cbb2c12
commit 35299307d6
131 changed files with 26501 additions and 852 deletions
+53 -11
View File
@@ -185,15 +185,26 @@ pub fn orbit_eye(target: [f32; 3], yaw: f32, pitch: f32, dist: f32) -> [f32; 3]
]
}
/// Baut eine `Camera` fuer eines der fuenf Presets der three.js-Sicht. `target`
/// ist das Blickziel (Modell-Mitte), `dist` der Abstand. Front/Top/Side/Iso
/// sind orthografisch (Front/Top/Side achsparallel, Iso diagonal); nur Persp
/// ist perspektivisch.
/// Baut eine `Camera` fuer eines der Kardinal-/Iso-Presets (ROADMAP §11).
/// `target` ist das Blickziel (Modell-Mitte), `dist` der Abstand. Alle Presets
/// ausser `Persp` sind orthografisch (Front/Back/Top/Side/Left achsparallel,
/// die Iso-Varianten diagonal); nur Persp ist perspektivisch.
///
/// Achs-Konvention (wie die three.js-Sicht, s. `applyView3d` in Viewport3D.tsx):
/// +Z = vorne (Front blickt von +Z entlang -Z), +X = rechts (Side blickt von
/// +X entlang -X). Back/Left sind exakt die Gegenrichtungen (-Z/-X); es gibt
/// noch KEINEN Nordwinkel — die Kardinalrichtungen sind rein modellrelativ
/// (Vorne/Rechts/Hinten/Links im UI, keine Himmelsrichtungen).
pub fn preset_camera(preset: CameraPreset, target: [f32; 3], dist: f32) -> Camera {
let mut cam = Camera {
target,
..Camera::default()
};
// Iso-Distanz-Helfer: Augenabstand-Komponente je Achse, sodass der
// tatsaechliche eye-target-Abstand exakt `dist` bleibt (d*sqrt(3) == dist,
// wie bei den bisherigen Front/Top/Side-Presets), damit alle Iso-Varianten
// das Modell gleich gross zeigen.
let iso_d = dist / 3.0_f32.sqrt();
match preset {
// Blick entlang -Z (von vorne), orthografisch.
CameraPreset::Front => {
@@ -202,6 +213,13 @@ pub fn preset_camera(preset: CameraPreset, target: [f32; 3], dist: f32) -> Camer
cam.up = [0.0, 1.0, 0.0];
cam.ortho_half_height = dist * 0.5;
}
// Blick entlang +Z (von hinten) — Gegenrichtung von Front.
CameraPreset::Back => {
cam.projection = Projection::Orthographic;
cam.eye = [target[0], target[1], target[2] - dist];
cam.up = [0.0, 1.0, 0.0];
cam.ortho_half_height = dist * 0.5;
}
// Blick von oben entlang -Y (Grundriss), orthografisch. Up = -Z, damit
// Modell-Y (world +Z) im Bild nach unten zeigt (wie die 2D-Plan-Sicht).
CameraPreset::Top => {
@@ -210,24 +228,48 @@ pub fn preset_camera(preset: CameraPreset, target: [f32; 3], dist: f32) -> Camer
cam.up = [0.0, 0.0, -1.0];
cam.ortho_half_height = dist * 0.5;
}
// Blick entlang -X (von der Seite), orthografisch.
// Blick entlang -X (von der rechten Seite), orthografisch.
CameraPreset::Side => {
cam.projection = Projection::Orthographic;
cam.eye = [target[0] + dist, target[1], target[2]];
cam.up = [0.0, 1.0, 0.0];
cam.ortho_half_height = dist * 0.5;
}
// Isometrischer Ueberblick (orthografisch, Blick von schraeg oben).
// Blick entlang +X (von der linken Seite) — Gegenrichtung von Side.
CameraPreset::Left => {
cam.projection = Projection::Orthographic;
cam.eye = [target[0] - dist, target[1], target[2]];
cam.up = [0.0, 1.0, 0.0];
cam.ortho_half_height = dist * 0.5;
}
// Isometrischer Ueberblick von vorne-oben-rechts (Default-Iso).
// Echte Isometrie ist per Definition parallelprojiziert (keine
// perspektivische Verzerrung, Kantenlaengen bleiben massstabsgetreu).
CameraPreset::Iso => {
cam.projection = Projection::Orthographic;
let d = dist / 3.0_f32.sqrt();
cam.eye = [target[0] + d, target[1] + d, target[2] + d];
cam.eye = [target[0] + iso_d, target[1] + iso_d, target[2] + iso_d];
cam.up = [0.0, 1.0, 0.0];
cam.ortho_half_height = dist * 0.5;
}
// Isometrischer Ueberblick von vorne-oben-links.
CameraPreset::IsoFrontLeft => {
cam.projection = Projection::Orthographic;
cam.eye = [target[0] - iso_d, target[1] + iso_d, target[2] + iso_d];
cam.up = [0.0, 1.0, 0.0];
cam.ortho_half_height = dist * 0.5;
}
// Isometrischer Ueberblick von hinten-oben-rechts.
CameraPreset::IsoBackRight => {
cam.projection = Projection::Orthographic;
cam.eye = [target[0] + iso_d, target[1] + iso_d, target[2] - iso_d];
cam.up = [0.0, 1.0, 0.0];
cam.ortho_half_height = dist * 0.5;
}
// Isometrischer Ueberblick von hinten-oben-links.
CameraPreset::IsoBackLeft => {
cam.projection = Projection::Orthographic;
cam.eye = [target[0] - iso_d, target[1] + iso_d, target[2] - iso_d];
cam.up = [0.0, 1.0, 0.0];
// eye-target-Abstand ist hier (wie bei Front/Top/Side) exakt
// `dist` (d*sqrt(3) == dist), darum dieselbe Skalierung wie dort,
// damit das Modell im Bild aehnlich gross erscheint.
cam.ortho_half_height = dist * 0.5;
}
// Freie perspektivische Standard-Ansicht (leicht von vorn-oben-rechts).