shipyard_rapier3d/physics/
resources.rs

1use crate::rapier::{
2    geometry::{ContactEvent, IntersectionEvent},
3    pipeline::{EventHandler, PhysicsHooks},
4};
5use concurrent_queue::ConcurrentQueue;
6use rapier::math::Vector;
7
8/// A resource for specifying configuration information for the physics simulation
9pub struct RapierConfiguration {
10    /// Specifying the gravity of the physics simulation.
11    pub gravity: Vector<f32>,
12    /// Specifies a scale ratio between the physics world and the bevy transforms.
13    /// This will affect the transform synchronization between Bevy and Rapier.
14    /// Each Rapier rigid-body position will have its coordinates multiplied by this scale factor.
15    pub scale: f32,
16    /// Specifies if the physics simulation is active and update the physics world.
17    pub physics_pipeline_active: bool,
18    /// Specifies if the query pipeline is active and update the query pipeline.
19    pub query_pipeline_active: bool,
20    /// Specifies if the number of physics steps run at each frame should depend
21    /// of the real-world time elapsed since the last step.
22    pub time_dependent_number_of_timesteps: bool,
23}
24
25impl Default for RapierConfiguration {
26    fn default() -> Self {
27        Self {
28            gravity: Vector::y() * -9.81,
29            scale: 1.0,
30            physics_pipeline_active: true,
31            query_pipeline_active: true,
32            time_dependent_number_of_timesteps: false,
33        }
34    }
35}
36
37// TODO: it may be more efficient to use crossbeam channel.
38// However crossbeam channels cause a Segfault (I have not
39// investigated how to reproduce this exactly to open an
40// issue).
41/// A set of queues collecting events emitted by the physics engine.
42pub struct EventQueue {
43    /// The unbounded contact event queue.
44    pub contact_events: ConcurrentQueue<ContactEvent>,
45    /// The unbounded intersection event queue.
46    pub intersection_events: ConcurrentQueue<IntersectionEvent>,
47    /// Are these queues automatically cleared before each simulation timestep?
48    pub auto_clear: bool,
49}
50
51impl EventQueue {
52    /// Creates a new empty event queue.
53    pub fn new(auto_clear: bool) -> Self {
54        Self {
55            contact_events: ConcurrentQueue::unbounded(),
56            intersection_events: ConcurrentQueue::unbounded(),
57            auto_clear,
58        }
59    }
60
61    /// Removes all events contained by this queue.
62    pub fn clear(&self) {
63        while let Ok(_) = self.contact_events.pop() {}
64        while let Ok(_) = self.intersection_events.pop() {}
65    }
66}
67
68impl EventHandler for EventQueue {
69    fn handle_intersection_event(&self, event: IntersectionEvent) {
70        let _ = self.intersection_events.push(event);
71    }
72
73    fn handle_contact_event(&self, event: ContactEvent) {
74        let _ = self.contact_events.push(event);
75    }
76}
77
78/// Difference between simulation and rendering time
79#[derive(Default)]
80pub struct SimulationToRenderTime {
81    /// Difference between simulation and rendering time
82    pub diff: f32,
83}
84
85/// Custom filters for intersection and contact pairs.
86pub struct UserPhysicsHooks {
87    /// Custom user defined physics.
88    pub hooks: Box<dyn PhysicsHooks>,
89}
90
91impl UserPhysicsHooks {
92    /// A new interaction pair filter with no custom intersection and contact pair filters.
93    pub fn new() -> Self {
94        Self {
95            hooks: Box::new(()),
96        }
97    }
98
99    /// Set the user defined physics hooks.
100    pub fn hooks(&mut self, hooks: impl PhysicsHooks + 'static) {
101        self.hooks = Box::new(hooks) as Box<dyn PhysicsHooks>;
102    }
103}