rtbvh/
iter.rs

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}