bs_trace/linalg/
ray.rs

1use super::prelude::*;
2use num_traits::{Float, One};
3use std::iter::Sum;
4use std::ops::{Add, Mul};
5
6/// A ray with an origin and a direction. The direction is normalised.
7pub struct Ray<T, const N: usize> {
8    pub origin: Vector<T, N>,
9    pub direction: Vector<T, N>,
10}
11
12impl<T, const N: usize> Ray<T, N> {
13    /// Constructs a ray from an origin and direction. The given direction is normalised by the callee.
14    pub fn new(origin: Vector<T, N>, direction: Vector<T, N>) -> Self
15    where
16        T: Mul<T, Output = T> + Clone + Sum + One + Float,
17    {
18        let direction_normalised = direction.normalised();
19        unsafe { Self::new_unchecked(origin, direction_normalised) }
20    }
21
22    /// Constructs a ray from an origin and direction.
23    ///
24    /// # Safety
25    ///
26    /// The caller must ensure that the direction vector is normalised.
27    pub unsafe fn new_unchecked(origin: Vector<T, N>, direction: Vector<T, N>) -> Self {
28        Self { origin, direction }
29    }
30
31    /// Evaluates this ray at t.
32    ///
33    /// In the case of non-negative t, `ray.at(t)` is the point that is t units away from the ray's
34    /// origin, in the ray's direction.
35    ///
36    /// In the case of negative t, `ray.at(t)` is the point that is -t units away from the ray's
37    /// origin, in the opposite direction to the ray's direction.
38    pub fn at(&self, t: T) -> Vector<T, N>
39    where
40        T: Add<T, Output = T> + Mul<T, Output = T> + Clone,
41    {
42        let ds = self.direction.clone() * t;
43        self.origin.clone() + ds
44    }
45}