Skip to main content

parry3d/query/contact/
contact_heightfield_shape.rs

1use crate::bounding_volume::BoundingVolume;
2use crate::math::{Pose, Real};
3use crate::query::{Contact, QueryDispatcher};
4use crate::shape::{HeightField, Shape};
5
6/// Best contact between a heightfield and any other shape.
7///
8/// Tests the elements intersecting `shape2`'s Aabb (loosened by `prediction`) and returns
9/// the deepest contact.
10pub fn contact_heightfield_shape<D>(
11    dispatcher: &D,
12    pos12: &Pose,
13    heightfield1: &HeightField,
14    shape2: &dyn Shape,
15    prediction: Real,
16) -> Option<Contact>
17where
18    D: ?Sized + QueryDispatcher,
19{
20    let aabb2_1 = shape2.compute_aabb(pos12).loosened(prediction.max(0.0));
21    let mut result = None::<Contact>;
22
23    heightfield1.map_elements_in_local_aabb(&aabb2_1, &mut |_, elt1| {
24        // The elements are already in the heightfield's local frame, so the sub-shape
25        // contact needs no transform.
26        if let Ok(Some(c)) = dispatcher.contact(pos12, elt1, shape2, prediction) {
27            if result.is_none_or(|best| c.dist < best.dist) {
28                result = Some(c);
29            }
30        }
31    });
32
33    result
34}
35
36/// Best contact between a shape and a heightfield.
37pub fn contact_shape_heightfield<D>(
38    dispatcher: &D,
39    pos12: &Pose,
40    shape1: &dyn Shape,
41    heightfield2: &HeightField,
42    prediction: Real,
43) -> Option<Contact>
44where
45    D: ?Sized + QueryDispatcher,
46{
47    contact_heightfield_shape(
48        dispatcher,
49        &pos12.inverse(),
50        heightfield2,
51        shape1,
52        prediction,
53    )
54    .map(|c| c.flipped())
55}