pub struct TrackedContact<Data> {
pub local_p1: Point<f32>,
pub local_p2: Point<f32>,
pub dist: f32,
pub fid1: PackedFeatureId,
pub fid2: PackedFeatureId,
pub data: Data,
}Expand description
A single contact point between two shapes.
A TrackedContact represents a single point of contact between two shapes, with enough
information to track the contact across multiple frames and identify which geometric
features (vertices, edges, faces) are in contact.
§Understanding Contact Points
Each contact point consists of:
- Two contact positions (one on each shape, in local coordinates)
- A distance value (negative = penetrating, positive = separated)
- Feature IDs that identify which part of each shape is in contact
- Optional user data for tracking contact-specific information
§Local vs World Space
Contact points are stored in local space (the coordinate system of each shape). This is important because:
- Shapes can move and rotate, but local coordinates remain constant
- Contact tracking works by comparing feature IDs and local positions
- To get world-space positions, transform the local points by the shape’s position
§Distance Convention
The dist field uses the following convention:
dist < 0.0: Shapes are penetrating (overlapping). The absolute value is the penetration depth.dist == 0.0: Shapes are exactly touching.dist > 0.0: Shapes are separated. This happens when using contact prediction.
§Example: Basic Contact Query
use parry3d::query::{ContactManifold, TrackedContact};
use parry3d::query::details::contact_manifold_ball_ball;
use parry3d::shape::Ball;
use parry3d::math::Isometry;
// Two balls, one slightly overlapping the other
let ball1 = Ball::new(1.0);
let ball2 = Ball::new(1.0);
let pos12 = Isometry::translation(1.5, 0.0, 0.0); // Overlapping by 0.5
let mut manifold = ContactManifold::<(), ()>::new();
contact_manifold_ball_ball(&pos12, &ball1, &ball2, 0.0, &mut manifold);
if let Some(contact) = manifold.points.first() {
println!("Penetration depth: {}", -contact.dist);
println!("Contact on ball1 (local): {:?}", contact.local_p1);
println!("Contact on ball2 (local): {:?}", contact.local_p2);
}§Example: Converting to World Space
use parry3d::query::{ContactManifold, TrackedContact};
use parry3d::query::details::contact_manifold_ball_ball;
use parry3d::shape::Ball;
use parry3d::math::Isometry;
let ball1 = Ball::new(1.0);
let ball2 = Ball::new(1.0);
// Position shapes in world space
let pos1 = Isometry::translation(0.0, 0.0, 0.0);
let pos2 = Isometry::translation(1.5, 0.0, 0.0);
let pos12 = pos1.inverse() * pos2; // Relative position
let mut manifold = ContactManifold::<(), ()>::new();
contact_manifold_ball_ball(&pos12, &ball1, &ball2, 0.0, &mut manifold);
if let Some(contact) = manifold.points.first() {
// Convert local positions to world space
let world_p1 = pos1 * contact.local_p1;
let world_p2 = pos2 * contact.local_p2;
println!("Contact in world space:");
println!(" On ball1: {:?}", world_p1);
println!(" On ball2: {:?}", world_p2);
}§Feature IDs
The fid1 and fid2 fields identify which geometric features are in contact:
- For a ball: Always the face (surface)
- For a box: Could be a vertex, edge, or face
- For a triangle: Could be a vertex, edge, or the face
These IDs are used to track contacts across frames. If the same feature IDs appear in consecutive frames, it’s likely the same physical contact point.
Fields§
§local_p1: Point<f32>The contact point in the local-space of the first shape.
This is the point on the first shape’s surface (or interior if penetrating) that is closest to or in contact with the second shape.
local_p2: Point<f32>The contact point in the local-space of the second shape.
This is the point on the second shape’s surface (or interior if penetrating) that is closest to or in contact with the first shape.
dist: f32The signed distance between the two contact points.
- Negative values indicate penetration (shapes are overlapping)
- Positive values indicate separation (used with contact prediction)
- Zero means the shapes are exactly touching
The magnitude represents the distance along the contact normal.
fid1: PackedFeatureIdThe feature ID of the first shape involved in the contact.
This identifies which geometric feature (vertex, edge, or face) of the first shape is involved in this contact. Used for contact tracking across frames.
fid2: PackedFeatureIdThe feature ID of the second shape involved in the contact.
This identifies which geometric feature (vertex, edge, or face) of the second shape is involved in this contact. Used for contact tracking across frames.
data: DataUser-data associated to this contact.
This can be used to store any additional information you need to track per-contact, such as:
- Accumulated impulses for warm-starting in physics solvers
- Contact age or lifetime
- Material properties or friction state
- Custom identifiers or flags
Implementations§
Source§impl<Data: Default + Copy> TrackedContact<Data>
impl<Data: Default + Copy> TrackedContact<Data>
Sourcepub fn new(
local_p1: Point<f32>,
local_p2: Point<f32>,
fid1: PackedFeatureId,
fid2: PackedFeatureId,
dist: f32,
) -> Self
pub fn new( local_p1: Point<f32>, local_p2: Point<f32>, fid1: PackedFeatureId, fid2: PackedFeatureId, dist: f32, ) -> Self
Creates a new tracked contact.
§Arguments
local_p1- Contact point on the first shape (in its local space)local_p2- Contact point on the second shape (in its local space)fid1- Feature ID of the first shape (which part is in contact)fid2- Feature ID of the second shape (which part is in contact)dist- Signed distance between the contact points (negative = penetrating)
The contact data is initialized to its default value.
§Example
use parry3d::query::TrackedContact;
use parry3d::shape::PackedFeatureId;
use parry3d::math::Point;
let contact = TrackedContact::<()>::new(
Point::new(1.0, 0.0, 0.0), // Point on shape 1
Point::new(-1.0, 0.0, 0.0), // Point on shape 2
PackedFeatureId::face(0), // Face 0 of shape 1
PackedFeatureId::face(0), // Face 0 of shape 2
-0.1, // Penetration depth of 0.1
);
assert_eq!(contact.dist, -0.1);Sourcepub fn flipped(
local_p1: Point<f32>,
local_p2: Point<f32>,
fid1: PackedFeatureId,
fid2: PackedFeatureId,
dist: f32,
flipped: bool,
) -> Self
pub fn flipped( local_p1: Point<f32>, local_p2: Point<f32>, fid1: PackedFeatureId, fid2: PackedFeatureId, dist: f32, flipped: bool, ) -> Self
Creates a new tracked contact where its input may need to be flipped.
Sourcepub fn copy_geometry_from(&mut self, contact: Self)
pub fn copy_geometry_from(&mut self, contact: Self)
Copy to self the geometric information from contact.
Trait Implementations§
Source§impl<Data: Clone> Clone for TrackedContact<Data>
impl<Data: Clone> Clone for TrackedContact<Data>
Source§fn clone(&self) -> TrackedContact<Data>
fn clone(&self) -> TrackedContact<Data>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<Data: Debug> Debug for TrackedContact<Data>
impl<Data: Debug> Debug for TrackedContact<Data>
impl<Data: Copy> Copy for TrackedContact<Data>
Auto Trait Implementations§
impl<Data> Freeze for TrackedContact<Data>where
Data: Freeze,
impl<Data> RefUnwindSafe for TrackedContact<Data>where
Data: RefUnwindSafe,
impl<Data> Send for TrackedContact<Data>where
Data: Send,
impl<Data> Sync for TrackedContact<Data>where
Data: Sync,
impl<Data> Unpin for TrackedContact<Data>where
Data: Unpin,
impl<Data> UnwindSafe for TrackedContact<Data>where
Data: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.