pub mod kinematic_body;
pub mod static_body;
pub mod trigger_area;
pub mod contact;
use super::Mask;
use crate::{
object::{kinematic_body::KinematicBody, static_body::StaticBody},
world::aabb::Aabb,
};
use alloc::sync::Arc;
use bvh_arena::VolumeHandle;
use parry::{
math::{Isometry, Real, Vector},
query::{self, Contact, ShapeCastHit, ShapeCastOptions},
shape::Shape,
};
const MASK_ALL: Mask = Mask::MAX;
pub trait Object {
type Payload;
fn set_handle(&mut self, handle: VolumeHandle);
fn unset_handle(&mut self);
fn handle(&self) -> Option<VolumeHandle>;
fn shape(&self) -> &dyn Shape;
fn isometry(&self) -> &Isometry<Real>;
fn aabb(&self) -> Aabb;
fn payload(&self) -> &Self::Payload;
fn payload_mut(&mut self) -> &mut Self::Payload;
#[inline]
fn layer(&self) -> Mask {
MASK_ALL
}
#[inline]
fn mask(&self) -> Mask {
MASK_ALL
}
#[inline]
fn velocity(&self) -> Vector<Real> {
Vector::default()
}
#[inline]
fn as_kinematic(&self) -> Option<&KinematicBody<Self::Payload>> {
None
}
#[inline]
fn as_static(&self) -> Option<&StaticBody<Self::Payload>> {
None
}
}
struct CommonData<P> {
handle: Option<VolumeHandle>,
shape: Arc<dyn Shape>,
isometry: Isometry<Real>,
payload: P,
}
impl<P> CommonData<P> {
#[inline]
pub fn new(shape: Arc<dyn Shape>, isometry: Isometry<Real>, payload: P) -> Self {
CommonData {
handle: None,
shape,
isometry,
payload,
}
}
}
impl<P> Object for CommonData<P> {
type Payload = P;
#[inline]
fn set_handle(&mut self, handle: VolumeHandle) {
self.handle = Some(handle);
}
#[inline]
fn unset_handle(&mut self) {
self.handle = None;
}
#[inline]
fn handle(&self) -> Option<VolumeHandle> {
self.handle
}
#[inline]
fn shape(&self) -> &dyn Shape {
self.shape.as_ref()
}
#[inline]
fn isometry(&self) -> &Isometry<f32> {
&self.isometry
}
#[inline]
fn aabb(&self) -> Aabb {
Aabb::new(self.shape.compute_aabb(&self.isometry), MASK_ALL, MASK_ALL)
}
#[inline]
fn payload(&self) -> &Self::Payload {
&self.payload
}
#[inline]
fn payload_mut(&mut self) -> &mut Self::Payload {
&mut self.payload
}
}
#[inline]
pub fn intersects<A, B>(a: &A, b: &B) -> bool
where
A: Object,
B: Object,
{
query::intersection_test(a.isometry(), a.shape(), b.isometry(), b.shape()).unwrap_or(false)
}
#[inline]
pub fn contacts<A, B>(a: &A, b: &B, prediction: Real) -> Option<Contact>
where
A: Object,
B: Object,
{
query::contact(a.isometry(), a.shape(), b.isometry(), b.shape(), prediction).unwrap_or(None)
}
#[inline]
pub fn collides<A, B>(a: &A, b: &B, options: ShapeCastOptions) -> Option<ShapeCastHit>
where
A: Object,
B: Object,
{
query::cast_shapes(
a.isometry(),
&a.velocity(),
a.shape(),
b.isometry(),
&b.velocity(),
b.shape(),
options,
)
.unwrap_or(None)
}