Skip to content

Commit

Permalink
Parry convenience query methods
Browse files Browse the repository at this point in the history
  • Loading branch information
Aceeri committed Oct 9, 2023
1 parent 0ea000b commit 5213f38
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 6 deletions.
2 changes: 2 additions & 0 deletions src/geometry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use rapier::prelude::FeatureId;

mod collider;
mod collider_impl;
/// Wrappers around Parry shape queries.
pub mod query;
/// Wrappers around Rapier shapes to access their properties.
pub mod shape_views;

Expand Down
101 changes: 101 additions & 0 deletions src/geometry/query/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use crate::{
parry::{self, shape::Shape, query::{Unsupported, Contact}},
prelude::*,
utils::pos_rot_to_iso,
};

/// Results from [`closest_points`]
pub enum ClosestPoints {
/// The two objects are intersecting.
Intersecting,
/// The two objects are non-intersecting but closer than a given user-defined distance.
WithinMargin(Vect, Vect),
/// The two objects are non-intersecting and further than a given user-defined distance.
Disjoint,
}

use parry::query::closest_points::ClosestPoints as ParryClosestPoints;
impl From<ParryClosestPoints> for ClosestPoints {
fn from(parry: ParryClosestPoints) -> ClosestPoints {
match parry {
ParryClosestPoints::Intersecting => ClosestPoints::Intersecting,
ParryClosestPoints::Disjoint => ClosestPoints::Disjoint,
ParryClosestPoints::WithinMargin(p1, p2) => {
ClosestPoints::WithinMargin(p1.into(), p2.into())
}
}
}
}

/// Computes the pair of closest points between two shapes.
///
/// Returns `ClosestPoints::Disjoint` if the objects are separated by a distance greater than `max_dist`. The result points in `ClosestPoints::WithinMargin` are expressed in world-space.
pub fn closest_points(
pos1: Vect,
rot1: Rot,
shape1: &dyn Shape,
pos2: Vect,
rot2: Rot,
shape2: &dyn Shape,
max_dist: Real,
physics_scale: Real,
) -> Result<ClosestPoints, Unsupported> {
let iso1 = pos_rot_to_iso(pos1, rot1, physics_scale);
let iso2 = pos_rot_to_iso(pos2, rot2, physics_scale);

parry::query::closest_points(&iso1, shape1, &iso2, shape2, max_dist)
.map(|parry| parry.into())
}

/// Computes the minimum distance separating two shapes.
///
/// Returns 0.0 if the objects are touching or penetrating.
pub fn distance(
pos1: Vect,
rot1: Rot,
shape1: &dyn Shape,
pos2: Vect,
rot2: Rot,
shape2: &dyn Shape,
physics_scale: Real,
) -> Result<Real, Unsupported> {
let iso1 = pos_rot_to_iso(pos1, rot1, physics_scale);
let iso2 = pos_rot_to_iso(pos2, rot2, physics_scale);

parry::query::distance(&iso1, shape1, &iso2, shape2)
}

/// Computes one pair of contact points point between two shapes.
///
/// Returns None if the objects are separated by a distance greater than prediction. The result is given in world-space.
pub fn contact(
pos1: Vect,
rot1: Rot,
shape1: &dyn Shape,
pos2: Vect,
rot2: Rot,
shape2: &dyn Shape,
prediction: Real,
physics_scale: Real,
) -> Result<Option<Contact>, Unsupported> {
let iso1 = pos_rot_to_iso(pos1, rot1, physics_scale);
let iso2 = pos_rot_to_iso(pos2, rot2, physics_scale);

parry::query::contact(&iso1, shape1, &iso2, shape2, prediction)
}

/// Tests whether two shapes are intersecting.
pub fn intersection_test(
pos1: Vect,
rot1: Rot,
shape1: &dyn Shape,
pos2: Vect,
rot2: Rot,
shape2: &dyn Shape,
physics_scale: Real,
) -> Result<bool, Unsupported> {
let iso1 = pos_rot_to_iso(pos1, rot1, physics_scale);
let iso2 = pos_rot_to_iso(pos2, rot2, physics_scale);

parry::query::intersection_test(&iso1, shape1, &iso2, shape2)
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ pub mod render;
/// Miscellaneous helper functions.
pub mod utils;

pub use crate::geometry::query;

/// Groups the most often used types.
pub mod prelude {
pub use crate::control::*;
Expand Down
27 changes: 21 additions & 6 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::prelude::*;
use bevy::prelude::Transform;
use rapier::math::{Isometry, Real};

Expand Down Expand Up @@ -31,21 +32,35 @@ pub fn iso_to_transform(iso: &Isometry<Real>, physics_scale: Real) -> Transform
#[cfg(feature = "dim2")]
pub(crate) fn transform_to_iso(transform: &Transform, physics_scale: Real) -> Isometry<Real> {
use bevy::math::Vec3Swizzles;
Isometry::new(
(transform.translation / physics_scale).xy().into(),
pos_rot_to_iso(
transform.translation.xy(),
transform.rotation.to_scaled_axis().z,
physics_scale,
)
}

/// Converts a translation and rotation into a Rapier isometry.
///
/// The translation is divided by the `physics_scale`.
#[cfg(feature = "dim2")]
pub(crate) fn pos_rot_to_iso(pos: Vect, rot: Rot, physics_scale: Real) -> Isometry<Real> {
Isometry::new((pos / physics_scale).into(), rot)
}

/// Converts a Bevy transform to a Rapier isometry.
///
/// The translation is divided by the `physics_scale`.
#[cfg(feature = "dim3")]
pub(crate) fn transform_to_iso(transform: &Transform, physics_scale: Real) -> Isometry<Real> {
Isometry::from_parts(
(transform.translation / physics_scale).into(),
transform.rotation.into(),
)
pos_rot_to_iso(transform.translation, transform.rotation, physics_scale)
}

/// Converts a translation and rotation into a Rapier isometry.
///
/// The translation is divided by the `physics_scale`.
#[cfg(feature = "dim3")]
pub(crate) fn pos_rot_to_iso(pos: Vect, rot: Rot, physics_scale: Real) -> Isometry<Real> {
Isometry::from_parts((pos / physics_scale).into(), rot.into())
}

#[cfg(test)]
Expand Down

0 comments on commit 5213f38

Please sign in to comment.