1#[cfg(feature = "alloc")]
4pub(crate) use self::broad_phase_bvh::DeferredBvhOptimize;
5#[cfg(feature = "alloc")]
6pub use self::broad_phase_bvh::{BroadPhaseBvh, BvhOptimizationStrategy};
7pub use self::broad_phase_pair_event::{BroadPhasePairEvent, ColliderPair};
8#[cfg(feature = "alloc")]
9pub use self::collider::{Collider, ColliderBuilder};
10#[cfg(feature = "alloc")]
11pub use self::collider_components::*;
12pub use self::collider_handle::ColliderHandle;
13#[cfg(feature = "alloc")]
14pub use self::collider_set::{ColliderSet, ModifiedColliders};
15#[cfg(feature = "alloc")]
16pub(crate) use self::contact_pair::ContactRecycleState;
17#[cfg(feature = "alloc")]
18pub(crate) use self::contact_pair::PairEventStatus;
19#[cfg(feature = "alloc")]
20pub(crate) use self::contact_pair::SOLVER_DYNAMIC_COLOR_COUNT;
21#[cfg(feature = "alloc")]
22pub(crate) use self::contact_pair::relative_pose_drift;
23#[cfg(feature = "alloc")]
24pub use self::contact_pair::{
25 ContactData, ContactId, ContactManifoldData, ContactPair, IntersectionPair, NEW_CONTACT_BIT,
26 PairContacts, RigidPairContacts, SimdSolverContact, SolverContact, SolverContactGeneric,
27 SolverContacts, SolverFlags, is_bouncy, is_bouncy_simd,
28};
29#[cfg(feature = "alloc")]
30pub use self::interaction_graph::{
31 ColliderGraphIndex, InteractionGraph, RigidBodyGraphIndex, TemporaryInteractionIndex,
32};
33pub use self::interaction_groups::{Group, InteractionGroups, InteractionTestMode};
34#[cfg(feature = "alloc")]
35pub use self::mesh_converter::{MeshConverter, MeshConverterError};
36#[cfg(feature = "alloc")]
37pub use self::narrow_phase::NarrowPhase;
38#[cfg(feature = "alloc")]
39pub(crate) use self::narrow_phase::soft_contacts;
40#[cfg(feature = "alloc")]
41pub use self::narrow_phase::soft_contacts::{
42 SoftContactImpulse, SoftEdgeCandidate, SoftEdgePass, SoftPairContacts, SoftVertexCandidate,
43 SoftVertexHits, SoftVertexPass, SoftVolumePatch, VolumeBin,
44};
45#[cfg(feature = "alloc")]
46pub use parry::utils::Array2;
47
48pub use parry::bounding_volume::BoundingVolume;
49#[cfg(feature = "alloc")]
50pub use parry::partitioning::{Bvh, BvhBuildStrategy};
51#[cfg(feature = "alloc")]
52pub use parry::query::{PointQuery, PointQueryWithLocation, RayCast, TrackedContact};
53#[cfg(feature = "alloc")]
54pub use parry::shape::{SharedShape, VoxelState, VoxelType, Voxels};
55
56#[cfg(feature = "alloc")]
57use crate::math::{Real, Vector};
58
59#[cfg(feature = "alloc")]
61pub type Contact = parry::query::TrackedContact<ContactData>;
62#[cfg(feature = "alloc")]
64pub type ContactManifold = parry::query::ContactManifold<ContactManifoldData, ContactData>;
65pub type Segment = parry::shape::Segment;
67pub type Cuboid = parry::shape::Cuboid;
69pub type Triangle = parry::shape::Triangle;
71pub type Ball = parry::shape::Ball;
73pub type Capsule = parry::shape::Capsule;
75#[cfg(feature = "alloc")]
77pub type HeightField = parry::shape::HeightField;
78#[cfg(feature = "dim3")]
80pub type Cylinder = parry::shape::Cylinder;
81#[cfg(feature = "dim3")]
83pub type Cone = parry::shape::Cone;
84pub type Aabb = parry::bounding_volume::Aabb;
86pub type Ray = parry::query::Ray;
88pub type RayIntersection = parry::query::RayIntersection;
90pub type PointProjection = parry::query::PointProjection;
92pub type ShapeCastHit = parry::query::ShapeCastHit;
94#[cfg(feature = "alloc")]
96pub type DefaultBroadPhase = BroadPhaseBvh;
97
98bitflags::bitflags! {
99 #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
101 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
102 pub struct CollisionEventFlags: u32 {
103 const SENSOR = 0b0001;
106 const REMOVED = 0b0010;
109 }
110}
111
112#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
113#[derive(Copy, Clone, Hash, Debug)]
114pub enum CollisionEvent {
144 Started(ColliderHandle, ColliderHandle, CollisionEventFlags),
146 Stopped(ColliderHandle, ColliderHandle, CollisionEventFlags),
148}
149
150impl CollisionEvent {
151 pub fn started(self) -> bool {
153 matches!(self, CollisionEvent::Started(..))
154 }
155
156 pub fn stopped(self) -> bool {
158 matches!(self, CollisionEvent::Stopped(..))
159 }
160
161 pub fn collider1(self) -> ColliderHandle {
163 match self {
164 Self::Started(h, _, _) | Self::Stopped(h, _, _) => h,
165 }
166 }
167
168 pub fn collider2(self) -> ColliderHandle {
170 match self {
171 Self::Started(_, h, _) | Self::Stopped(_, h, _) => h,
172 }
173 }
174
175 pub fn sensor(self) -> bool {
177 match self {
178 Self::Started(_, _, f) | Self::Stopped(_, _, f) => {
179 f.contains(CollisionEventFlags::SENSOR)
180 }
181 }
182 }
183
184 pub fn removed(self) -> bool {
186 match self {
187 Self::Started(_, _, f) | Self::Stopped(_, _, f) => {
188 f.contains(CollisionEventFlags::REMOVED)
189 }
190 }
191 }
192}
193
194#[cfg(feature = "alloc")]
195#[derive(Copy, Clone, PartialEq, Debug, Default)]
196pub struct ContactForceEvent {
199 pub collider1: ColliderHandle,
201 pub collider2: ColliderHandle,
203 pub total_force: Vector,
205 pub total_force_magnitude: Real,
211 pub max_force_direction: Vector,
213 pub max_force_magnitude: Real,
215 pub started: bool,
225}
226
227#[cfg(feature = "alloc")]
228impl ContactForceEvent {
229 pub fn from_contact_pair(dt: Real, pair: &ContactPair, total_force_magnitude: Real) -> Self {
231 let mut result = ContactForceEvent {
232 collider1: pair.collider1,
233 collider2: pair.collider2,
234 total_force_magnitude,
235 started: !pair
238 .event_status
239 .contains(PairEventStatus::INITIAL_FORCE_THRESHOLD_EVENT_EMITTED),
240 ..ContactForceEvent::default()
241 };
242
243 for m in pair.solver_manifolds() {
244 let mut total_manifold_impulse = 0.0;
245 for pt in m.contacts() {
246 total_manifold_impulse += pt.data.impulse;
247
248 if pt.data.impulse > result.max_force_magnitude {
249 result.max_force_magnitude = pt.data.impulse;
250 result.max_force_direction = m.data.normal;
251 }
252 }
253
254 result.total_force += m.data.normal * total_manifold_impulse;
255 }
256 if let Some(soft) = pair.soft() {
258 for i in soft.impulses(pair.collider1) {
259 if i.impulse > result.max_force_magnitude {
260 result.max_force_magnitude = i.impulse;
261 result.max_force_direction = i.normal;
262 }
263 result.total_force += i.normal * i.impulse;
264 }
265 }
266
267 let inv_dt = crate::utils::inv(dt);
268 result.total_force *= inv_dt;
273 result.max_force_magnitude *= inv_dt;
274 result
275 }
276}
277
278#[cfg(feature = "alloc")]
279pub(crate) use self::narrow_phase::ContactManifoldIndex;
280#[cfg(feature = "alloc")]
281pub use parry::shape::*;
282
283#[cfg(all(feature = "serde-serialize", feature = "alloc"))]
284pub(crate) fn default_persistent_query_dispatcher()
285-> alloc::sync::Arc<dyn parry::query::PersistentQueryDispatcher<ContactManifoldData, ContactData>> {
286 alloc::sync::Arc::new(parry::query::DefaultQueryDispatcher)
287}
288
289#[cfg(feature = "alloc")]
290mod collider_components;
291mod collider_handle;
292#[cfg(feature = "alloc")]
293pub(crate) mod contact_pair;
294#[cfg(feature = "alloc")]
295mod interaction_graph;
296mod interaction_groups;
297#[cfg(feature = "alloc")]
298mod narrow_phase;
299
300#[cfg(feature = "alloc")]
301mod broad_phase_bvh;
302mod broad_phase_pair_event;
303#[cfg(feature = "alloc")]
304mod collider;
305#[cfg(feature = "alloc")]
306mod collider_set;
307#[cfg(feature = "alloc")]
308mod mesh_converter;
309
310#[cfg(all(feature = "dim3", feature = "alloc"))]
311mod manifold_reduction;
312
313#[cfg(all(feature = "dim3", feature = "alloc"))]
314mod contact_clustering;