1use crate::*;
2
3pub trait RayIterator<'a, 'b, T: 'a + Primitive>: Iterator<Item = (&'a T, &'b mut Ray)> {}
4pub trait PacketIterator<'a, 'b, T: 'a + Primitive>:
5 Iterator<Item = (&'a T, &'b mut RayPacket4)>
6{
7}
8
9pub trait IntoRayIterator<'a, 'b, T: 'a + Primitive> {
10 type RIterator: RayIterator<'a, 'b, T>;
11
12 fn iter(&'a self, ray: &'b mut Ray, primitives: &'a [T]) -> Self::RIterator;
13}
14
15pub trait IntoPacketIterator<'a, 'b, T: 'a + Primitive> {
16 type RIterator: PacketIterator<'a, 'b, T>;
17
18 fn iter(&'a self, packet: &'b mut RayPacket4, primitives: &'a [T]) -> Self::RIterator;
19}
20
21#[derive(Debug)]
22pub struct BvhIterator<'a, 'b, T: 'a + Primitive> {
23 ray: &'b mut Ray,
24 i: i32,
25 stack: [i32; 32],
26 stack_ptr: i32,
27 nodes: &'a [BvhNode],
28 indices: &'a [u32],
29 primitives: &'a [T],
30}
31
32impl<'a, 'b, T: 'a + Primitive> RayIterator<'a, 'b, T> for BvhIterator<'a, 'b, T> {}
33
34impl<'a, 'b, T: 'a + Primitive> BvhIterator<'a, 'b, T> {
35 pub fn new(ray: &'b mut Ray, bvh: &'a Bvh, primitives: &'a [T]) -> Self {
36 let stack_ptr = if bvh.nodes.is_empty()
37 || ray.origin.is_nan()
38 || ray.direction.is_nan()
39 || primitives.is_empty()
40 {
41 -1
42 } else {
43 0
44 };
45
46 Self {
47 ray,
48 i: 0,
49 stack: [0; 32],
50 stack_ptr,
51 nodes: bvh.nodes(),
52 indices: bvh.indices(),
53 primitives,
54 }
55 }
56
57 pub fn from_slices(
58 ray: &'b mut Ray,
59 nodes: &'a [BvhNode],
60 indices: &'a [u32],
61 primitives: &'a [T],
62 ) -> Self {
63 let stack_ptr = if nodes.is_empty()
64 || ray.origin.is_nan()
65 || ray.direction.is_nan()
66 || primitives.is_empty()
67 {
68 -1
69 } else {
70 0
71 };
72
73 Self {
74 ray,
75 i: 0,
76 stack: [0; 32],
77 stack_ptr,
78 nodes,
79 indices,
80 primitives,
81 }
82 }
83}
84
85impl<'a, 'b, T: 'a + Primitive> Iterator for BvhIterator<'a, 'b, T> {
86 type Item = (&'a T, &'b mut Ray);
87
88 fn next(&mut self) -> Option<Self::Item> {
89 loop {
90 if self.stack_ptr < 0 {
91 return None;
92 }
93
94 let node = unsafe {
95 self.nodes
96 .get_unchecked(*self.stack.get_unchecked(self.stack_ptr as usize) as usize)
97 };
98 self.stack_ptr -= 1;
99
100 let count = node.get_count_unchecked();
101 let left_first = node.get_left_first_unchecked();
102
103 if count > -1 {
104 if self.i < count {
105 let prim_id =
106 unsafe { *self.indices.get_unchecked((left_first + self.i) as usize) };
107 self.i += 1;
108 self.stack_ptr += 1;
109 if let Some(prim) = self.primitives.get(prim_id as usize) {
110 return Some((prim, unsafe {
111 std::mem::transmute::<&mut Ray, &'b mut Ray>(self.ray)
112 }));
113 }
114 }
115 self.i = 0;
116 } else if left_first > -1 {
117 self.stack_ptr = BvhNode::sort_nodes(
118 unsafe { self.nodes.get_unchecked(left_first as usize) }.intersect(&self.ray),
119 unsafe { self.nodes.get_unchecked((left_first + 1) as usize) }
120 .intersect(&self.ray),
121 &mut self.stack,
122 self.stack_ptr,
123 left_first,
124 );
125 }
126 }
127 }
128}
129
130#[derive(Debug)]
131pub struct BvhPacketIterator<'a, 'b, T: 'a + Primitive> {
132 ray: &'b mut RayPacket4,
133 i: i32,
134 stack: [i32; 32],
135 stack_ptr: i32,
136 nodes: &'a [BvhNode],
137 indices: &'a [u32],
138 primitives: &'a [T],
139}
140
141impl<'a, 'b, T: 'a + Primitive> PacketIterator<'a, 'b, T> for BvhPacketIterator<'a, 'b, T> {}
142
143impl<'a, 'b, T: 'a + Primitive> BvhPacketIterator<'a, 'b, T> {
144 pub fn new(ray: &'b mut RayPacket4, bvh: &'a Bvh, primitives: &'a [T]) -> Self {
145 let stack_ptr = if bvh.nodes.is_empty()
146 || ray.origin_x.is_nan()
147 || ray.origin_y.is_nan()
148 || ray.origin_z.is_nan()
149 || ray.direction_x.is_nan()
150 || ray.direction_y.is_nan()
151 || ray.direction_z.is_nan()
152 || primitives.is_empty()
153 {
154 -1
155 } else {
156 0
157 };
158 Self {
159 ray,
160 i: 0,
161 stack: [0; 32],
162 stack_ptr,
163 nodes: bvh.nodes(),
164 indices: bvh.indices(),
165 primitives,
166 }
167 }
168
169 pub fn from_slices(
170 ray: &'b mut RayPacket4,
171 nodes: &'a [BvhNode],
172 indices: &'a [u32],
173 primitives: &'a [T],
174 ) -> Self {
175 let stack_ptr = if nodes.is_empty()
176 || ray.origin_x.is_nan()
177 || ray.origin_y.is_nan()
178 || ray.origin_z.is_nan()
179 || ray.direction_x.is_nan()
180 || ray.direction_y.is_nan()
181 || ray.direction_z.is_nan()
182 || primitives.is_empty()
183 {
184 -1
185 } else {
186 0
187 };
188 Self {
189 ray,
190 i: 0,
191 stack: [0; 32],
192 stack_ptr,
193 nodes,
194 indices,
195 primitives,
196 }
197 }
198}
199
200impl<'a, 'b, T: 'a + Primitive> Iterator for BvhPacketIterator<'a, 'b, T> {
201 type Item = (&'a T, &'b mut RayPacket4);
202
203 fn next(&mut self) -> Option<Self::Item> {
204 loop {
205 if self.stack_ptr < 0 {
206 return None;
207 }
208
209 let node = unsafe {
210 self.nodes
211 .get_unchecked(*self.stack.get_unchecked(self.stack_ptr as usize) as usize)
212 };
213 self.stack_ptr -= 1;
214
215 let count = node.get_count_unchecked();
216 let left_first = node.get_left_first_unchecked();
217
218 if count > -1 {
219 if self.i < count {
220 let prim_id =
221 unsafe { *self.indices.get_unchecked((left_first + self.i) as usize) };
222 self.i += 1;
223 self.stack_ptr += 1;
224 if let Some(prim) = self.primitives.get(prim_id as usize) {
225 return Some((prim, unsafe {
226 std::mem::transmute::<&mut RayPacket4, &'b mut RayPacket4>(self.ray)
227 }));
228 }
229 }
230 self.i = 0;
231 } else if left_first > -1 {
232 self.stack_ptr = BvhNode::sort_nodes4(
233 unsafe { self.nodes.get_unchecked(left_first as usize) }.intersect4(self.ray),
234 unsafe { self.nodes.get_unchecked((left_first + 1) as usize) }
235 .intersect4(self.ray),
236 &mut self.stack,
237 self.stack_ptr,
238 left_first,
239 );
240 }
241 }
242 }
243}
244
245#[derive(Debug)]
246pub struct MbvhIterator<'a, 'b, T: 'a + Primitive> {
247 ray: &'b mut Ray,
248 hit: MbvhHit,
249 current: i32,
250 i: i32,
251 j: i32,
252 stack: [i32; 32],
253 stack_ptr: i32,
254 indices: &'a [u32],
255 nodes: &'a [MbvhNode],
256 primitives: &'a [T],
257}
258
259impl<'a, 'b, T: 'a + Primitive> RayIterator<'a, 'b, T> for MbvhIterator<'a, 'b, T> {}
260
261impl<'a, 'b, T: Primitive> MbvhIterator<'a, 'b, T> {
262 pub fn new(ray: &'b mut Ray, bvh: &'a Mbvh, primitives: &'a [T]) -> Self {
263 let hit = bvh
264 .m_nodes
265 .get(0)
266 .map(|n| n.intersect(&ray))
267 .unwrap_or_default();
268 Self {
269 ray,
270 hit,
271 current: 0,
272 i: 0,
273 j: 0,
274 stack: [0; 32],
275 stack_ptr: -1,
276 indices: &bvh.prim_indices,
277 nodes: &bvh.m_nodes,
278 primitives,
279 }
280 }
281
282 pub fn from_slices(
283 ray: &'b mut Ray,
284 nodes: &'a [MbvhNode],
285 indices: &'a [u32],
286 primitives: &'a [T],
287 ) -> Self {
288 let hit = nodes.get(0).map(|n| n.intersect(&ray)).unwrap_or_default();
289
290 Self {
291 ray,
292 hit,
293 current: 0,
294 i: 0,
295 j: 0,
296 stack: [0; 32],
297 stack_ptr: -1,
298 indices,
299 nodes,
300 primitives,
301 }
302 }
303}
304
305impl<'a, 'b, T: 'a + Primitive> Iterator for MbvhIterator<'a, 'b, T> {
306 type Item = (&'a T, &'b mut Ray);
307
308 fn next(&mut self) -> Option<Self::Item> {
309 loop {
310 let node = unsafe { self.nodes.get_unchecked(self.current as usize) };
311
312 if self.i >= 4 {
313 if self.stack_ptr < 0 {
314 return None;
315 }
316
317 self.current = self.stack[self.stack_ptr as usize];
318 self.stack_ptr -= 1;
319 self.hit = unsafe {
320 self.nodes
321 .get_unchecked(self.current as usize)
322 .intersect(&self.ray)
323 };
324 self.i = 0;
325 } else {
326 let id = unsafe { *self.hit.ids.get_unchecked((3 - self.i) as usize) } as usize;
327 if unsafe { *self.hit.result.get_unchecked(id) } {
328 let count = node.counts[id];
329 let left_first = node.children[id];
330
331 if count > -1 {
332 if self.j < count {
333 let prim_id = unsafe {
334 *self.indices.get_unchecked((left_first + self.j) as usize)
335 };
336 self.j += 1;
337 if let Some(prim) = self.primitives.get(prim_id as usize) {
338 return Some((prim, unsafe {
339 std::mem::transmute::<&mut Ray, &'b mut Ray>(self.ray)
340 }));
341 }
342 }
343 self.j = 0;
344 } else if left_first > -1 {
345 self.stack_ptr += 1;
346 unsafe {
347 *self.stack.get_unchecked_mut(self.stack_ptr as usize) = left_first;
348 }
349 }
350 }
351 self.i += 1;
352 }
353 }
354 }
355}
356
357#[derive(Debug)]
358pub struct MbvhPacketIterator<'a, 'b, T: 'a + Primitive> {
359 ray: &'b mut RayPacket4,
360 hit: MbvhHit,
361 current: i32,
362 i: i32,
363 j: i32,
364 stack: [i32; 32],
365 stack_ptr: i32,
366 indices: &'a [u32],
367 nodes: &'a [MbvhNode],
368 primitives: &'a [T],
369}
370
371impl<'a, 'b, T: 'a + Primitive> PacketIterator<'a, 'b, T> for MbvhPacketIterator<'a, 'b, T> {}
372
373impl<'a, 'b, T: 'a + Primitive> MbvhPacketIterator<'a, 'b, T> {
374 pub fn new(ray: &'b mut RayPacket4, bvh: &'a Mbvh, primitives: &'a [T]) -> Self {
375 let hit = bvh
376 .m_nodes
377 .get(0)
378 .map(|n| n.intersect4(&ray))
379 .unwrap_or_default();
380 Self {
381 ray,
382 hit,
383 current: 0,
384 i: 0,
385 j: 0,
386 stack: [0; 32],
387 stack_ptr: -1,
388 indices: &bvh.prim_indices,
389 nodes: &bvh.m_nodes,
390 primitives,
391 }
392 }
393
394 pub fn from_slices(
395 ray: &'b mut RayPacket4,
396 nodes: &'a [MbvhNode],
397 indices: &'a [u32],
398 primitives: &'a [T],
399 ) -> Self {
400 let hit = nodes.get(0).map(|n| n.intersect4(&ray)).unwrap_or_default();
401
402 Self {
403 ray,
404 hit,
405 current: 0,
406 i: 0,
407 j: 0,
408 stack: [0; 32],
409 stack_ptr: -1,
410 indices,
411 nodes,
412 primitives,
413 }
414 }
415}
416
417impl<'a, 'b, T: 'a + Primitive> Iterator for MbvhPacketIterator<'a, 'b, T> {
418 type Item = (&'a T, &'b mut RayPacket4);
419
420 fn next(&mut self) -> Option<Self::Item> {
421 loop {
422 let node = unsafe { self.nodes.get_unchecked(self.current as usize) };
423
424 if self.i >= 4 {
425 if self.stack_ptr < 0 {
426 return None;
427 }
428
429 self.current = self.stack[self.stack_ptr as usize];
430 self.stack_ptr -= 1;
431 self.hit = unsafe {
432 self.nodes
433 .get_unchecked(self.current as usize)
434 .intersect4(&self.ray)
435 };
436 self.i = 0;
437 } else {
438 let id = unsafe { *self.hit.ids.get_unchecked((3 - self.i) as usize) } as usize;
439 if unsafe { *self.hit.result.get_unchecked(id) } {
440 let count = node.counts[id];
441 let left_first = node.children[id];
442
443 if count > -1 {
444 if self.j < count {
445 let prim_id = unsafe {
446 *self.indices.get_unchecked((left_first + self.j) as usize)
447 };
448 self.j += 1;
449 if let Some(prim) = self.primitives.get(prim_id as usize) {
450 return Some((prim, unsafe {
451 std::mem::transmute::<&mut RayPacket4, &'b mut RayPacket4>(
452 self.ray,
453 )
454 }));
455 }
456 }
457 self.j = 0;
458 } else if left_first > -1 {
459 self.stack_ptr += 1;
460 unsafe {
461 *self.stack.get_unchecked_mut(self.stack_ptr as usize) = left_first;
462 }
463 }
464 }
465 self.i += 1;
466 }
467 }
468 }
469}