Struct DefaultQueryDispatcher

Source
pub struct DefaultQueryDispatcher;
Expand description

The default query dispatcher implementation provided by Parry.

This dispatcher handles all the built-in shape types and automatically selects the most appropriate algorithm for each shape pair combination. It is used internally by all the free functions in the crate::query module.

§What It Does

DefaultQueryDispatcher implements efficient query dispatch logic that:

  1. Examines shape types using runtime type checking (as_ball(), as_cuboid(), etc.)
  2. Selects specialized algorithms for specific shape pairs (e.g., ball-ball, cuboid-cuboid)
  3. Falls back to general algorithms when specialized versions aren’t available (e.g., GJK/EPA for support map shapes)
  4. Handles composite shapes by decomposing them and performing multiple sub-queries

§Supported Shape Combinations

The dispatcher provides optimized implementations for many shape pairs, including:

§Basic Shapes

  • Ball-Ball: Analytical formulas (fastest)
  • Ball-Convex: Specialized algorithms
  • Cuboid-Cuboid: SAT-based algorithms
  • Segment-Segment: Direct geometric calculations

§Support Map Shapes

For shapes implementing the SupportMap trait (most convex shapes):

  • Uses GJK algorithm for distance and intersection queries
  • Uses EPA algorithm for penetration depth when shapes overlap

§Composite Shapes

Handles complex shapes by decomposing them:

  • TriMesh: Queries individual triangles using BVH acceleration
  • Compound: Queries component shapes
  • HeightField: Efficiently queries relevant cells
  • Voxels: Queries occupied voxels

§Special Cases

  • HalfSpace: Infinite planes with specialized handling
  • Rounded shapes: Automatically accounts for border radius

§When to Use

You typically don’t need to create DefaultQueryDispatcher explicitly. The free functions in crate::query use it automatically:

use parry3d::query;
use parry3d::shape::Ball;
use parry3d::na::Isometry3;

let ball1 = Ball::new(1.0);
let ball2 = Ball::new(1.0);
let pos1 = Isometry3::identity();
let pos2 = Isometry3::translation(5.0, 0.0, 0.0);

// This uses DefaultQueryDispatcher internally
let distance = query::distance(&pos1, &ball1, &pos2, &ball2);

However, you might use it explicitly when:

  • Creating a dispatcher chain with custom dispatchers
  • Implementing custom query logic that needs to delegate to default behavior
  • Building a custom collision detection pipeline

§Example: Direct Usage

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(1.0, 1.0, 1.0));

let pos1 = Isometry3::identity();
let pos2 = Isometry3::translation(3.0, 0.0, 0.0);
let pos12 = pos1.inv_mul(&pos2);

// Query intersection
let intersects = dispatcher.intersection_test(&pos12, &ball, &cuboid)
    .expect("This shape pair is supported");

// Query distance
let dist = dispatcher.distance(&pos12, &ball, &cuboid)
    .expect("This shape pair is supported");

println!("Distance: {}, Intersecting: {}", dist, intersects);

§Example: Chaining with Custom Dispatcher

use parry3d::query::{QueryDispatcher, DefaultQueryDispatcher};

struct MyCustomDispatcher;
// ... implement QueryDispatcher for MyCustomDispatcher ...

// Try custom dispatcher first, fall back to default
let dispatcher = MyCustomDispatcher.chain(DefaultQueryDispatcher);

// Now queries will use your custom logic when applicable,
// and Parry's default logic otherwise
let dist = dispatcher.distance(&pos12, shape1, shape2)?;

§Algorithm Selection Strategy

The dispatcher follows this priority order when selecting algorithms:

  1. Exact shape type matching: Ball-Ball, Cuboid-Cuboid, etc.
  2. Specialized asymmetric pairs: Ball-ConvexShape, HalfSpace-SupportMap, etc.
  3. Support map fallback: Any SupportMap-SupportMap pair uses GJK/EPA
  4. Composite shape decomposition: TriMesh, Compound, HeightField, Voxels
  5. Unsupported: Returns Err(Unsupported) if no algorithm exists

§Performance Characteristics

  • Type checking overhead: Minimal - uses efficient trait object downcasting
  • Specialized algorithms: O(1) for ball-ball, O(log n) to O(n) for composite shapes
  • GJK/EPA: Iterative algorithms that typically converge in 5-20 iterations
  • Composite shapes: Use BVH for O(log n) acceleration of sub-queries

§Thread Safety

DefaultQueryDispatcher is Send + Sync and has no internal state, making it safe to share across threads. You can use a single instance for all queries in a parallel collision detection system.

§Limitations

Some shape pairs are not supported and will return Err(Unsupported):

  • Custom shapes not implementing required traits (e.g., not convex, no support map)
  • Some asymmetric pairs that lack specialized implementations
  • Certain combinations involving custom user shapes

When encountering Unsupported, you can implement a custom dispatcher to handle these cases.

§See Also

Trait Implementations§

Source§

impl Clone for DefaultQueryDispatcher

Source§

fn clone(&self) -> DefaultQueryDispatcher

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for DefaultQueryDispatcher

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<ManifoldData, ContactData> PersistentQueryDispatcher<ManifoldData, ContactData> for DefaultQueryDispatcher
where ManifoldData: Default + Clone, ContactData: Default + Copy,

Source§

fn contact_manifolds( &self, pos12: &Isometry<f32>, shape1: &dyn Shape, shape2: &dyn Shape, prediction: f32, manifolds: &mut Vec<ContactManifold<ManifoldData, ContactData>>, workspace: &mut Option<ContactManifoldsWorkspace>, ) -> Result<(), Unsupported>

Compute all the contacts between two shapes. Read more
Source§

fn contact_manifold_convex_convex( &self, pos12: &Isometry<f32>, shape1: &dyn Shape, shape2: &dyn Shape, normal_constraints1: Option<&dyn NormalConstraints>, normal_constraints2: Option<&dyn NormalConstraints>, prediction: f32, manifold: &mut ContactManifold<ManifoldData, ContactData>, ) -> Result<(), Unsupported>

Computes the contact-manifold between two convex shapes.
Source§

impl QueryDispatcher for DefaultQueryDispatcher

Source§

fn distance( &self, pos12: &Isometry<f32>, shape1: &dyn Shape, shape2: &dyn Shape, ) -> Result<f32, Unsupported>

Computes the minimum distance separating two shapes.

Returns 0.0 if the objects are touching or penetrating.

Source§

fn intersection_test( &self, pos12: &Isometry<f32>, shape1: &dyn Shape, shape2: &dyn Shape, ) -> Result<bool, Unsupported>

Tests whether two shapes are intersecting.
Source§

fn contact( &self, pos12: &Isometry<f32>, shape1: &dyn Shape, shape2: &dyn Shape, prediction: f32, ) -> Result<Option<Contact>, Unsupported>

Computes one pair of contact points point between two shapes. Read more
Source§

fn closest_points( &self, pos12: &Isometry<f32>, shape1: &dyn Shape, shape2: &dyn Shape, max_dist: f32, ) -> Result<ClosestPoints, Unsupported>

Computes the pair of closest points between two shapes. Read more
Source§

fn cast_shapes( &self, pos12: &Isometry<f32>, local_vel12: &Vector<f32>, shape1: &dyn Shape, shape2: &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. Read more
Source§

fn cast_shapes_nonlinear( &self, motion1: &NonlinearRigidMotion, shape1: &dyn Shape, motion2: &NonlinearRigidMotion, shape2: &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. Read more
Source§

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

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts 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>

Converts 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)

Converts &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)

Converts &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
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Sync + Send>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.