pub trait QueryDispatcher: Send + Sync {
// Required methods
fn intersection_test(
&self,
pos12: &Isometry<f32>,
g1: &dyn Shape,
g2: &dyn Shape,
) -> Result<bool, Unsupported>;
fn distance(
&self,
pos12: &Isometry<f32>,
g1: &dyn Shape,
g2: &dyn Shape,
) -> Result<f32, Unsupported>;
fn contact(
&self,
pos12: &Isometry<f32>,
g1: &dyn Shape,
g2: &dyn Shape,
prediction: f32,
) -> Result<Option<Contact>, Unsupported>;
fn closest_points(
&self,
pos12: &Isometry<f32>,
g1: &dyn Shape,
g2: &dyn Shape,
max_dist: f32,
) -> Result<ClosestPoints, Unsupported>;
fn cast_shapes(
&self,
pos12: &Isometry<f32>,
local_vel12: &Vector<f32>,
g1: &dyn Shape,
g2: &dyn Shape,
options: ShapeCastOptions,
) -> Result<Option<ShapeCastHit>, Unsupported>;
fn cast_shapes_nonlinear(
&self,
motion1: &NonlinearRigidMotion,
g1: &dyn Shape,
motion2: &NonlinearRigidMotion,
g2: &dyn Shape,
start_time: f32,
end_time: f32,
stop_at_penetration: bool,
) -> Result<Option<ShapeCastHit>, Unsupported>;
// Provided method
fn chain<U: QueryDispatcher>(
self,
other: U,
) -> QueryDispatcherChain<Self, U>
where Self: Sized { ... }
}Expand description
Dispatcher for pairwise geometric queries between shapes.
This is the core trait for performing geometric queries (distance, intersection, contact, etc.) between pairs of shapes in Parry. It provides a uniform interface for querying different shape combinations.
§Purpose
The QueryDispatcher trait serves as an abstraction layer that:
-
Decouples query algorithms from shape types: Different shape pairs may require different algorithms (e.g., sphere-sphere uses simple math, while convex-convex uses GJK/EPA).
-
Enables extensibility: You can implement custom dispatchers to add support for custom shape types or specialized algorithms without modifying Parry’s core code.
-
Provides fallback mechanisms: Dispatchers can be chained together using
chain(), allowing graceful fallback when a query is not supported.
§The pos12 Parameter Convention
All query methods in this trait take a pos12 parameter, which represents the relative
position of shape 2 (g2) in shape 1’s (g1) local coordinate frame:
pos12 = pos1.inverse() * pos2This convention is used because:
- It reduces redundant transformations during query execution
- Many algorithms naturally work in one shape’s local space
- It’s more efficient than passing two separate world-space positions
When using the high-level query functions, this transformation is done automatically.
§Query Methods Overview
The trait provides several categories of queries:
§Basic Queries
intersection_test: Boolean intersection check (fastest)distance: Minimum separating distanceclosest_points: Pair of closest pointscontact: Contact point with penetration depth
§Motion Queries (Time of Impact)
cast_shapes: Linear motion (translation only)cast_shapes_nonlinear: Nonlinear motion (translation + rotation)
§Thread Safety
Query dispatchers must be Send + Sync because they’re often shared across threads in:
- Parallel collision detection
- Physics simulations with multi-threaded broad phase
- Game engines with parallel scene queries
Ensure your custom dispatcher implementations are thread-safe or use appropriate synchronization.
§Error Handling with Unsupported
All query methods return Result<T, Unsupported>. The Unsupported error indicates:
- The dispatcher doesn’t know how to handle the given shape pair
- The shapes don’t support this type of query
- The query is mathematically undefined for these shapes
When chaining dispatchers with chain(), returning Unsupported causes the
next dispatcher in the chain to be tried.
§Example: Using the Default Dispatcher
use parry3d::query::{QueryDispatcher, DefaultQueryDispatcher};
use parry3d::shape::{Ball, Cuboid};
use parry3d::na::{Isometry3, Vector3};
let dispatcher = DefaultQueryDispatcher;
let ball = Ball::new(1.0);
let cuboid = Cuboid::new(Vector3::new(2.0, 2.0, 2.0));
let pos1 = Isometry3::identity();
let pos2 = Isometry3::translation(5.0, 0.0, 0.0);
let pos12 = pos1.inv_mul(&pos2);
// Test intersection
let intersects = dispatcher.intersection_test(&pos12, &ball, &cuboid).unwrap();
// Compute distance
let dist = dispatcher.distance(&pos12, &ball, &cuboid).unwrap();
println!("Intersects: {}, Distance: {}", intersects, dist);§Example: Chaining Dispatchers
use parry3d::query::{QueryDispatcher, DefaultQueryDispatcher};
struct MyCustomDispatcher;
impl QueryDispatcher for MyCustomDispatcher {
fn distance(
&self,
pos12: &Isometry<Real>,
g1: &dyn Shape,
g2: &dyn Shape,
) -> Result<Real, Unsupported> {
// Handle custom shape types
if let Some(my_shape) = g1.as_any().downcast_ref::<MyShape>() {
// ... custom distance computation
Ok(computed_distance)
} else {
// Don't know how to handle this, let the next dispatcher try
Err(Unsupported)
}
}
// ... implement other methods
}
// Chain custom dispatcher with default as fallback
let dispatcher = MyCustomDispatcher.chain(DefaultQueryDispatcher);
// Now all queries try custom dispatcher first, then default
let dist = dispatcher.distance(&pos12, shape1, shape2)?;§See Also
DefaultQueryDispatcher: The built-in implementation used by ParryPersistentQueryDispatcher: Extended trait for contact manifold queriescrate::query: High-level query functions that use dispatchers internally
Required Methods§
Sourcefn intersection_test(
&self,
pos12: &Isometry<f32>,
g1: &dyn Shape,
g2: &dyn Shape,
) -> Result<bool, Unsupported>
fn intersection_test( &self, pos12: &Isometry<f32>, g1: &dyn Shape, g2: &dyn Shape, ) -> Result<bool, Unsupported>
Tests whether two shapes are intersecting.
Sourcefn distance(
&self,
pos12: &Isometry<f32>,
g1: &dyn Shape,
g2: &dyn Shape,
) -> Result<f32, Unsupported>
fn distance( &self, pos12: &Isometry<f32>, g1: &dyn Shape, g2: &dyn Shape, ) -> Result<f32, Unsupported>
Computes the minimum distance separating two shapes.
Returns 0.0 if the objects are touching or penetrating.
Sourcefn contact(
&self,
pos12: &Isometry<f32>,
g1: &dyn Shape,
g2: &dyn Shape,
prediction: f32,
) -> Result<Option<Contact>, Unsupported>
fn contact( &self, pos12: &Isometry<f32>, g1: &dyn Shape, g2: &dyn Shape, prediction: f32, ) -> Result<Option<Contact>, Unsupported>
Computes one pair of contact points point between two shapes.
Returns None if the objects are separated by a distance greater than prediction.
Sourcefn closest_points(
&self,
pos12: &Isometry<f32>,
g1: &dyn Shape,
g2: &dyn Shape,
max_dist: f32,
) -> Result<ClosestPoints, Unsupported>
fn closest_points( &self, pos12: &Isometry<f32>, g1: &dyn Shape, g2: &dyn Shape, max_dist: f32, ) -> Result<ClosestPoints, Unsupported>
Computes the pair of closest points between two shapes.
Returns ClosestPoints::Disjoint if the objects are separated by a distance greater than max_dist.
Sourcefn cast_shapes(
&self,
pos12: &Isometry<f32>,
local_vel12: &Vector<f32>,
g1: &dyn Shape,
g2: &dyn Shape,
options: ShapeCastOptions,
) -> Result<Option<ShapeCastHit>, Unsupported>
fn cast_shapes( &self, pos12: &Isometry<f32>, local_vel12: &Vector<f32>, g1: &dyn Shape, g2: &dyn Shape, options: ShapeCastOptions, ) -> Result<Option<ShapeCastHit>, Unsupported>
Computes the smallest time when two shapes under translational movement are separated by a
distance smaller or equal to distance.
Returns 0.0 if the objects are touching or penetrating.
§Parameters
pos12: the position of the second shape relative to the first shape.local_vel12: the relative velocity between the two shapes, expressed in the local-space of the first shape. In other world:pos1.inverse() * (vel2 - vel1).g1: the first shape involved in the shape-cast.g2: the second shape involved in the shape-cast.target_dist: a hit will be returned as soon as the two shapes get closer thantarget_dist.max_time_of_impact: the maximum allowed travel time. This method returnsNoneif the time-of-impact detected is theater than this value.
Sourcefn cast_shapes_nonlinear(
&self,
motion1: &NonlinearRigidMotion,
g1: &dyn Shape,
motion2: &NonlinearRigidMotion,
g2: &dyn Shape,
start_time: f32,
end_time: f32,
stop_at_penetration: bool,
) -> Result<Option<ShapeCastHit>, Unsupported>
fn cast_shapes_nonlinear( &self, motion1: &NonlinearRigidMotion, g1: &dyn Shape, motion2: &NonlinearRigidMotion, g2: &dyn Shape, start_time: f32, end_time: f32, stop_at_penetration: bool, ) -> Result<Option<ShapeCastHit>, Unsupported>
Computes the smallest time of impact of two shapes under translational and rotational movement.
§Parameters
motion1- The motion of the first shape.g1- The first shape involved in the query.motion2- The motion of the second shape.g2- The second shape involved in the query.start_time- The starting time of the interval where the motion takes place.end_time- The end time of the interval where the motion takes place.stop_at_penetration- If the casted shape starts in a penetration state with any collider, two results are possible. Ifstop_at_penetrationistruethen, the result will have atime_of_impactequal tostart_time. Ifstop_at_penetrationisfalsethen the nonlinear shape-casting will see if further motion wrt. the penetration normal would result in tunnelling. If it does not (i.e. we have a separating velocity along that normal) then the nonlinear shape-casting will attempt to find another impact, at a time> start_timethat could result in tunnelling.
Provided Methods§
Sourcefn chain<U: QueryDispatcher>(self, other: U) -> QueryDispatcherChain<Self, U>where
Self: Sized,
fn chain<U: QueryDispatcher>(self, other: U) -> QueryDispatcherChain<Self, U>where
Self: Sized,
Construct a QueryDispatcher that falls back on other for cases not handled by self