1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use std::marker::PhantomData;
use cgmath::{BaseFloat, BaseNum, InnerSpace};
use cgmath::{EuclideanSpace, Point2, Point3};
use cgmath::{VectorSpace, Vector2, Vector3};
use intersect::{Continuous, Discrete};
#[derive(Copy, Clone, PartialEq)]
#[cfg_attr(feature = "eders", derive(Serialize, Deserialize))]
pub struct Ray<S, P, V> {
pub origin: P,
pub direction: V,
phantom_s: PhantomData<S>,
}
impl<S, V, P> Ray<S, P, V>
where
S: BaseNum,
V: VectorSpace<Scalar = S>,
P: EuclideanSpace<Scalar = S, Diff = V>,
{
pub fn new(origin: P, direction: V) -> Ray<S, P, V> {
Ray {
origin: origin,
direction: direction,
phantom_s: PhantomData,
}
}
}
pub type Ray2<S> = Ray<S, Point2<S>, Vector2<S>>;
pub type Ray3<S> = Ray<S, Point3<S>, Vector3<S>>;
impl<S, P> Continuous<Ray<S, P, P::Diff>, P> for P
where
S: BaseFloat,
P: EuclideanSpace<Scalar = S>,
P::Diff: InnerSpace<Scalar = S>,
{
fn intersection(&self, ray: &Ray<S, P, P::Diff>) -> Option<P> {
if self.intersects(ray) {
Some(self.clone())
} else {
None
}
}
}
impl<S, P> Discrete<Ray<S, P, P::Diff>> for P
where
S: BaseFloat,
P: EuclideanSpace<Scalar = S>,
P::Diff: InnerSpace<Scalar = S>,
{
fn intersects(&self, ray: &Ray<S, P, P::Diff>) -> bool {
let p = self.clone();
let l = p - ray.origin;
let tca = l.dot(ray.direction);
tca > S::zero() &&
(tca * tca).relative_eq(
&l.magnitude2(),
S::default_epsilon(),
S::default_max_relative(),
)
}
}