From 5213f38b2e8a491ae7f0ce7f498352b6dd11a95b Mon Sep 17 00:00:00 2001 From: Aceeri Date: Mon, 9 Oct 2023 09:37:49 -0700 Subject: [PATCH 1/3] Parry convenience query methods --- src/geometry/mod.rs | 2 + src/geometry/query/mod.rs | 101 ++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 + src/utils/mod.rs | 27 +++++++--- 4 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 src/geometry/query/mod.rs diff --git a/src/geometry/mod.rs b/src/geometry/mod.rs index da170406..1b6ad356 100644 --- a/src/geometry/mod.rs +++ b/src/geometry/mod.rs @@ -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; diff --git a/src/geometry/query/mod.rs b/src/geometry/query/mod.rs new file mode 100644 index 00000000..e7f28b39 --- /dev/null +++ b/src/geometry/query/mod.rs @@ -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 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 { + 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 { + 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, 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 { + 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) +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 557cd268..2c25c4b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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::*; diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 5523dac0..e118dc12 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,3 +1,4 @@ +use crate::prelude::*; use bevy::prelude::Transform; use rapier::math::{Isometry, Real}; @@ -31,21 +32,35 @@ pub fn iso_to_transform(iso: &Isometry, physics_scale: Real) -> Transform #[cfg(feature = "dim2")] pub(crate) fn transform_to_iso(transform: &Transform, physics_scale: Real) -> Isometry { 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 { + 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 { - 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 { + Isometry::from_parts((pos / physics_scale).into(), rot.into()) } #[cfg(test)] From 4a38baec44749b13ae565dee6be27e8019ebed64 Mon Sep 17 00:00:00 2001 From: Aceeri Date: Mon, 9 Oct 2023 09:56:57 -0700 Subject: [PATCH 2/3] AsRef for Collider --- src/geometry/collider.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/geometry/collider.rs b/src/geometry/collider.rs index e182e981..7207df68 100644 --- a/src/geometry/collider.rs +++ b/src/geometry/collider.rs @@ -97,6 +97,12 @@ impl<'a> From<&'a Collider> for &'a dyn Shape { } } +impl AsRef for Collider { + fn as_ref(&self) -> &dyn Shape { + &*self.raw + } +} + impl fmt::Debug for Collider { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.as_typed_shape().fmt(f) From c3623dbe49a76ce9f181b9175e3ccc0b1c8393f7 Mon Sep 17 00:00:00 2001 From: Aceeri Date: Mon, 9 Oct 2023 09:58:14 -0700 Subject: [PATCH 3/3] Formatting --- src/geometry/query/mod.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/geometry/query/mod.rs b/src/geometry/query/mod.rs index e7f28b39..b49e99ca 100644 --- a/src/geometry/query/mod.rs +++ b/src/geometry/query/mod.rs @@ -1,5 +1,9 @@ use crate::{ - parry::{self, shape::Shape, query::{Unsupported, Contact}}, + parry::{ + self, + query::{Contact, Unsupported}, + shape::Shape, + }, prelude::*, utils::pos_rot_to_iso, }; @@ -28,7 +32,7 @@ impl From for ClosestPoints { } /// 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, @@ -43,12 +47,11 @@ pub fn closest_points( 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()) + 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, @@ -98,4 +101,4 @@ pub fn intersection_test( let iso2 = pos_rot_to_iso(pos2, rot2, physics_scale); parry::query::intersection_test(&iso1, shape1, &iso2, shape2) -} \ No newline at end of file +}