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}