refactor
This commit is contained in:
+28
-8
@@ -1,10 +1,8 @@
|
||||
//! Minimale f32-Matrix-Mathematik für den Renderer — bewusst handgerollt
|
||||
//! statt glam: PS1-Style braucht nur Multiply, View und Perspective.
|
||||
//! (Die Spiellogik bekommt später ihr eigenes Q16.16 wie irl3d; das hier
|
||||
//! ist nur der GPU-Pfad.)
|
||||
//! statt glam: nötig sind nur Multiply, View und Perspective.
|
||||
//!
|
||||
//! Konventionen:
|
||||
//! - rechtshändig, Kamera blickt -Z, +Y oben (wie Blender-OBJ-Export)
|
||||
//! - rechtshändig, Kamera blickt -Z, +Y oben (wie der Blender-Export)
|
||||
//! - Spaltenvektoren, Speicher column-major — `Mat4.0[spalte][zeile]`,
|
||||
//! bytemuck-kompatibel zu WGSL `mat4x4f`
|
||||
//! - Clip-Z in [0,1] (wgpu/WebGPU, nicht GL-[-1,1])
|
||||
@@ -67,8 +65,7 @@ impl Mat4 {
|
||||
}
|
||||
|
||||
/// FPS-View: erst Kamera-Position abziehen, dann Yaw, dann Pitch
|
||||
/// herausdrehen. Yaw/Pitch wie die irl3d-Kamera: yaw=0 blickt -Z,
|
||||
/// positiver Pitch hebt den Blick.
|
||||
/// herausdrehen. yaw=0 blickt -Z, positiver Pitch hebt den Blick.
|
||||
pub fn view(pos: [f32; 3], yaw: f32, pitch: f32) -> Mat4 {
|
||||
Mat4::rot_x(-pitch)
|
||||
.mul(&Mat4::rot_y(-yaw))
|
||||
@@ -104,8 +101,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn view_yaw_quarter_turn_looks_minus_x() {
|
||||
// yaw=90°: Blick Richtung -X (irl3d-Konvention) — ein Punkt auf
|
||||
// -X liegt dann vor der Kamera.
|
||||
// yaw=90°: Blick Richtung -X — ein Punkt auf -X liegt vor der Kamera.
|
||||
let v = Mat4::view([0.0, 0.0, 0.0], std::f32::consts::FRAC_PI_2, 0.0);
|
||||
assert!(close(v.transform([-2.0, 0.0, 0.0, 1.0]), [0.0, 0.0, -2.0, 1.0]));
|
||||
}
|
||||
@@ -116,6 +112,30 @@ mod tests {
|
||||
assert!(close(v.transform([0.0, 3.0, 0.0, 1.0]), [0.0, 0.0, -3.0, 1.0]));
|
||||
}
|
||||
|
||||
/// Die Bewegungs-Basis des Players muss exakt zu der Richtung passen, die
|
||||
/// `view` als „vor der Kamera" definiert — sonst driften Steuerung und Bild
|
||||
/// auseinander. Ein Punkt `d` voraus muss im View-Space auf (0, 0, -d)
|
||||
/// landen, `right_dir` auf +X und ohne Y-Anteil.
|
||||
#[test]
|
||||
fn view_matches_player_basis() {
|
||||
use crate::engine::player::Player;
|
||||
for &(yaw, pitch) in &[(0.0, 0.0), (0.7, 0.0), (0.0, 0.5), (1.2, -0.4)] {
|
||||
let mut p = Player::new([1.0, 2.0, 3.0]);
|
||||
(p.yaw, p.pitch) = (yaw, pitch);
|
||||
let v = Mat4::view(p.pos, p.yaw, p.pitch);
|
||||
|
||||
let f = p.look_dir();
|
||||
let ahead = [p.pos[0] + f[0] * 5.0, p.pos[1] + f[1] * 5.0, p.pos[2] + f[2] * 5.0, 1.0];
|
||||
assert!(close(v.transform(ahead), [0.0, 0.0, -5.0, 1.0]),
|
||||
"look_dir bei yaw={yaw} pitch={pitch}: {:?}", v.transform(ahead));
|
||||
|
||||
let r = p.right_dir();
|
||||
assert!(r[1].abs() < 1e-6, "right_dir darf kein Y haben: {r:?}");
|
||||
let side = v.transform([p.pos[0] + r[0] * 5.0, p.pos[1], p.pos[2] + r[2] * 5.0, 1.0]);
|
||||
assert!(side[0] > 4.0, "right_dir sollte nach View-+X zeigen: {side:?}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn perspective_maps_near_far_to_0_1() {
|
||||
let p = Mat4::perspective(1.0, 4.0 / 3.0, 0.1, 100.0);
|
||||
|
||||
Reference in New Issue
Block a user