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}