scopedvr-map-core/editor/fly_math.gd
2026-11-01 19:31:33 +01:00

71 lines
No EOL
3 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

extends RefCounted
class_name FlyMath
## Freelook-Flug-Mathe (Karte t_c46d31c2, Karte 1/3) — bewusst pure Funktionen
## (kein Knoten, keine Kamera): speed_for/wheel_speed/move_delta/forward- und
## Euler-Umrechnung. tests/test_shortcuts.gd prüft headless; orbit_camera.gd
## ist nur der dünne Anwender.
##
## Euler-Konvention identisch zur Orbit-Kamera (_apply in orbit_camera.gd):
## Blickrichtung forward(yaw, pitch) =
## (−sin(yaw)·cos(pitch), −sin(pitch), −cos(yaw)·cos(pitch))
## pitch positiv = Kamera schaut von OBEN herab (Orbit-Pitch 5…85°),
## im Flug erlaubt: −85…+85° (auch von unten hochschauen).
const BASE_SPEED_MPS := 30.0 # Grundgeschwindigkeit (Mausrad ändert sie dauerhaft)
const FAST_MULT := 3.0 # Strg halten = schneller (Shooter-Konvention)
const SLOW_MULT := 0.3 # Alt halten = langsamer
const WHEEL_MULT := 1.15 # Mausrad-Tick: +15 % / −13 %
const SPEED_MIN_MPS := 2.0
const SPEED_MAX_MPS := 300.0
const PITCH_MAX_DEG := 85.0 # Flug-Blick grenzwertig (±) — kein Gimbal-Kippen
## Flug-Tempo: Strg dominiert, wenn (unüblicherweise) beide Modifier unten sind.
static func speed_for(base_mps: float, fast: bool, slow: bool) -> float:
if fast:
return base_mps * FAST_MULT
if slow:
return base_mps * SLOW_MULT
return base_mps
## Mausrad-Tick: Grundgeschwindigkeit DAUERHAFT ändern (nicht nur solange
## gedrückt) — up=true schneller, down=false langsamer, immer geklemmt.
static func wheel_speed(base_mps: float, up: bool) -> float:
var next := base_mps * WHEEL_MULT if up else base_mps / WHEEL_MULT
return clampf(next, SPEED_MIN_MPS, SPEED_MAX_MPS)
## Bewegungs-Delta für einen Frame. forward = BLICKRICHTUNG (3D, mit Pitch —
## W/S fliegen dorthin, wo man hinsieht), right = horizontal-rechts, und
## vertikal ist Welt-UP (Leertaste/Shift heben/senken unabhängig vom Blick —
## Shooter-Konvention, Sly-Wunsch 17.10.).
## Diagonal-Eingaben werden normalisiert (kein √2-Tempo). Rückgabe: Meter.
static func move_delta(forward: Vector3, right: Vector3, fwd_input: float,
side_input: float, vert_input: float, speed_mps: float, delta_s: float) -> Vector3:
var dir := forward * fwd_input + right * side_input + Vector3.UP * vert_input
if dir.length_squared() < 0.0000001:
return Vector3.ZERO
return dir.normalized() * speed_mps * delta_s
## Blickrichtung → (yaw_deg, pitch_deg) in der Orbit-Konvention (siehe oben).
static func euler_from_forward(forward: Vector3) -> Vector2:
var f := forward
if f.length_squared() < 0.0000001:
return Vector2(0.0, 0.0)
f = f.normalized()
var pitch := rad_to_deg(asin(clampf(-f.y, -1.0, 1.0)))
var yaw := rad_to_deg(atan2(-f.x, -f.z))
return Vector2(yaw, pitch)
## (yaw_deg, pitch_deg) → Blickrichtung (Inverse von euler_from_forward).
static func forward_from_euler(yaw_deg: float, pitch_deg: float) -> Vector3:
var yaw := deg_to_rad(yaw_deg)
var pitch := deg_to_rad(clampf(pitch_deg, -PITCH_MAX_DEG, PITCH_MAX_DEG))
return Vector3(
-sin(yaw) * cos(pitch),
-sin(pitch),
-cos(yaw) * cos(pitch))