parry2d/query/nonlinear_shape_cast/
nonlinear_shape_cast_composite_shape_shape.rs1use crate::math::Real;
2use crate::partitioning::BvhNode;
3use crate::query::{
4 self, details::NonlinearShapeCastMode, NonlinearRigidMotion, QueryDispatcher, ShapeCastHit,
5};
6use crate::shape::{Ball, CompositeShapeRef, Shape, SubShapeId, TypedCompositeShape};
7
8impl<S: ?Sized + TypedCompositeShape> CompositeShapeRef<'_, S> {
9 pub fn cast_shape_nonlinear<D: ?Sized + QueryDispatcher>(
16 &self,
17 dispatcher: &D,
18 motion1: &NonlinearRigidMotion,
19 motion2: &NonlinearRigidMotion,
20 shape2: &dyn Shape,
21 start_time: Real,
22 end_time: Real,
23 stop_at_penetration: bool,
24 ) -> Option<(SubShapeId, ShapeCastHit)> {
25 let sphere2 = shape2.compute_local_bounding_sphere();
26
27 self.0.bvh().find_best(
28 end_time,
29 |node: &BvhNode, _| {
30 let aabb1 = node.aabb();
31 let center1 = aabb1.center();
32 let radius1 = aabb1.half_extents().length();
33 let ball1 = Ball::new(radius1);
34 let ball2 = Ball::new(sphere2.radius());
35 let ball_motion1 = motion1.prepend_translation(center1);
36 let ball_motion2 = motion2.prepend_translation(sphere2.center);
37
38 query::details::cast_shapes_nonlinear_support_map_support_map(
39 dispatcher,
40 &ball_motion1,
41 &ball1,
42 &ball1,
43 &ball_motion2,
44 &ball2,
45 &ball2,
46 start_time,
47 end_time,
48 NonlinearShapeCastMode::StopAtPenetration,
49 )
50 .map(|hit| hit.time_of_impact)
51 .unwrap_or(Real::MAX)
52 },
53 |part_id, _| {
54 self.0
55 .map_untyped_part_at(part_id, |part_pos1, part_shape1, _| {
56 if let Some(part_pos1) = part_pos1 {
57 dispatcher
58 .cast_shapes_nonlinear(
59 &motion1.prepend(*part_pos1),
60 part_shape1,
61 motion2,
62 shape2,
63 start_time,
64 end_time,
65 stop_at_penetration,
66 )
67 .ok()?
68 .map(|hit| hit.transform1_by(part_pos1))
69 } else {
70 dispatcher
71 .cast_shapes_nonlinear(
72 motion1,
73 part_shape1,
74 motion2,
75 shape2,
76 start_time,
77 end_time,
78 stop_at_penetration,
79 )
80 .ok()?
81 }
82 })?
83 },
84 )
85 }
86}
87
88pub fn cast_shapes_nonlinear_composite_shape_shape<D, G1>(
90 dispatcher: &D,
91 motion1: &NonlinearRigidMotion,
92 shape1: &G1,
93 motion2: &NonlinearRigidMotion,
94 shape2: &dyn Shape,
95 start_time: Real,
96 end_time: Real,
97 stop_at_penetration: bool,
98) -> Option<ShapeCastHit>
99where
100 D: ?Sized + QueryDispatcher,
101 G1: ?Sized + TypedCompositeShape,
102{
103 CompositeShapeRef(shape1)
104 .cast_shape_nonlinear(
105 dispatcher,
106 motion1,
107 motion2,
108 shape2,
109 start_time,
110 end_time,
111 stop_at_penetration,
112 )
113 .map(|(part_id, mut hit)| {
114 hit.subshape1 = part_id;
115 hit
116 })
117}
118
119pub fn cast_shapes_nonlinear_shape_composite_shape<D, G2>(
121 dispatcher: &D,
122 motion1: &NonlinearRigidMotion,
123 shape1: &dyn Shape,
124 motion2: &NonlinearRigidMotion,
125 shape2: &G2,
126 start_time: Real,
127 end_time: Real,
128 stop_at_penetration: bool,
129) -> Option<ShapeCastHit>
130where
131 D: ?Sized + QueryDispatcher,
132 G2: ?Sized + TypedCompositeShape,
133{
134 cast_shapes_nonlinear_composite_shape_shape(
135 dispatcher,
136 motion2,
137 shape2,
138 motion1,
139 shape1,
140 start_time,
141 end_time,
142 stop_at_penetration,
143 )
144 .map(|hit| hit.swapped())
145}