aboutsummaryrefslogtreecommitdiff
path: root/src/pipeline/collision_pipeline.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/pipeline/collision_pipeline.rs')
-rw-r--r--src/pipeline/collision_pipeline.rs111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/pipeline/collision_pipeline.rs b/src/pipeline/collision_pipeline.rs
new file mode 100644
index 0000000..0184295
--- /dev/null
+++ b/src/pipeline/collision_pipeline.rs
@@ -0,0 +1,111 @@
+//! Physics pipeline structures.
+
+use crate::dynamics::{JointSet, RigidBody, RigidBodyHandle, RigidBodySet};
+use crate::geometry::{BroadPhase, BroadPhasePairEvent, ColliderPair, ColliderSet, NarrowPhase};
+use crate::pipeline::EventHandler;
+
+/// The collision pipeline, responsible for performing collision detection between colliders.
+///
+/// This structure only contains temporary data buffers. It can be dropped and replaced by a fresh
+/// copy at any time. For performance reasons it is recommended to reuse the same physics pipeline
+/// instance to benefit from the cached data.
+// NOTE: this contains only workspace data, so there is no point in making this serializable.
+pub struct CollisionPipeline {
+ broadphase_collider_pairs: Vec<ColliderPair>,
+ broad_phase_events: Vec<BroadPhasePairEvent>,
+ empty_joints: JointSet,
+}
+
+#[allow(dead_code)]
+fn check_pipeline_send_sync() {
+ fn do_test<T: Sync>() {}
+ do_test::<CollisionPipeline>();
+}
+
+impl CollisionPipeline {
+ /// Initializes a new physics pipeline.
+ pub fn new() -> CollisionPipeline {
+ CollisionPipeline {
+ broadphase_collider_pairs: Vec::new(),
+ broad_phase_events: Vec::new(),
+ empty_joints: JointSet::new(),
+ }
+ }
+
+ /// Executes one step of the collision detection.
+ pub fn step(
+ &mut self,
+ prediction_distance: f32,
+ broad_phase: &mut BroadPhase,
+ narrow_phase: &mut NarrowPhase,
+ bodies: &mut RigidBodySet,
+ colliders: &mut ColliderSet,
+ events: &dyn EventHandler,
+ ) {
+ bodies.maintain_active_set();
+ self.broadphase_collider_pairs.clear();
+
+ broad_phase.update_aabbs(prediction_distance, bodies, colliders);
+
+ self.broad_phase_events.clear();
+ broad_phase.find_pairs(&mut self.broad_phase_events);
+
+ narrow_phase.register_pairs(colliders, &self.broad_phase_events, events);
+
+ narrow_phase.compute_contacts(prediction_distance, bodies, colliders, events);
+ narrow_phase.compute_proximities(prediction_distance, bodies, colliders, events);
+
+ bodies.update_active_set_with_contacts(
+ colliders,
+ narrow_phase.contact_graph(),
+ self.empty_joints.joint_graph(),
+ 0,
+ );
+
+ // // Update kinematic bodies velocities.
+ // bodies.foreach_active_kinematic_body_mut_internal(|_, body| {
+ // body.compute_velocity_from_predicted_position(integration_parameters.inv_dt());
+ // });
+
+ // Update colliders positions and kinematic bodies positions.
+ bodies.foreach_active_body_mut_internal(|_, rb| {
+ if rb.is_kinematic() {
+ rb.position = rb.predicted_position;
+ } else {
+ rb.update_predicted_position(0.0);
+ }
+
+ for handle in &rb.colliders {
+ let collider = &mut colliders[*handle];
+ collider.position = rb.position * collider.delta;
+ collider.predicted_position = rb.predicted_position * collider.delta;
+ }
+ });
+
+ bodies.modified_inactive_set.clear();
+ }
+
+ /// Remove a rigid-body and all its associated data.
+ pub fn remove_rigid_body(
+ &mut self,
+ handle: RigidBodyHandle,
+ broad_phase: &mut BroadPhase,
+ narrow_phase: &mut NarrowPhase,
+ bodies: &mut RigidBodySet,
+ colliders: &mut ColliderSet,
+ ) -> Option<RigidBody> {
+ // Remove the body.
+ let body = bodies.remove_internal(handle)?;
+
+ // Remove this rigid-body from the broad-phase and narrow-phase.
+ broad_phase.remove_colliders(&body.colliders, colliders);
+ narrow_phase.remove_colliders(&body.colliders, colliders, bodies);
+
+ // Remove all colliders attached to this body.
+ for collider in &body.colliders {
+ colliders.remove_internal(*collider);
+ }
+
+ Some(body)
+ }
+}