use std::{f32::consts::FRAC_PI_2, time::Duration};
use glam::Vec3;
use crate::Context;
#[must_use]
#[derive(Debug)]
pub struct CameraController {
pub pitch: f32,
pub yaw: f32,
pub sensitivity: f32,
}
impl Default for CameraController {
fn default() -> Self {
Self {
pitch: 0.0,
yaw: 0.0,
sensitivity: 0.1,
}
}
}
impl CameraController {
pub fn with_pitch(mut self, pitch: f32) -> Self {
self.pitch = pitch;
self
}
pub fn with_yaw(mut self, yaw: f32) -> Self {
self.yaw = yaw;
self
}
pub fn with_sensitivity(mut self, sensitivity: f32) -> Self {
self.sensitivity = sensitivity;
self
}
pub fn on_update<M>(&mut self, ctx: &Context<M>, delta: Duration) {
let delta = delta.as_secs_f32();
let md = ctx.mouse_delta();
self.yaw += md.x * self.sensitivity * delta;
self.pitch -= md.y * self.sensitivity * delta;
self.pitch = self.pitch.clamp(-FRAC_PI_2 + 0.01, FRAC_PI_2 - 0.01);
}
#[must_use]
pub fn transform_dir(&self, dir: Vec3) -> Vec3 {
let (yaw_sin, yaw_cos) = self.yaw.sin_cos();
let forward = Vec3::new(yaw_cos, 0.0, yaw_sin);
let right = forward.cross(Vec3::Y);
(forward * dir.z + right * dir.x).normalize_or_zero()
}
}