ncollide3d/pipeline/glue/
query.rs

1use na::RealField;
2use std::vec::IntoIter;
3
4use crate::bounding_volume::AABB;
5use crate::math::Point;
6use crate::pipeline::broad_phase::BroadPhase;
7use crate::pipeline::object::{CollisionGroups, CollisionObjectRef, CollisionObjectSet};
8use crate::query::{PointQuery, Ray, RayCast, RayIntersection};
9
10/// Returns an iterator yielding all the collision objects intersecting with the given ray.
11///
12/// The result will only include collision objects in a group that can interact with the given `groups`.
13pub fn interferences_with_ray<'a, 'b, N, Objects>(
14    objects: &'a Objects,
15    broad_phase: &'a (impl BroadPhase<N, AABB<N>, Objects::CollisionObjectHandle> + ?Sized),
16    ray: &'b Ray<N>,
17    max_toi: N,
18    groups: &'b CollisionGroups,
19) -> InterferencesWithRay<'a, 'b, N, Objects>
20where
21    N: RealField + Copy,
22    Objects: CollisionObjectSet<N>,
23{
24    let mut handles = Vec::new();
25    broad_phase.interferences_with_ray(ray, max_toi, &mut handles);
26
27    InterferencesWithRay {
28        ray,
29        max_toi,
30        groups,
31        objects,
32        handles: handles.into_iter(),
33    }
34}
35
36/// Iterator through all the objects on the world that intersect a specific ray.
37pub struct InterferencesWithRay<'a, 'b, N: RealField + Copy, Objects: CollisionObjectSet<N>> {
38    ray: &'b Ray<N>,
39    max_toi: N,
40    objects: &'a Objects,
41    groups: &'b CollisionGroups,
42    handles: IntoIter<&'a Objects::CollisionObjectHandle>,
43}
44
45impl<'a, 'b, N: RealField + Copy, Objects> Iterator for InterferencesWithRay<'a, 'b, N, Objects>
46where
47    N: RealField + Copy,
48    Objects: CollisionObjectSet<N>,
49{
50    type Item = (
51        Objects::CollisionObjectHandle,
52        &'a Objects::CollisionObject,
53        RayIntersection<N>,
54    );
55
56    #[inline]
57    fn next(&mut self) -> Option<Self::Item> {
58        while let Some(handle) = self.handles.next() {
59            if let Some(co) = self.objects.collision_object(*handle) {
60                if co.collision_groups().can_interact_with_groups(self.groups) {
61                    let inter = co.shape().toi_and_normal_with_ray(
62                        &co.position(),
63                        self.ray,
64                        self.max_toi,
65                        true,
66                    );
67
68                    if let Some(inter) = inter {
69                        return Some((*handle, co, inter));
70                    }
71                }
72            }
73        }
74
75        None
76    }
77}
78
79/// Returns an iterator yielding all the collision objects containing the given point.
80///
81/// The result will only include collision objects in a group that can interact with the given `groups`.
82pub fn interferences_with_point<'a, 'b, N, Objects>(
83    objects: &'a Objects,
84    broad_phase: &'a (impl BroadPhase<N, AABB<N>, Objects::CollisionObjectHandle> + ?Sized),
85    point: &'b Point<N>,
86    groups: &'b CollisionGroups,
87) -> InterferencesWithPoint<'a, 'b, N, Objects>
88where
89    N: RealField + Copy,
90    Objects: CollisionObjectSet<N>,
91{
92    let mut handles = Vec::new();
93    broad_phase.interferences_with_point(point, &mut handles);
94
95    InterferencesWithPoint {
96        point,
97        groups,
98        objects,
99        handles: handles.into_iter(),
100    }
101}
102
103/// Iterator through all the objects on the world that intersect a specific point.
104pub struct InterferencesWithPoint<'a, 'b, N: RealField + Copy, Objects: CollisionObjectSet<N>> {
105    point: &'b Point<N>,
106    objects: &'a Objects,
107    groups: &'b CollisionGroups,
108    handles: IntoIter<&'a Objects::CollisionObjectHandle>,
109}
110
111impl<'a, 'b, N: RealField + Copy, Objects> Iterator for InterferencesWithPoint<'a, 'b, N, Objects>
112where
113    N: RealField + Copy,
114    Objects: CollisionObjectSet<N>,
115{
116    type Item = (Objects::CollisionObjectHandle, &'a Objects::CollisionObject);
117
118    #[inline]
119    fn next(&mut self) -> Option<Self::Item> {
120        while let Some(handle) = self.handles.next() {
121            if let Some(co) = self.objects.collision_object(*handle) {
122                if co.collision_groups().can_interact_with_groups(self.groups)
123                    && co.shape().contains_point(&co.position(), self.point)
124                {
125                    return Some((*handle, co));
126                }
127            }
128        }
129
130        None
131    }
132}
133
134/// Returns an iterator yielding all the collision objects with an AABB intersecting with the given AABB.
135///
136/// The result will only include collision objects in a group that can interact with the given `groups`.
137pub fn interferences_with_aabb<'a, 'b, N, Objects>(
138    objects: &'a Objects,
139    broad_phase: &'a (impl BroadPhase<N, AABB<N>, Objects::CollisionObjectHandle> + ?Sized),
140    aabb: &AABB<N>,
141    groups: &'b CollisionGroups,
142) -> InterferencesWithAABB<'a, 'b, N, Objects>
143where
144    N: RealField + Copy,
145    Objects: CollisionObjectSet<N>,
146{
147    let mut handles = Vec::new();
148    broad_phase.interferences_with_bounding_volume(aabb, &mut handles);
149
150    InterferencesWithAABB {
151        groups,
152        objects,
153        handles: handles.into_iter(),
154    }
155}
156
157/// Iterator through all the objects on the world which bounding volume intersects a specific AABB.
158pub struct InterferencesWithAABB<'a, 'b, N: RealField + Copy, Objects: CollisionObjectSet<N>> {
159    objects: &'a Objects,
160    groups: &'b CollisionGroups,
161    handles: IntoIter<&'a Objects::CollisionObjectHandle>,
162}
163
164impl<'a, 'b, N: RealField + Copy, Objects: CollisionObjectSet<N>> Iterator
165    for InterferencesWithAABB<'a, 'b, N, Objects>
166{
167    type Item = (Objects::CollisionObjectHandle, &'a Objects::CollisionObject);
168
169    #[inline]
170    fn next(&mut self) -> Option<Self::Item> {
171        while let Some(handle) = self.handles.next() {
172            if let Some(co) = self.objects.collision_object(*handle) {
173                if co.collision_groups().can_interact_with_groups(self.groups) {
174                    return Some((*handle, co));
175                }
176            }
177        }
178
179        None
180    }
181}
182
183/// Return structure for `first_interference_with_ray`
184///
185/// Contains the handle of the closest object along the ray along with its
186/// intersection details
187#[derive(Debug)]
188pub struct FirstInterferenceWithRay<'a, N: RealField + Copy, Objects: CollisionObjectSet<N>> {
189    /// Handle to the object the ray collided with.
190    pub handle: Objects::CollisionObjectHandle,
191    /// Reference to the object the ray collided with.
192    pub co: &'a Objects::CollisionObject,
193    /// Intersection details
194    pub inter: RayIntersection<N>,
195}
196
197/// Returns an the closest collision object intersecting with the given ray.
198///
199/// The result will only include collision objects in a group that can interact with the given `groups`.
200pub fn first_interference_with_ray<'a, 'b, N: RealField + Copy, Objects: CollisionObjectSet<N>>(
201    objects: &'a Objects,
202    broad_phase: &'a (impl BroadPhase<N, AABB<N>, Objects::CollisionObjectHandle> + ?Sized),
203    ray: &'b Ray<N>,
204    max_toi: N,
205    groups: &'b CollisionGroups,
206) -> Option<FirstInterferenceWithRay<'a, N, Objects>> {
207    // Narrow phase
208    let narrow_phase = move |handle: Objects::CollisionObjectHandle, ray: &Ray<N>, max_toi: N| {
209        let co = objects.collision_object(handle)?;
210        if co.collision_groups().can_interact_with_groups(groups) {
211            let inter = co
212                .shape()
213                .toi_and_normal_with_ray(&co.position(), ray, max_toi, true);
214
215            inter.map(|inter| (handle, inter))
216        } else {
217            None
218        }
219    };
220
221    let (handle, inter) = broad_phase.first_interference_with_ray(ray, max_toi, &narrow_phase)?;
222    let co = objects.collision_object(handle)?;
223    Some(FirstInterferenceWithRay { handle, co, inter })
224}