use glam::Vec3;
#[derive(Clone, Copy, Debug)]
pub struct Ray {
pub origin: Vec3,
pub dir: Vec3,
}
#[derive(Clone, Copy, Debug)]
pub struct HitRecord {
pub t: f32,
pub normal: Vec3,
pub facet_idx: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum FacetFinish {
#[default]
Polished,
Frosted,
}
pub struct Camera {
pub origin: Vec3,
pub forward: Vec3,
pub right: Vec3,
pub up: Vec3,
pub fov_tan: f32,
}
impl Camera {
#[must_use]
pub fn new(yaw: f32, pitch: f32, distance: f32, fov_deg: f32) -> Self {
let cos_p = pitch.cos();
let sin_p = pitch.sin();
let cos_y = yaw.cos();
let sin_y = yaw.sin();
let origin = Vec3::new(
distance * cos_p * sin_y,
distance * sin_p,
distance * cos_p * cos_y,
);
let forward = (-origin).normalize();
let world_up = if cos_p.abs() < 1e-4 {
Vec3::new(0.0, 0.0, -1.0)
} else {
Vec3::Y
};
let right = forward.cross(world_up).normalize();
let up = right.cross(forward).normalize();
let fov_tan = (fov_deg.to_radians() * 0.5).tan();
Self {
origin,
forward,
right,
up,
fov_tan,
}
}
#[must_use]
pub fn generate_ray(
&self,
screen_x: f32,
screen_y: f32,
width: f32,
height: f32,
jitter_x: f32,
jitter_y: f32,
) -> Ray {
let aspect = width / height;
let u = ((screen_x + jitter_x) / width - 0.5) * 2.0 * aspect * self.fov_tan;
let v = (0.5 - (screen_y + jitter_y) / height) * 2.0 * self.fov_tan;
let dir = (self.forward + self.right * u + self.up * v).normalize();
Ray {
origin: self.origin,
dir,
}
}
}