use nalgebra::{Point3, Rotation3, Unit, Vector3};
#[derive(Clone)]
pub struct Ray {
pub pos: Point3<f64>,
pub dir: Unit<Vector3<f64>>,
}
impl Ray {
#[inline]
#[must_use]
pub fn new(pos: Point3<f64>, mut dir: Unit<Vector3<f64>>) -> Self {
dir.renormalize();
Self { pos, dir }
}
#[inline]
#[must_use]
pub const fn destruct(self) -> (Point3<f64>, Unit<Vector3<f64>>) {
(self.pos, self.dir)
}
#[inline]
pub fn travel(&mut self, dist: f64) {
debug_assert!(dist > 0.0);
self.pos += self.dir.as_ref() * dist;
}
#[inline]
pub fn rotate(&mut self, pitch: f64, roll: f64) {
let arbitrary_axis = if (1.0 - self.dir.z.abs()) >= 1.0e-1 {
Vector3::z_axis()
} else {
Vector3::y_axis()
};
let pitch_axis = Unit::new_normalize(self.dir.cross(&arbitrary_axis));
let pitch_rot = Rotation3::from_axis_angle(&pitch_axis, pitch);
let roll_rot = Rotation3::from_axis_angle(&self.dir, roll);
self.dir = roll_rot * pitch_rot * self.dir;
self.dir.renormalize();
}
}