parry3d_f64/query/intersection_test/
intersection_test_composite_shape_shape.rs1use crate::bounding_volume::SimdAabb;
2use crate::math::{Isometry, Real, SIMD_WIDTH};
3use crate::partitioning::{SimdVisitStatus, SimdVisitor};
4use crate::query::QueryDispatcher;
5use crate::shape::{Shape, TypedSimdCompositeShape};
6use crate::utils::IsometryOpt;
7use simba::simd::SimdBool as _;
8
9pub fn intersection_test_composite_shape_shape<D, G1>(
11 dispatcher: &D,
12 pos12: &Isometry<Real>,
13 g1: &G1,
14 g2: &dyn Shape,
15) -> bool
16where
17 D: ?Sized + QueryDispatcher,
18 G1: ?Sized + TypedSimdCompositeShape,
19{
20 let mut visitor = IntersectionCompositeShapeShapeVisitor::new(dispatcher, pos12, g1, g2);
21
22 let _ = g1.typed_qbvh().traverse_depth_first(&mut visitor);
23 visitor.found_intersection.is_some()
24}
25
26pub fn intersection_test_shape_composite_shape<D, G2>(
28 dispatcher: &D,
29 pos12: &Isometry<Real>,
30 g1: &dyn Shape,
31 g2: &G2,
32) -> bool
33where
34 D: ?Sized + QueryDispatcher,
35 G2: ?Sized + TypedSimdCompositeShape,
36{
37 intersection_test_composite_shape_shape(dispatcher, &pos12.inverse(), g2, g1)
38}
39
40pub struct IntersectionCompositeShapeShapeVisitor<'a, D: ?Sized, G1: 'a>
42where
43 G1: ?Sized + TypedSimdCompositeShape,
44{
45 ls_aabb2: SimdAabb,
46
47 dispatcher: &'a D,
48 pos12: &'a Isometry<Real>,
49 g1: &'a G1,
50 g2: &'a dyn Shape,
51
52 pub found_intersection: Option<G1::PartId>,
56}
57
58impl<'a, D, G1> IntersectionCompositeShapeShapeVisitor<'a, D, G1>
59where
60 D: ?Sized + QueryDispatcher,
61 G1: ?Sized + TypedSimdCompositeShape,
62{
63 pub fn new(
65 dispatcher: &'a D,
66 pos12: &'a Isometry<Real>,
67 g1: &'a G1,
68 g2: &'a dyn Shape,
69 ) -> IntersectionCompositeShapeShapeVisitor<'a, D, G1> {
70 let ls_aabb2 = g2.compute_aabb(pos12);
71
72 IntersectionCompositeShapeShapeVisitor {
73 dispatcher,
74 ls_aabb2: SimdAabb::splat(ls_aabb2),
75 pos12,
76 g1,
77 g2,
78 found_intersection: None,
79 }
80 }
81}
82
83impl<D, G1> SimdVisitor<G1::PartId, SimdAabb> for IntersectionCompositeShapeShapeVisitor<'_, D, G1>
84where
85 D: ?Sized + QueryDispatcher,
86 G1: ?Sized + TypedSimdCompositeShape,
87{
88 fn visit(
89 &mut self,
90 bv: &SimdAabb,
91 data: Option<[Option<&G1::PartId>; SIMD_WIDTH]>,
92 ) -> SimdVisitStatus {
93 let mask = self.ls_aabb2.intersects(bv);
94
95 if let Some(data) = data {
96 let bitmask = mask.bitmask();
97 let mut found_intersection = false;
98
99 for (ii, data) in data.into_iter().enumerate() {
100 if (bitmask & (1 << ii)) != 0 {
101 let Some(data) = data else { continue };
102 let part_id = *data;
103 self.g1.map_untyped_part_at(part_id, |part_pos1, g1, _| {
104 found_intersection = self.dispatcher.intersection_test(
105 &part_pos1.inv_mul(self.pos12),
106 g1,
107 self.g2,
108 ) == Ok(true);
109 });
110
111 if found_intersection {
112 self.found_intersection = Some(part_id);
113 return SimdVisitStatus::ExitEarly;
114 }
115 }
116 }
117 }
118
119 SimdVisitStatus::MaybeContinue(mask)
120 }
121}