use na::{RealField, Unit};
use crate::bounding_volume::{BoundingVolume, AABB};
use crate::math::{Isometry, Point, Rotation, Translation, Vector};
use crate::pipeline::broad_phase::{BroadPhase, BroadPhasePairFilter, DBVTBroadPhase};
use crate::pipeline::glue::{
self, FirstInterferenceWithRay, InterferencesWithAABB, InterferencesWithPoint,
InterferencesWithRay,
};
use crate::pipeline::narrow_phase::{
ContactAlgorithm, ContactEvents, DefaultContactDispatcher, DefaultProximityDispatcher,
Interaction, InteractionGraph, NarrowPhase, ProximityDetector, ProximityEvents,
TemporaryInteractionIndex,
};
use crate::pipeline::object::{
CollisionGroups, CollisionObject, CollisionObjectSet, CollisionObjectSlab,
CollisionObjectSlabHandle, CollisionObjects, GeometricQueryType,
};
use crate::query::{ContactManifold, DefaultTOIDispatcher, Proximity, Ray, TOIDispatcher, TOI};
use crate::shape::{Shape, ShapeHandle};
pub type BroadPhaseObject<N> = Box<dyn BroadPhase<N, AABB<N>, CollisionObjectSlabHandle>>;
pub struct CollisionWorld<N: RealField, T> {
pub objects: CollisionObjectSlab<N, T>,
pub broad_phase: BroadPhaseObject<N>,
pub narrow_phase: NarrowPhase<N, CollisionObjectSlabHandle>,
pub toi_dispatcher: Box<dyn TOIDispatcher<N>>,
pub interactions: InteractionGraph<N, CollisionObjectSlabHandle>,
pub pair_filters: Option<Box<dyn BroadPhasePairFilter<N, CollisionObjectSlab<N, T>>>>,
}
impl<N: RealField, T> CollisionWorld<N, T> {
pub fn new(margin: N) -> CollisionWorld<N, T> {
let objects = CollisionObjectSlab::new();
let coll_dispatcher = Box::new(DefaultContactDispatcher::new());
let prox_dispatcher = Box::new(DefaultProximityDispatcher::new());
let toi_dispatcher = Box::new(DefaultTOIDispatcher);
let broad_phase =
Box::new(DBVTBroadPhase::<N, AABB<N>, CollisionObjectSlabHandle>::new(margin));
let narrow_phase = NarrowPhase::new(coll_dispatcher, prox_dispatcher);
CollisionWorld {
interactions: InteractionGraph::new(),
objects,
broad_phase,
narrow_phase,
toi_dispatcher,
pair_filters: None,
}
}
pub fn add(
&mut self,
position: Isometry<N>,
shape: ShapeHandle<N>,
collision_groups: CollisionGroups,
query_type: GeometricQueryType<N>,
data: T,
) -> (CollisionObjectSlabHandle, &mut CollisionObject<N, T>) {
let entry = self.objects.objects.vacant_entry();
let handle = CollisionObjectSlabHandle(entry.key());
let (proxy_handle, graph_index) = glue::create_proxies(
handle,
&mut *self.broad_phase,
&mut self.interactions,
&position,
shape.as_ref(),
query_type,
);
let co = CollisionObject::new(
Some(proxy_handle),
Some(graph_index),
position,
shape,
collision_groups,
query_type,
data,
);
(handle, entry.insert(co))
}
pub fn update(&mut self) {
self.narrow_phase.clear_events();
glue::perform_all_pipeline(
&self.objects,
&mut *self.broad_phase,
&mut self.narrow_phase,
&mut self.interactions,
self.pair_filters.as_ref().map(|f| &**f),
);
for (_, co) in self.objects.iter_mut() {
co.clear_update_flags();
}
}
pub fn clear_events(&mut self) {
self.narrow_phase.clear_events();
}
pub fn remove(&mut self, handles: &[CollisionObjectSlabHandle]) {
for handle in handles {
let co = self.objects.remove(*handle);
let graph_index = co.graph_index().expect(crate::NOT_REGISTERED_ERROR);
let proxy_handle = co.proxy_handle().expect(crate::NOT_REGISTERED_ERROR);
if let Some((new_handle, new_index)) = glue::remove_proxies(
&mut *self.broad_phase,
&mut self.interactions,
proxy_handle,
graph_index,
) {
self.objects[new_handle].set_graph_index(Some(new_index))
}
}
}
#[deprecated = "Call directly the method `.set_position` on the collision object."]
pub fn set_position(&mut self, handle: CollisionObjectSlabHandle, pos: Isometry<N>) {
if let Some(co) = self.objects.get_mut(handle) {
co.set_position(pos);
}
}
#[inline]
#[deprecated = "Call directly the method `.set_query_type` on the collision object."]
pub fn set_query_type(
&mut self,
handle: CollisionObjectSlabHandle,
query_type: GeometricQueryType<N>,
) {
if let Some(co) = self.objects.get_mut(handle) {
co.set_query_type(query_type);
}
}
#[inline]
#[deprecated = "Call directly the method `.set_shape` on the collision object."]
pub fn set_shape(&mut self, handle: CollisionObjectSlabHandle, shape: ShapeHandle<N>) {
if let Some(co) = self.objects.get_mut(handle) {
co.set_shape(shape);
}
}
#[deprecated = "Call directly the method `.set_deformations` on the collision object."]
pub fn set_deformations(&mut self, handle: CollisionObjectSlabHandle, coords: &[N]) {
if let Some(co) = self.objects.get_mut(handle) {
co.set_deformations(coords);
}
}
pub fn set_broad_phase_pair_filter<F>(&mut self, filter: Option<F>)
where
F: BroadPhasePairFilter<N, CollisionObjectSlab<N, T>> + 'static,
{
self.pair_filters = filter
.map(|f| Box::new(f) as Box<dyn BroadPhasePairFilter<N, CollisionObjectSlab<N, T>>>);
self.broad_phase.deferred_recompute_all_proximities();
}
pub fn perform_broad_phase(&mut self) {
glue::perform_broad_phase(
&self.objects,
&mut *self.broad_phase,
&mut self.narrow_phase,
&mut self.interactions,
self.pair_filters.as_ref().map(|f| &**f),
)
}
pub fn perform_narrow_phase(&mut self) {
glue::perform_narrow_phase(
&self.objects,
&mut self.narrow_phase,
&mut self.interactions,
)
}
pub fn broad_phase_aabb(&self, handle: CollisionObjectSlabHandle) -> Option<&AABB<N>> {
let co = self.objects.collision_object(handle)?;
let proxy_handle = co.proxy_handle().expect(crate::NOT_REGISTERED_ERROR);
self.broad_phase.proxy(proxy_handle).map(|p| p.0)
}
#[inline]
pub fn collision_objects(&self) -> CollisionObjects<N, T> {
self.objects.iter()
}
#[inline]
pub fn collision_object(
&self,
handle: CollisionObjectSlabHandle,
) -> Option<&CollisionObject<N, T>> {
self.objects.collision_object(handle)
}
#[inline]
pub fn get_mut(
&mut self,
handle: CollisionObjectSlabHandle,
) -> Option<&mut CollisionObject<N, T>> {
self.objects.get_mut(handle)
}
#[inline]
pub fn collision_object_pair_mut(
&mut self,
handle1: CollisionObjectSlabHandle,
handle2: CollisionObjectSlabHandle,
) -> (
Option<&mut CollisionObject<N, T>>,
Option<&mut CollisionObject<N, T>>,
) {
self.objects.get_pair_mut(handle1, handle2)
}
#[inline]
#[deprecated = "Call directly the method `.set_collision_groups` on the collision object."]
pub fn set_collision_groups(
&mut self,
handle: CollisionObjectSlabHandle,
groups: CollisionGroups,
) {
if let Some(co) = self.objects.get_mut(handle) {
co.set_collision_groups(groups);
}
}
#[inline]
pub fn sweep_test<'a>(
&'a self,
shape: &'a dyn Shape<N>,
isometry: &'a Isometry<N>,
direction: &'a Unit<Vector<N>>,
maximum_distance: N,
groups: &'a CollisionGroups,
) -> impl Iterator<Item = (CollisionObjectSlabHandle, TOI<N>)> + 'a {
let a = shape.aabb(&isometry);
let b = shape.aabb(&Isometry::from_parts(
Translation::from(isometry.translation.vector + direction.as_ref() * maximum_distance),
Rotation::identity(),
));
let aabb = a.merged(&b);
let interferences: Vec<_> = self.interferences_with_aabb(&aabb, groups).collect();
let dispatcher = &*self.toi_dispatcher;
interferences.into_iter().filter_map(move |(handle, x)| {
dispatcher
.time_of_impact(
dispatcher,
&isometry,
&direction,
shape,
x.position(),
&Vector::zeros(),
x.shape().as_ref(),
N::max_value(),
N::zero(),
)
.unwrap_or(None)
.map(|toi| (handle, toi))
})
}
#[inline]
pub fn interferences_with_ray<'a, 'b>(
&'a self,
ray: &'b Ray<N>,
max_toi: N,
groups: &'b CollisionGroups,
) -> InterferencesWithRay<'a, 'b, N, CollisionObjectSlab<N, T>> {
glue::interferences_with_ray(&self.objects, &*self.broad_phase, ray, max_toi, groups)
}
#[inline]
pub fn first_interference_with_ray<'a, 'b>(
&'a self,
ray: &'b Ray<N>,
max_toi: N,
groups: &'b CollisionGroups,
) -> Option<FirstInterferenceWithRay<'a, N, CollisionObjectSlab<N, T>>> {
glue::first_interference_with_ray(&self.objects, &*self.broad_phase, ray, max_toi, groups)
}
#[inline]
pub fn interferences_with_point<'a, 'b>(
&'a self,
point: &'b Point<N>,
groups: &'b CollisionGroups,
) -> InterferencesWithPoint<'a, 'b, N, CollisionObjectSlab<N, T>> {
glue::interferences_with_point(&self.objects, &*self.broad_phase, point, groups)
}
#[inline]
pub fn interferences_with_aabb<'a, 'b>(
&'a self,
aabb: &'b AABB<N>,
groups: &'b CollisionGroups,
) -> InterferencesWithAABB<'a, 'b, N, CollisionObjectSlab<N, T>> {
glue::interferences_with_aabb(&self.objects, &*self.broad_phase, aabb, groups)
}
pub fn set_narrow_phase(&mut self, narrow_phase: NarrowPhase<N, CollisionObjectSlabHandle>) {
self.narrow_phase = narrow_phase;
self.broad_phase.deferred_recompute_all_proximities();
}
pub fn interaction_pairs(
&self,
effective_only: bool,
) -> impl Iterator<
Item = (
CollisionObjectSlabHandle,
CollisionObjectSlabHandle,
&Interaction<N>,
),
> {
self.interactions.interaction_pairs(effective_only)
}
pub fn contact_pairs(
&self,
effective_only: bool,
) -> impl Iterator<
Item = (
CollisionObjectSlabHandle,
CollisionObjectSlabHandle,
&ContactAlgorithm<N>,
&ContactManifold<N>,
),
> {
self.interactions.contact_pairs(effective_only)
}
pub fn proximity_pairs(
&self,
effective_only: bool,
) -> impl Iterator<
Item = (
CollisionObjectSlabHandle,
CollisionObjectSlabHandle,
&dyn ProximityDetector<N>,
Proximity,
),
> {
self.interactions.proximity_pairs(effective_only)
}
pub fn interaction_pair(
&self,
handle1: CollisionObjectSlabHandle,
handle2: CollisionObjectSlabHandle,
effective_only: bool,
) -> Option<(
CollisionObjectSlabHandle,
CollisionObjectSlabHandle,
&Interaction<N>,
)> {
let co1 = self.objects.collision_object(handle1)?;
let co2 = self.objects.collision_object(handle2)?;
let id1 = co1.graph_index().expect(crate::NOT_REGISTERED_ERROR);
let id2 = co2.graph_index().expect(crate::NOT_REGISTERED_ERROR);
self.interactions.interaction_pair(id1, id2, effective_only)
}
pub fn contact_pair(
&self,
handle1: CollisionObjectSlabHandle,
handle2: CollisionObjectSlabHandle,
effective_only: bool,
) -> Option<(
CollisionObjectSlabHandle,
CollisionObjectSlabHandle,
&ContactAlgorithm<N>,
&ContactManifold<N>,
)> {
let co1 = self.objects.collision_object(handle1)?;
let co2 = self.objects.collision_object(handle2)?;
let id1 = co1.graph_index().expect(crate::NOT_REGISTERED_ERROR);
let id2 = co2.graph_index().expect(crate::NOT_REGISTERED_ERROR);
self.interactions.contact_pair(id1, id2, effective_only)
}
pub fn proximity_pair(
&self,
handle1: CollisionObjectSlabHandle,
handle2: CollisionObjectSlabHandle,
effective_only: bool,
) -> Option<(
CollisionObjectSlabHandle,
CollisionObjectSlabHandle,
&dyn ProximityDetector<N>,
Proximity,
)> {
let co1 = self.objects.collision_object(handle1)?;
let co2 = self.objects.collision_object(handle2)?;
let id1 = co1.graph_index().expect(crate::NOT_REGISTERED_ERROR);
let id2 = co2.graph_index().expect(crate::NOT_REGISTERED_ERROR);
self.interactions.proximity_pair(id1, id2, effective_only)
}
pub fn interactions_with(
&self,
handle: CollisionObjectSlabHandle,
effective_only: bool,
) -> Option<
impl Iterator<
Item = (
CollisionObjectSlabHandle,
CollisionObjectSlabHandle,
&Interaction<N>,
),
>,
> {
let co = self.objects.collision_object(handle)?;
let id = co.graph_index().expect(crate::NOT_REGISTERED_ERROR);
Some(self.interactions.interactions_with(id, effective_only))
}
pub fn interactions_with_mut(
&mut self,
handle: CollisionObjectSlabHandle,
) -> Option<(
&mut NarrowPhase<N, CollisionObjectSlabHandle>,
impl Iterator<
Item = (
CollisionObjectSlabHandle,
CollisionObjectSlabHandle,
TemporaryInteractionIndex,
&mut Interaction<N>,
),
>,
)> {
let co = self.objects.collision_object(handle)?;
let id = co.graph_index().expect(crate::NOT_REGISTERED_ERROR);
Some((
&mut self.narrow_phase,
self.interactions.interactions_with_mut(id),
))
}
pub fn proximities_with(
&self,
handle: CollisionObjectSlabHandle,
effective_only: bool,
) -> Option<
impl Iterator<
Item = (
CollisionObjectSlabHandle,
CollisionObjectSlabHandle,
&dyn ProximityDetector<N>,
Proximity,
),
>,
> {
let co = self.objects.collision_object(handle)?;
let id = co.graph_index().expect(crate::NOT_REGISTERED_ERROR);
Some(self.interactions.proximities_with(id, effective_only))
}
pub fn contacts_with(
&self,
handle: CollisionObjectSlabHandle,
effective_only: bool,
) -> Option<
impl Iterator<
Item = (
CollisionObjectSlabHandle,
CollisionObjectSlabHandle,
&ContactAlgorithm<N>,
&ContactManifold<N>,
),
>,
> {
let co = self.objects.collision_object(handle)?;
let id = co.graph_index().expect(crate::NOT_REGISTERED_ERROR);
Some(self.interactions.contacts_with(id, effective_only))
}
pub fn collision_objects_interacting_with<'a>(
&'a self,
handle: CollisionObjectSlabHandle,
) -> Option<impl Iterator<Item = CollisionObjectSlabHandle> + 'a> {
let co = self.objects.collision_object(handle)?;
let id = co.graph_index().expect(crate::NOT_REGISTERED_ERROR);
Some(self.interactions.collision_objects_interacting_with(id))
}
pub fn collision_objects_in_contact_with<'a>(
&'a self,
handle: CollisionObjectSlabHandle,
) -> Option<impl Iterator<Item = CollisionObjectSlabHandle> + 'a> {
let co = self.objects.collision_object(handle)?;
let id = co.graph_index().expect(crate::NOT_REGISTERED_ERROR);
Some(self.interactions.collision_objects_in_contact_with(id))
}
pub fn collision_objects_in_proximity_of<'a>(
&'a self,
handle: CollisionObjectSlabHandle,
) -> Option<impl Iterator<Item = CollisionObjectSlabHandle> + 'a> {
let co = self.objects.collision_object(handle)?;
let id = co.graph_index().expect(crate::NOT_REGISTERED_ERROR);
Some(self.interactions.collision_objects_in_proximity_of(id))
}
pub fn contact_events(&self) -> &ContactEvents<CollisionObjectSlabHandle> {
self.narrow_phase.contact_events()
}
pub fn proximity_events(&self) -> &ProximityEvents<CollisionObjectSlabHandle> {
self.narrow_phase.proximity_events()
}
}