parry3d/query/contact_manifolds/
contact_manifolds_composite_shape_shape.rs1use alloc::{boxed::Box, vec::Vec};
2
3use crate::bounding_volume::BoundingVolume;
4use crate::math::{Isometry, Real};
5use crate::query::contact_manifolds::contact_manifolds_workspace::{
6 TypedWorkspaceData, WorkspaceData,
7};
8use crate::query::contact_manifolds::ContactManifoldsWorkspace;
9use crate::query::query_dispatcher::PersistentQueryDispatcher;
10use crate::query::ContactManifold;
11use crate::shape::{CompositeShape, Shape};
12use crate::utils::hashmap::{Entry, HashMap};
13use crate::utils::IsometryOpt;
14
15#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
16#[cfg_attr(
17 feature = "rkyv",
18 derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize),
19 archive(check_bytes)
20)]
21#[derive(Clone)]
22struct SubDetector {
23 manifold_id: usize,
24 timestamp: bool,
25}
26
27#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
28#[derive(Clone, Default)]
29pub struct CompositeShapeShapeContactManifoldsWorkspace {
30 timestamp: bool,
31 sub_detectors: HashMap<u32, SubDetector>,
32}
33
34impl CompositeShapeShapeContactManifoldsWorkspace {
35 pub fn new() -> Self {
36 Self::default()
37 }
38}
39
40fn ensure_workspace_exists(workspace: &mut Option<ContactManifoldsWorkspace>) {
41 if workspace
42 .as_ref()
43 .and_then(|w| {
44 w.0.downcast_ref::<CompositeShapeShapeContactManifoldsWorkspace>()
45 })
46 .is_some()
47 {
48 return;
49 }
50
51 *workspace = Some(ContactManifoldsWorkspace(Box::new(
52 CompositeShapeShapeContactManifoldsWorkspace::new(),
53 )));
54}
55
56pub fn contact_manifolds_composite_shape_shape<ManifoldData, ContactData>(
58 dispatcher: &dyn PersistentQueryDispatcher<ManifoldData, ContactData>,
59 pos12: &Isometry<Real>,
60 composite1: &dyn CompositeShape,
61 shape2: &dyn Shape,
62 prediction: Real,
63 manifolds: &mut Vec<ContactManifold<ManifoldData, ContactData>>,
64 workspace: &mut Option<ContactManifoldsWorkspace>,
65 flipped: bool,
66) where
67 ManifoldData: Default + Clone,
68 ContactData: Default + Copy,
69{
70 ensure_workspace_exists(workspace);
71 let workspace: &mut CompositeShapeShapeContactManifoldsWorkspace =
72 workspace.as_mut().unwrap().0.downcast_mut().unwrap();
73 let new_timestamp = !workspace.timestamp;
74 workspace.timestamp = new_timestamp;
75
76 let pos12 = *pos12;
81 let pos21 = pos12.inverse();
82
83 let ls_aabb2_1 = shape2.compute_aabb(&pos12).loosened(prediction);
85 let mut old_manifolds = core::mem::take(manifolds);
86
87 let mut leaf1_fn = |leaf1: u32| {
88 composite1.map_part_at(leaf1, &mut |part_pos1, part_shape1, normal_constraints1| {
89 let sub_detector = match workspace.sub_detectors.entry(leaf1) {
90 Entry::Occupied(entry) => {
91 let sub_detector = entry.into_mut();
92 let manifold = old_manifolds[sub_detector.manifold_id].take();
93 sub_detector.manifold_id = manifolds.len();
94 sub_detector.timestamp = new_timestamp;
95 manifolds.push(manifold);
96 sub_detector
97 }
98 Entry::Vacant(entry) => {
99 let sub_detector = SubDetector {
100 manifold_id: manifolds.len(),
101 timestamp: new_timestamp,
102 };
103
104 let mut manifold = ContactManifold::new();
105
106 if flipped {
107 manifold.subshape1 = 0;
108 manifold.subshape2 = leaf1;
109 manifold.subshape_pos2 = part_pos1.copied();
110 } else {
111 manifold.subshape1 = leaf1;
112 manifold.subshape2 = 0;
113 manifold.subshape_pos1 = part_pos1.copied();
114 };
115
116 manifolds.push(manifold);
117 entry.insert(sub_detector)
118 }
119 };
120
121 let manifold = &mut manifolds[sub_detector.manifold_id];
122
123 if flipped {
124 let _ = dispatcher.contact_manifold_convex_convex(
125 &part_pos1.prepend_to(&pos21),
126 shape2,
127 part_shape1,
128 None,
129 normal_constraints1,
130 prediction,
131 manifold,
132 );
133 } else {
134 let _ = dispatcher.contact_manifold_convex_convex(
135 &part_pos1.inv_mul(&pos12),
136 part_shape1,
137 shape2,
138 normal_constraints1,
139 None,
140 prediction,
141 manifold,
142 );
143 }
144 });
145 };
146
147 for leaf_id in composite1.bvh().intersect_aabb(&ls_aabb2_1) {
148 leaf1_fn(leaf_id);
149 }
150
151 workspace
152 .sub_detectors
153 .retain(|_, detector| detector.timestamp == new_timestamp)
154}
155
156impl WorkspaceData for CompositeShapeShapeContactManifoldsWorkspace {
157 fn as_typed_workspace_data(&self) -> TypedWorkspaceData<'_> {
158 TypedWorkspaceData::CompositeShapeShapeContactManifoldsWorkspace(self)
159 }
160
161 fn clone_dyn(&self) -> Box<dyn WorkspaceData> {
162 Box::new(self.clone())
163 }
164}