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}