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}