mod collider;
pub use collider::*;
pub mod broad_phase;
pub mod collider_backend;
#[cfg(feature = "default-collider")]
pub mod contact_query;
pub mod contact_reporting;
pub mod narrow_phase;
use crate::prelude::*;
use bevy::prelude::*;
use indexmap::IndexMap;
#[derive(Resource, Clone, Debug, Default, PartialEq)]
pub struct Collisions(IndexMap<(Entity, Entity), Contacts, fxhash::FxBuildHasher>);
impl Collisions {
pub fn get_internal(&self) -> &IndexMap<(Entity, Entity), Contacts, fxhash::FxBuildHasher> {
&self.0
}
pub fn get_internal_mut(
&mut self,
) -> &mut IndexMap<(Entity, Entity), Contacts, fxhash::FxBuildHasher> {
&mut self.0
}
pub fn get(&self, entity1: Entity, entity2: Entity) -> Option<&Contacts> {
self.0
.get(&(entity1, entity2))
.filter(|contacts| contacts.during_current_frame)
.or_else(|| {
self.0
.get(&(entity2, entity1))
.filter(|contacts| contacts.during_current_frame)
})
}
pub fn get_mut(&mut self, entity1: Entity, entity2: Entity) -> Option<&mut Contacts> {
if self.0.contains_key(&(entity1, entity2)) {
self.0
.get_mut(&(entity1, entity2))
.filter(|contacts| contacts.during_current_frame)
} else {
self.0
.get_mut(&(entity2, entity1))
.filter(|contacts| contacts.during_current_frame)
}
}
pub fn contains(&self, entity1: Entity, entity2: Entity) -> bool {
self.get(entity1, entity2).is_some()
}
pub fn iter(&self) -> impl Iterator<Item = &Contacts> {
self.0
.values()
.filter(|collision| collision.during_current_frame)
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Contacts> {
self.0
.values_mut()
.filter(|collision| collision.during_current_frame)
}
pub fn collisions_with_entity(&self, entity: Entity) -> impl Iterator<Item = &Contacts> {
self.0
.iter()
.filter_map(move |((entity1, entity2), contacts)| {
if contacts.during_current_frame && (*entity1 == entity || *entity2 == entity) {
Some(contacts)
} else {
None
}
})
}
pub fn collisions_with_entity_mut(
&mut self,
entity: Entity,
) -> impl Iterator<Item = &mut Contacts> {
self.0
.iter_mut()
.filter_map(move |((entity1, entity2), contacts)| {
if contacts.during_current_frame && (*entity1 == entity || *entity2 == entity) {
Some(contacts)
} else {
None
}
})
}
pub fn insert_collision_pair(&mut self, contacts: Contacts) -> Option<Contacts> {
self.0
.insert((contacts.entity1, contacts.entity2), contacts)
}
pub fn extend<I: IntoIterator<Item = Contacts>>(&mut self, collisions: I) {
let iter = collisions.into_iter();
let reserve = if self.get_internal().is_empty() {
iter.size_hint().0
} else {
(iter.size_hint().0 + 1) / 2
};
self.get_internal_mut().reserve(reserve);
iter.for_each(move |contacts| {
self.insert_collision_pair(contacts);
});
}
pub fn retain<F>(&mut self, mut keep: F)
where
F: FnMut(&mut Contacts) -> bool,
{
self.0.retain(|_, contacts| keep(contacts));
}
pub fn remove_collision_pair(&mut self, entity1: Entity, entity2: Entity) -> Option<Contacts> {
self.0
.swap_remove(&(entity1, entity2))
.or_else(|| self.0.swap_remove(&(entity2, entity1)))
}
pub fn remove_collisions_with_entity(&mut self, entity: Entity) {
self.retain(|contacts| contacts.entity1 != entity && contacts.entity2 != entity);
}
}
#[derive(Resource, Clone, Debug, Default, Deref, DerefMut, PartialEq)]
pub(super) struct PreviousCollisions(Collisions);
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
pub struct Contacts {
pub entity1: Entity,
pub entity2: Entity,
pub manifolds: Vec<ContactManifold>,
pub during_current_frame: bool,
pub during_current_substep: bool,
pub during_previous_frame: bool,
pub total_normal_impulse: Scalar,
#[doc(alias = "total_friction_impulse")]
pub total_tangent_impulse: Scalar,
}
impl Contacts {
pub fn total_normal_force(&self, delta_time: Scalar) -> Scalar {
self.total_normal_impulse / delta_time
}
#[doc(alias = "total_friction_force")]
pub fn total_tangent_force(&self, delta_time: Scalar) -> Scalar {
self.total_tangent_impulse / delta_time
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
pub struct ContactManifold {
pub contacts: Vec<ContactData>,
pub normal1: Vector,
pub normal2: Vector,
pub index: usize,
}
impl ContactManifold {
pub fn global_normal1(&self, rotation: &Rotation) -> Vector {
rotation.rotate(self.normal1)
}
pub fn global_normal2(&self, rotation: &Rotation) -> Vector {
rotation.rotate(self.normal2)
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
pub struct SingleContact {
pub point1: Vector,
pub point2: Vector,
pub normal1: Vector,
pub normal2: Vector,
pub penetration: Scalar,
}
impl SingleContact {
pub fn new(
point1: Vector,
point2: Vector,
normal1: Vector,
normal2: Vector,
penetration: Scalar,
) -> Self {
Self {
point1,
point2,
normal1,
normal2,
penetration,
}
}
pub fn global_point1(&self, position: &Position, rotation: &Rotation) -> Vector {
position.0 + rotation.rotate(self.point1)
}
pub fn global_point2(&self, position: &Position, rotation: &Rotation) -> Vector {
position.0 + rotation.rotate(self.point2)
}
pub fn global_normal1(&self, rotation: &Rotation) -> Vector {
rotation.rotate(self.normal1)
}
pub fn global_normal2(&self, rotation: &Rotation) -> Vector {
rotation.rotate(self.normal2)
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
pub struct ContactData {
pub point1: Vector,
pub point2: Vector,
pub normal1: Vector,
pub normal2: Vector,
pub penetration: Scalar,
pub normal_impulse: Scalar,
#[doc(alias = "friction_impulse")]
pub tangent_impulse: Scalar,
pub index: usize,
}
impl ContactData {
pub fn new(
point1: Vector,
point2: Vector,
normal1: Vector,
normal2: Vector,
penetration: Scalar,
index: usize,
) -> Self {
Self {
point1,
point2,
normal1,
normal2,
penetration,
normal_impulse: 0.0,
tangent_impulse: 0.0,
index,
}
}
pub fn normal_force(&self, delta_time: Scalar) -> Scalar {
self.normal_impulse / delta_time
}
#[doc(alias = "friction_force")]
pub fn tangent_force(&self, delta_time: Scalar) -> Scalar {
self.tangent_impulse / delta_time
}
pub fn global_point1(&self, position: &Position, rotation: &Rotation) -> Vector {
position.0 + rotation.rotate(self.point1)
}
pub fn global_point2(&self, position: &Position, rotation: &Rotation) -> Vector {
position.0 + rotation.rotate(self.point2)
}
pub fn global_normal1(&self, rotation: &Rotation) -> Vector {
rotation.rotate(self.normal1)
}
pub fn global_normal2(&self, rotation: &Rotation) -> Vector {
rotation.rotate(self.normal2)
}
}