parry3d/query/shape_cast/
shape_cast_composite_shape_shape.rs1use crate::bounding_volume::Aabb;
2use crate::math::{Pose, Real, Vector};
3use crate::partitioning::BvhNode;
4use crate::query::shape_cast::ShapeCastOptions;
5use crate::query::{QueryDispatcher, Ray, RayCast, ShapeCastHit};
6use crate::shape::{CompositeShapeRef, Shape, SubShapeId, TypedCompositeShape};
7
8impl<S: ?Sized + TypedCompositeShape> CompositeShapeRef<'_, S> {
9 pub fn cast_shape<D: ?Sized + QueryDispatcher>(
16 &self,
17 dispatcher: &D,
18 pose12: &Pose,
19 vel12: Vector,
20 g2: &dyn Shape,
21 options: ShapeCastOptions,
22 ) -> Option<(SubShapeId, ShapeCastHit)> {
23 let ls_aabb2 = g2.compute_aabb(pose12);
24 let ray = Ray::new(Vector::ZERO, vel12);
25 let msum_shift = -ls_aabb2.center();
26 let msum_margin = ls_aabb2.half_extents() + Vector::splat(options.target_distance);
27
28 self.0.bvh().find_best(
29 options.max_time_of_impact,
30 |node: &BvhNode, best_so_far| {
31 let msum = Aabb {
33 mins: node.mins() + msum_shift - msum_margin,
34 maxs: node.maxs() + msum_shift + msum_margin,
35 };
36
37 msum.cast_local_ray(&ray, best_so_far, true)
39 .unwrap_or(Real::MAX)
40 },
41 |part_id, _| {
42 self.0
43 .map_untyped_part_at(part_id, |part_pose1, part_g1, _| {
44 if let Some(part_pose1) = part_pose1 {
45 dispatcher
46 .cast_shapes(
47 &part_pose1.inv_mul(pose12),
48 part_pose1.rotation.inverse() * vel12,
49 part_g1,
50 g2,
51 options,
52 )
53 .ok()?
54 .map(|hit| hit.transform1_by(part_pose1))
55 } else {
56 dispatcher
57 .cast_shapes(pose12, vel12, part_g1, g2, options)
58 .ok()?
59 }
60 })?
61 },
62 )
63 }
64}
65
66pub fn cast_shapes_composite_shape_shape<D, G1>(
68 dispatcher: &D,
69 pos12: &Pose,
70 vel12: Vector,
71 g1: &G1,
72 g2: &dyn Shape,
73 options: ShapeCastOptions,
74) -> Option<ShapeCastHit>
75where
76 D: ?Sized + QueryDispatcher,
77 G1: ?Sized + TypedCompositeShape,
78{
79 CompositeShapeRef(g1)
80 .cast_shape(dispatcher, pos12, vel12, g2, options)
81 .map(|(part_id, mut hit)| {
82 hit.subshape1 = part_id;
83 hit
84 })
85}
86
87pub fn cast_shapes_shape_composite_shape<D, G2>(
89 dispatcher: &D,
90 pos12: &Pose,
91 vel12: Vector,
92 g1: &dyn Shape,
93 g2: &G2,
94 options: ShapeCastOptions,
95) -> Option<ShapeCastHit>
96where
97 D: ?Sized + QueryDispatcher,
98 G2: ?Sized + TypedCompositeShape,
99{
100 cast_shapes_composite_shape_shape(
101 dispatcher,
102 &pos12.inverse(),
103 -(pos12.rotation.inverse() * vel12),
104 g2,
105 g1,
106 options,
107 )
108 .map(|time_of_impact| time_of_impact.swapped())
109}