rapier3d/pipeline/event_handler.rs
1use crate::dynamics::RigidBodySet;
2use crate::geometry::{ColliderSet, CollisionEvent, ContactForceEvent, ContactPair};
3use crate::math::Real;
4use std::sync::mpsc::Sender;
5
6bitflags::bitflags! {
7 #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
8 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
9 /// Flags affecting the events generated for this collider.
10 pub struct ActiveEvents: u32 {
11 /// If set, Rapier will call `EventHandler::handle_collision_event`
12 /// whenever relevant for this collider.
13 const COLLISION_EVENTS = 0b0001;
14 /// If set, Rapier will call `EventHandler::handle_contact_force_event`
15 /// whenever relevant for this collider.
16 const CONTACT_FORCE_EVENTS = 0b0010;
17 }
18}
19
20impl Default for ActiveEvents {
21 fn default() -> Self {
22 ActiveEvents::empty()
23 }
24}
25
26/// Trait implemented by structures responsible for handling events generated by the physics engine.
27///
28/// Implementors of this trait will typically collect these events for future processing.
29pub trait EventHandler: Send + Sync {
30 /// Handle a collision event.
31 ///
32 /// A collision event is emitted when the state of intersection between two colliders changes.
33 /// At least one of the involved colliders must have the `ActiveEvents::COLLISION_EVENTS` flag
34 /// set.
35 ///
36 /// # Parameters
37 /// * `event` - The collision event.
38 /// * `bodies` - The set of rigid-bodies.
39 /// * `colliders` - The set of colliders.
40 /// * `contact_pair` - The current state of contacts between the two colliders. This is set to `None`
41 /// if at least one of the collider is a sensor (in which case no contact information
42 /// is ever computed).
43 fn handle_collision_event(
44 &self,
45 bodies: &RigidBodySet,
46 colliders: &ColliderSet,
47 event: CollisionEvent,
48 contact_pair: Option<&ContactPair>,
49 );
50
51 /// Handle a force event.
52 ///
53 /// A force event is generated whenever the total force magnitude applied between two
54 /// colliders is `> Collider::contact_force_event_threshold` value of any of these
55 /// colliders with the `ActiveEvents::CONTACT_FORCE_EVENTS` flag set.
56 ///
57 /// The "total force magnitude" here means "the sum of the magnitudes of the forces applied at
58 /// all the contact points in a contact pair". Therefore, if the contact pair involves two
59 /// forces `{0.0, 1.0, 0.0}` and `{0.0, -1.0, 0.0}`, then the total force magnitude tested
60 /// against the `contact_force_event_threshold` is `2.0` even if the sum of these forces is actually the
61 /// zero vector.
62 fn handle_contact_force_event(
63 &self,
64 dt: Real,
65 bodies: &RigidBodySet,
66 colliders: &ColliderSet,
67 contact_pair: &ContactPair,
68 total_force_magnitude: Real,
69 );
70}
71
72impl EventHandler for () {
73 fn handle_collision_event(
74 &self,
75 _bodies: &RigidBodySet,
76 _colliders: &ColliderSet,
77 _event: CollisionEvent,
78 _contact_pair: Option<&ContactPair>,
79 ) {
80 }
81
82 fn handle_contact_force_event(
83 &self,
84 _dt: Real,
85 _bodies: &RigidBodySet,
86 _colliders: &ColliderSet,
87 _contact_pair: &ContactPair,
88 _total_force_magnitude: Real,
89 ) {
90 }
91}
92
93/// A collision event handler that collects events into a channel.
94pub struct ChannelEventCollector {
95 collision_event_sender: Sender<CollisionEvent>,
96 contact_force_event_sender: Sender<ContactForceEvent>,
97}
98
99impl ChannelEventCollector {
100 /// Initialize a new collision event handler from channel senders.
101 pub fn new(
102 collision_event_sender: Sender<CollisionEvent>,
103 contact_force_event_sender: Sender<ContactForceEvent>,
104 ) -> Self {
105 Self {
106 collision_event_sender,
107 contact_force_event_sender,
108 }
109 }
110}
111
112impl EventHandler for ChannelEventCollector {
113 fn handle_collision_event(
114 &self,
115 _bodies: &RigidBodySet,
116 _colliders: &ColliderSet,
117 event: CollisionEvent,
118 _: Option<&ContactPair>,
119 ) {
120 let _ = self.collision_event_sender.send(event);
121 }
122
123 fn handle_contact_force_event(
124 &self,
125 dt: Real,
126 _bodies: &RigidBodySet,
127 _colliders: &ColliderSet,
128 contact_pair: &ContactPair,
129 total_force_magnitude: Real,
130 ) {
131 let result = ContactForceEvent::from_contact_pair(dt, contact_pair, total_force_magnitude);
132 let _ = self.contact_force_event_sender.send(result);
133 }
134}