use cgmath::{Matrix4, Point3, Vector3, Deg, perspective, InnerSpace, Rotation, Quaternion, Rotation3, Rad}; #[derive(Debug)] pub struct Camera { pub eye: Point3, pub target: Point3, pub up: Vector3, pub fov_y: Deg, pub aspect: f32, pub znear: f32, pub zfar: f32, } impl Camera { pub fn new(aspect: f32) -> Self { Self { eye: Point3::new(0.0, 0.0, 5.0), target: Point3::new(0.0, 0.0, 0.0), up: Vector3::unit_y(), fov_y: Deg(45.0), aspect, znear: 0.1, zfar: 100.0, } } pub fn build_view_projection_matrix(&self) -> Matrix4 { let view = Matrix4::look_at_rh(self.eye, self.target, self.up); let proj = perspective(self.fov_y, self.aspect, self.znear, self.zfar); proj * view } pub fn rotate_yaw_pitch(&mut self, yaw: f32, pitch: f32) { let dir = (self.target - self.eye).normalize(); let horizontal = Vector3::unit_y().cross(dir).normalize(); let vertical = horizontal.cross(dir).normalize(); let pitch_q = Quaternion::from_axis_angle(vertical, Rad(pitch.to_radians())); let yaw_q = Quaternion::from_axis_angle(Vector3::unit_y(), Rad(yaw.to_radians())); let rotation = yaw_q * pitch_q; let rotated = rotation.rotate_vector(dir).normalize(); let distance = (self.target - self.eye).magnitude(); self.eye = self.target - rotated * distance; } pub fn zoom(&mut self, amount: f32) { let dir = (self.target - self.eye).normalize(); self.eye += dir * amount; } pub fn set_aspect(&mut self, aspect: f32) { self.aspect = aspect; } }