use crate::math::Ray;
use glam::Vec3;
pub struct Camera {
pub position: Vec3,
pub yaw: f32, pub pitch: f32, pub fov_y: f32, }
impl Camera {
pub fn new(position: Vec3, fov_y_deg: f32) -> Self {
Self {
position,
yaw: 0.0,
pitch: 0.0,
fov_y: fov_y_deg.to_radians(),
}
}
pub fn forward(&self) -> Vec3 {
let cp = self.pitch.cos();
Vec3::new(
self.yaw.sin() * cp,
self.pitch.sin(),
-self.yaw.cos() * cp,
)
.normalize()
}
pub fn right(&self) -> Vec3 {
Vec3::new(self.yaw.cos(), 0.0, self.yaw.sin()).normalize()
}
pub fn up(&self) -> Vec3 {
self.right().cross(self.forward()).normalize()
}
pub fn ray(&self, x: u16, y: u16, w: u16, h: u16, jitter: glam::Vec2) -> Ray {
let aspect = w as f32 / h.max(1) as f32;
let pixel_aspect = 1.0; let half_h = (self.fov_y * 0.5).tan();
let half_w = half_h * aspect * pixel_aspect;
let u = ((x as f32 + jitter.x) / w as f32) * 2.0 - 1.0;
let v = 1.0 - ((y as f32 + jitter.y) / h as f32) * 2.0;
let dir = self.forward() + self.right() * (u * half_w) + self.up() * (v * half_h);
Ray::new(self.position, dir)
}
pub fn translate_local(&mut self, delta: Vec3) {
let f = self.forward();
let r = self.right();
let u = Vec3::Y;
self.position += r * delta.x + u * delta.y + f * delta.z;
}
pub fn rotate(&mut self, dyaw: f32, dpitch: f32) {
self.yaw += dyaw;
self.pitch = (self.pitch + dpitch).clamp(-1.5, 1.5);
}
}