shipyard_rapier3d 0.1.0

An integration with the physics engine rapier, for the shipard ECS.
Documentation
use crate::rapier::{
    geometry::{ContactEvent, IntersectionEvent},
    pipeline::{EventHandler, PhysicsHooks},
};
use concurrent_queue::ConcurrentQueue;
use rapier::math::Vector;

/// A resource for specifying configuration information for the physics simulation
pub struct RapierConfiguration {
    /// Specifying the gravity of the physics simulation.
    pub gravity: Vector<f32>,
    /// Specifies a scale ratio between the physics world and the bevy transforms.
    /// This will affect the transform synchronization between Bevy and Rapier.
    /// Each Rapier rigid-body position will have its coordinates multiplied by this scale factor.
    pub scale: f32,
    /// Specifies if the physics simulation is active and update the physics world.
    pub physics_pipeline_active: bool,
    /// Specifies if the query pipeline is active and update the query pipeline.
    pub query_pipeline_active: bool,
    /// Specifies if the number of physics steps run at each frame should depend
    /// of the real-world time elapsed since the last step.
    pub time_dependent_number_of_timesteps: bool,
}

impl Default for RapierConfiguration {
    fn default() -> Self {
        Self {
            gravity: Vector::y() * -9.81,
            scale: 1.0,
            physics_pipeline_active: true,
            query_pipeline_active: true,
            time_dependent_number_of_timesteps: false,
        }
    }
}

// TODO: it may be more efficient to use crossbeam channel.
// However crossbeam channels cause a Segfault (I have not
// investigated how to reproduce this exactly to open an
// issue).
/// A set of queues collecting events emitted by the physics engine.
pub struct EventQueue {
    /// The unbounded contact event queue.
    pub contact_events: ConcurrentQueue<ContactEvent>,
    /// The unbounded intersection event queue.
    pub intersection_events: ConcurrentQueue<IntersectionEvent>,
    /// Are these queues automatically cleared before each simulation timestep?
    pub auto_clear: bool,
}

impl EventQueue {
    /// Creates a new empty event queue.
    pub fn new(auto_clear: bool) -> Self {
        Self {
            contact_events: ConcurrentQueue::unbounded(),
            intersection_events: ConcurrentQueue::unbounded(),
            auto_clear,
        }
    }

    /// Removes all events contained by this queue.
    pub fn clear(&self) {
        while let Ok(_) = self.contact_events.pop() {}
        while let Ok(_) = self.intersection_events.pop() {}
    }
}

impl EventHandler for EventQueue {
    fn handle_intersection_event(&self, event: IntersectionEvent) {
        let _ = self.intersection_events.push(event);
    }

    fn handle_contact_event(&self, event: ContactEvent) {
        let _ = self.contact_events.push(event);
    }
}

/// Difference between simulation and rendering time
#[derive(Default)]
pub struct SimulationToRenderTime {
    /// Difference between simulation and rendering time
    pub diff: f32,
}

/// Custom filters for intersection and contact pairs.
pub struct UserPhysicsHooks {
    /// Custom user defined physics.
    pub hooks: Box<dyn PhysicsHooks>,
}

impl UserPhysicsHooks {
    /// A new interaction pair filter with no custom intersection and contact pair filters.
    pub fn new() -> Self {
        Self {
            hooks: Box::new(()),
        }
    }

    /// Set the user defined physics hooks.
    pub fn hooks(&mut self, hooks: impl PhysicsHooks + 'static) {
        self.hooks = Box::new(hooks) as Box<dyn PhysicsHooks>;
    }
}