rtbvh/
ray.rs

1use glam::*;
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7#[derive(Debug, Copy, Clone, PartialEq)]
8#[repr(align(16))]
9pub struct Ray {
10    pub origin: Vec3,
11    pub t_min: f32,
12    pub direction: Vec3,
13    pub t: f32,
14    pub(crate) inv_direction: Vec3,
15    pub(crate) signs: [u8; 4],
16}
17
18impl From<(Vec3, Vec3)> for Ray {
19    fn from(vectors: (Vec3, Vec3)) -> Self {
20        let signs = [
21            (vectors.1.x < 0.0) as u8,
22            (vectors.1.y < 0.0) as u8,
23            (vectors.1.z < 0.0) as u8,
24            0,
25        ];
26
27        Ray {
28            origin: vectors.0,
29            direction: vectors.1,
30            inv_direction: Vec3::ONE / vectors.1,
31            t_min: 1e-4,
32            t: 1e34,
33            signs,
34        }
35    }
36}
37
38impl From<Ray> for (Vec3, Vec3) {
39    fn from(r: Ray) -> Self {
40        (r.origin, r.direction)
41    }
42}
43
44#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
45#[repr(align(16))]
46#[derive(Debug, Copy, Clone)]
47pub struct RayPacket4 {
48    pub origin_x: Vec4,
49    pub origin_y: Vec4,
50    pub origin_z: Vec4,
51
52    pub direction_x: Vec4,
53    pub direction_y: Vec4,
54    pub direction_z: Vec4,
55
56    pub inv_direction_x: Vec4,
57    pub inv_direction_y: Vec4,
58    pub inv_direction_z: Vec4,
59
60    pub t: Vec4,
61}
62
63impl RayPacket4 {
64    pub fn new(origins: [Vec4; 4], directions: [Vec4; 4]) -> RayPacket4 {
65        Self {
66            origin_x: vec4(origins[0].x, origins[1].x, origins[2].x, origins[3].x),
67            origin_y: vec4(origins[0].y, origins[1].y, origins[2].y, origins[3].y),
68            origin_z: vec4(origins[0].z, origins[1].z, origins[2].z, origins[3].z),
69            direction_x: vec4(
70                directions[0].x,
71                directions[1].x,
72                directions[2].x,
73                directions[3].x,
74            ),
75            direction_y: vec4(
76                directions[0].y,
77                directions[1].y,
78                directions[2].y,
79                directions[3].y,
80            ),
81            direction_z: vec4(
82                directions[0].z,
83                directions[1].z,
84                directions[2].z,
85                directions[3].z,
86            ),
87            inv_direction_x: vec4(
88                1.0 / directions[0].x,
89                1.0 / directions[1].x,
90                1.0 / directions[2].x,
91                1.0 / directions[3].x,
92            ),
93            inv_direction_y: vec4(
94                1.0 / directions[0].y,
95                1.0 / directions[1].y,
96                1.0 / directions[2].y,
97                1.0 / directions[3].y,
98            ),
99            inv_direction_z: vec4(
100                1.0 / directions[0].z,
101                1.0 / directions[1].z,
102                1.0 / directions[2].z,
103                1.0 / directions[3].z,
104            ),
105            t: Vec4::splat(1e34),
106        }
107    }
108
109    pub fn origin_xyz(&self) -> (Vec4, Vec4, Vec4) {
110        (self.origin_x, self.origin_y, self.origin_z)
111    }
112
113    pub fn direction_xyz(&self) -> (Vec4, Vec4, Vec4) {
114        (self.direction_x, self.direction_y, self.direction_z)
115    }
116
117    #[inline]
118    pub fn ray(&self, index: usize) -> Ray {
119        debug_assert!(index <= 4);
120
121        let origin = vec3(
122            self.origin_x[index],
123            self.origin_y[index],
124            self.origin_z[index],
125        );
126
127        let direction = vec3(
128            self.direction_x[index],
129            self.direction_y[index],
130            self.direction_z[index],
131        );
132
133        let signs = [
134            (direction.x < 0.0) as u8,
135            (direction.y < 0.0) as u8,
136            (direction.z < 0.0) as u8,
137            0,
138        ];
139
140        Ray {
141            origin,
142            t_min: 1e-4,
143            direction,
144            t: self.t[index],
145            inv_direction: Vec3::ONE / direction,
146            signs,
147        }
148    }
149
150    #[inline(always)]
151    pub fn t(&self) -> Vec4 {
152        self.t
153    }
154
155    #[inline(always)]
156    pub fn reset(&mut self) {
157        self.t = Vec4::splat(Ray::DEFAULT_T_MAX);
158    }
159}
160
161#[allow(dead_code)]
162impl Ray {
163    pub const DEFAULT_T_MIN: f32 = 1e-4;
164    pub const DEFAULT_T_MAX: f32 = 1e34;
165
166    pub fn new(origin: Vec3, direction: Vec3) -> Ray {
167        let signs = [
168            (direction.x < 0.0) as u8,
169            (direction.y < 0.0) as u8,
170            (direction.z < 0.0) as u8,
171            0,
172        ];
173
174        Ray {
175            origin,
176            direction,
177            t_min: Self::DEFAULT_T_MIN,
178            t: Self::DEFAULT_T_MAX,
179            inv_direction: Vec3::ONE / direction,
180            signs,
181        }
182    }
183
184    #[inline]
185    pub fn reflect(&self, hit_point: Vec3, n: Vec3, epsilon: f32) -> Ray {
186        let tmp: Vec3 = n * n.dot(self.direction) * 2.0;
187        let direction = self.direction - tmp;
188
189        let signs = [
190            (direction.x < 0.0) as u8,
191            (direction.y < 0.0) as u8,
192            (direction.z < 0.0) as u8,
193            0,
194        ];
195
196        Ray {
197            origin: hit_point + direction * epsilon,
198            direction,
199            inv_direction: Vec3::ONE / direction,
200            t_min: Self::DEFAULT_T_MIN,
201            t: Self::DEFAULT_T_MAX,
202            signs,
203        }
204    }
205
206    #[inline(always)]
207    pub fn is_valid(&self) -> bool {
208        self.t < 1e33
209    }
210
211    #[inline(always)]
212    pub fn get_point_at(&self, t: f32) -> Vec3 {
213        self.origin + t * self.direction
214    }
215
216    #[inline(always)]
217    pub(crate) fn sign_x(&self) -> usize {
218        self.signs[0] as usize
219    }
220
221    #[inline(always)]
222    pub(crate) fn sign_y(&self) -> usize {
223        self.signs[1] as usize
224    }
225
226    #[inline(always)]
227    pub(crate) fn sign_z(&self) -> usize {
228        self.signs[2] as usize
229    }
230
231    #[inline(always)]
232    pub fn reset(&mut self) {
233        self.t = Self::DEFAULT_T_MAX;
234    }
235}