use std::mem; use std::vec::IntoIter; use math::{Isometry, Point}; use geometry::bounding_volume::{self, BoundingVolume, AABB}; use geometry::shape::ShapeHandle; use geometry::query::{PointQuery, Ray, RayCast, RayIntersection}; use narrow_phase::{ContactPairs, Contacts, DefaultContactDispatcher, DefaultNarrowPhase, DefaultProximityDispatcher, NarrowPhase, ProximityPairs}; use broad_phase::{BroadPhase, BroadPhasePairFilter, BroadPhasePairFilters, DBVTBroadPhase, ProxyHandle}; use world::{CollisionGroups, CollisionGroupsPairFilter, CollisionObject, CollisionObjectHandle, CollisionObjectSlab, CollisionObjects, GeometricQueryType}; use events::{ContactEvent, ContactEvents, ProximityEvents}; /// Type of the narrow phase trait-object used by the collision world. pub type NarrowPhaseObject
= Box = Box ,
broad_phase: BroadPhaseObject ,
narrow_phase: Box ,
timestamp: usize, // FIXME: allow modification of the other properties too.
}
impl {
/// Creates a new collision world.
// FIXME: use default values for `margin` and allow its modification by the user ?
pub fn new(margin: P::Real) -> CollisionWorld {
let objects = CollisionObjectSlab::new();
let coll_dispatcher = Box::new(DefaultContactDispatcher::new());
let prox_dispatcher = Box::new(DefaultProximityDispatcher::new());
let broad_phase = Box::new(DBVTBroadPhase:: , CollisionObjectHandle>::new(
margin,
));
let narrow_phase = DefaultNarrowPhase::new(coll_dispatcher, prox_dispatcher);
CollisionWorld {
contact_events: ContactEvents::new(),
proximity_events: ProximityEvents::new(),
objects: objects,
broad_phase: broad_phase,
narrow_phase: Box::new(narrow_phase),
pair_filters: BroadPhasePairFilters::new(),
timestamp: 0,
}
}
/// Adds a collision object to the world.
pub fn add(
&mut self,
position: M,
shape: ShapeHandle ,
collision_groups: CollisionGroups,
query_type: GeometricQueryType ,
{
self.pair_filters
.register_collision_filter(name, Box::new(filter));
self.broad_phase.deferred_recompute_all_proximities();
}
/// Removes the pair filter named `name`.
pub fn unregister_broad_phase_pair_filter(&mut self, name: &str) {
if self.pair_filters.unregister_collision_filter(name) {
self.broad_phase.deferred_recompute_all_proximities();
}
}
/// Executes the broad phase of the collision detection pipeline.
pub fn perform_broad_phase(&mut self) {
let bf = &mut self.broad_phase;
let nf = &mut self.narrow_phase;
let sig = &mut self.contact_events;
let prox = &mut self.proximity_events;
let filts = &self.pair_filters;
let objs = &self.objects;
bf.update(
// Filter:
&mut |b1, b2| CollisionWorld::filter_collision(filts, objs, *b1, *b2),
// Handler:
&mut |b1, b2, started| nf.handle_interaction(sig, prox, objs, *b1, *b2, started),
);
}
/// Executes the narrow phase of the collision detection pipeline.
pub fn perform_narrow_phase(&mut self) {
self.narrow_phase.update(
&self.objects,
&mut self.contact_events,
&mut self.proximity_events,
self.timestamp,
);
self.timestamp = self.timestamp + 1;
}
/// Sets a new narrow phase and returns the previous one.
///
/// Keep in mind that modifying the narrow-pase will have a non-trivial overhead during the
/// next update as it will force re-detection of all collision pairs and their associated
/// contacts.
pub fn set_narrow_phase(
&mut self,
narrow_phase: Box {
self.narrow_phase.contact_pairs(&self.objects)
}
/// Iterates through all the proximity pairs detected since the last update.
#[inline]
pub fn proximity_pairs(&self) -> ProximityPairs {
self.narrow_phase.proximity_pairs(&self.objects)
}
/// Iterates through every contact detected since the last update.
#[inline]
pub fn contacts(&self) -> Contacts {
self.narrow_phase.contact_pairs(&self.objects).contacts()
}
/// Iterates through all collision objects.
#[inline]
pub fn collision_objects(&self) -> CollisionObjects {
self.objects.iter()
}
/// Returns a reference to the collision object identified by its handle.
#[inline]
pub fn collision_object(
&self,
handle: CollisionObjectHandle,
) -> Option<&CollisionObject > {
self.objects.get(handle)
}
/// Returns a mutable reference to the collision object identified by its handle.
#[inline]
pub fn collision_object_mut(
&mut self,
handle: CollisionObjectHandle,
) -> Option<&mut CollisionObject > {
self.objects.get_mut(handle)
}
/// Computes the interferences between every rigid bodies on this world and a ray.
#[inline]
pub fn interferences_with_ray<'a, 'b>(
&'a self,
ray: &'b Ray ,
groups: &'b CollisionGroups,
) -> InterferencesWithRay<'a, 'b, P, M, T> {
// FIXME: avoid allocation.
let mut handles = Vec::new();
self.broad_phase.interferences_with_ray(ray, &mut handles);
InterferencesWithRay {
ray: ray,
groups: groups,
objects: &self.objects,
handles: handles.into_iter(),
}
}
/// Computes the interferences between every rigid bodies of a given broad phase, and a point.
#[inline]
pub fn interferences_with_point<'a, 'b>(
&'a self,
point: &'b P,
groups: &'b CollisionGroups,
) -> InterferencesWithPoint<'a, 'b, P, M, T> {
// FIXME: avoid allocation.
let mut handles = Vec::new();
self.broad_phase
.interferences_with_point(point, &mut handles);
InterferencesWithPoint {
point: point,
groups: groups,
objects: &self.objects,
handles: handles.into_iter(),
}
}
/// Computes the interferences between every rigid bodies of a given broad phase, and a aabb.
#[inline]
pub fn interferences_with_aabb<'a, 'b>(
&'a self,
aabb: &'b AABB ,
groups: &'b CollisionGroups,
) -> InterferencesWithAABB<'a, 'b, P, M, T> {
// FIXME: avoid allocation.
let mut handles = Vec::new();
self.broad_phase
.interferences_with_bounding_volume(aabb, &mut handles);
InterferencesWithAABB {
groups: groups,
objects: &self.objects,
handles: handles.into_iter(),
}
}
/// The contact events pool.
pub fn contact_events(&self) -> &ContactEvents {
&self.contact_events
}
/// The proximity events pool.
pub fn proximity_events(&self) -> &ProximityEvents {
&self.proximity_events
}
// Filters by group and by the user-provided callback.
#[inline]
fn filter_collision(
filters: &BroadPhasePairFilters ,
objects: &CollisionObjectSlab ,
handle1: CollisionObjectHandle,
handle2: CollisionObjectHandle,
) -> bool {
let o1 = &objects[handle1];
let o2 = &objects[handle2];
let filter_by_groups = CollisionGroupsPairFilter;
filter_by_groups.is_pair_valid(o1, o2) && filters.is_pair_valid(o1, o2)
}
}
/// Iterator through all the objects on the world that intersect a specific ray.
pub struct InterferencesWithRay<'a, 'b, P: 'a + Point, M: 'a, T: 'a> {
ray: &'b Ray ,
objects: &'a CollisionObjectSlab ,
groups: &'b CollisionGroups,
handles: IntoIter<&'a CollisionObjectHandle>,
}
impl<'a, 'b, P: Point, M: Isometry , T> Iterator for InterferencesWithRay<'a, 'b, P, M, T> {
type Item = (&'a CollisionObject , RayIntersection ,
groups: &'b CollisionGroups,
handles: IntoIter<&'a CollisionObjectHandle>,
}
impl<'a, 'b, P: Point, M: Isometry , T> Iterator for InterferencesWithPoint<'a, 'b, P, M, T> {
type Item = &'a CollisionObject ;
#[inline]
fn next(&mut self) -> Option ,
groups: &'b CollisionGroups,
handles: IntoIter<&'a CollisionObjectHandle>,
}
impl<'a, 'b, P: Point, M, T> Iterator for InterferencesWithAABB<'a, 'b, P, M, T> {
type Item = &'a CollisionObject ;
#[inline]
fn next(&mut self) -> Option