Skip to main content

parry2d/query/intersection_test/
intersection_test_composite_shape_shape.rs

1use crate::bounding_volume::BoundingVolume;
2use crate::math::Pose;
3use crate::partitioning::BvhNode;
4use crate::query::{QueryDispatcher, ShapeIntersection};
5use crate::shape::{CompositeShapeRef, Shape, SubShapeId, TypedCompositeShape};
6use crate::utils::PoseOpt;
7
8impl<S: ?Sized + TypedCompositeShape> CompositeShapeRef<'_, S> {
9    /// Tests whether the given other `shape`, positioned at `pose12` relative to `self`,
10    /// intersects `self`.
11    ///
12    /// Returns `None` when they do not intersect. Otherwise returns the index of a sub-shape of
13    /// `self` that `shape` intersects alongside that sub-shape's own result (its `subshape1` is
14    /// the sub-shape's own when it is a composite too, and `subshape2` is `shape`'s).
15    pub fn intersects_shape<D: ?Sized + QueryDispatcher>(
16        &self,
17        dispatcher: &D,
18        pose12: &Pose,
19        shape: &dyn Shape,
20    ) -> Option<(SubShapeId, ShapeIntersection)> {
21        let ls_aabb2 = shape.compute_aabb(pose12);
22        self.0
23            .bvh()
24            .leaves(|node: &BvhNode| node.aabb().intersects(&ls_aabb2))
25            .find_map(|leaf_id| {
26                self.0
27                    .map_untyped_part_at(leaf_id, |part_pose1, sub1, _| {
28                        dispatcher
29                            .intersection_test(&part_pose1.inv_mul(pose12), sub1, shape)
30                            .ok()
31                            .filter(|result| result.intersecting)
32                            .map(|result| (leaf_id, result))
33                    })
34                    .flatten()
35            })
36    }
37}
38
39/// Intersection test between a composite shape (`Mesh`, `Compound`) and any other shape.
40pub fn intersection_test_composite_shape_shape<D, G1>(
41    dispatcher: &D,
42    pos12: &Pose,
43    g1: &G1,
44    g2: &dyn Shape,
45) -> ShapeIntersection
46where
47    D: ?Sized + QueryDispatcher,
48    G1: ?Sized + TypedCompositeShape,
49{
50    // `subshape2` is left as the dispatch set it: `g2` may be a composite too, and only it
51    // knows which of its parts answered.
52    match CompositeShapeRef(g1).intersects_shape(dispatcher, pos12, g2) {
53        Some((part_id, result)) => {
54            ShapeIntersection::new(true).with_subshapes(part_id, result.subshape2)
55        }
56        None => ShapeIntersection::new(false),
57    }
58}
59
60/// Proximity between a shape and a composite (`Mesh`, `Compound`) shape.
61pub fn intersection_test_shape_composite_shape<D, G2>(
62    dispatcher: &D,
63    pos12: &Pose,
64    g1: &dyn Shape,
65    g2: &G2,
66) -> ShapeIntersection
67where
68    D: ?Sized + QueryDispatcher,
69    G2: ?Sized + TypedCompositeShape,
70{
71    intersection_test_composite_shape_shape(dispatcher, &pos12.inverse(), g2, g1).swapped()
72}