parry3d_f64/query/contact_manifolds/mod.rs
1//! Contact manifolds for persistent collision detection.
2//!
3//! # What are Contact Manifolds?
4//!
5//! A **contact manifold** is a collection of contact points between two shapes that share
6//! the same contact normal and contact kinematics. Contact manifolds are fundamental to
7//! physics simulation because they provide stable, persistent contact information that can
8//! be reused across multiple simulation frames.
9//!
10//! Unlike single-shot contact queries that compute contact information from scratch each
11//! frame, contact manifolds maintain and update contact information over time, leading to
12//! more stable and efficient physics simulations.
13//!
14//! # Why are Contact Manifolds Important?
15//!
16//! Contact manifolds are critical for physics simulation for several reasons:
17//!
18//! 1. **Stability**: By maintaining persistent contact information across frames, physics
19//! engines can provide more stable contact resolution without jittering.
20//!
21//! 2. **Performance**: Updating existing contact points is often faster than recomputing
22//! them from scratch, especially for complex shapes.
23//!
24//! 3. **Contact Tracking**: Each contact point in a manifold has a unique identifier
25//! (feature IDs) that allows physics engines to track contacts over time and maintain
26//! contact-specific data like accumulated impulses for warm-starting.
27//!
28//! 4. **Multiple Contact Points**: Many shape pairs require multiple contact points for
29//! stable physics simulation. For example, a box resting on a plane typically needs
30//! 4 contact points (one for each corner).
31//!
32//! # Basic Usage
33//!
34//! ```rust
35//! # #[cfg(all(feature = "dim3", feature = "f32"))] {
36//! use parry3d::query::{ContactManifold, TrackedContact};
37//! use parry3d::query::details::contact_manifold_ball_ball;
38//! use parry3d::shape::Ball;
39//! use parry3d::math::{Pose, Vector};
40//!
41//! // Create two balls
42//! let ball1 = Ball::new(1.0);
43//! let ball2 = Ball::new(1.0);
44//!
45//! // Position them so they're touching
46//! let pos12 = Pose::translation(1.9, 0.0, 0.0);
47//!
48//! // Create an empty contact manifold
49//! // Note: ManifoldData and ContactData are user-defined types for tracking data
50//! let mut manifold = ContactManifold::<(), ()>::new();
51//!
52//! // Compute the contact manifold with a prediction distance
53//! let prediction = 0.1; // Look ahead distance
54//! contact_manifold_ball_ball(&pos12, &ball1, &ball2, prediction, &mut manifold);
55//!
56//! // Check if we have any contacts
57//! if let Some(contact) = manifold.points.first() {
58//! println!("Contact distance: {}", contact.dist);
59//! println!("Contact point on ball1: {:?}", contact.local_p1);
60//! println!("Contact point on ball2: {:?}", contact.local_p2);
61//! }
62//! # }
63//! ```
64//!
65//! # Updating Contact Manifolds
66//!
67//! One of the key benefits of contact manifolds is the ability to efficiently update them
68//! using spatial coherence:
69//!
70//! ```rust
71//! # #[cfg(all(feature = "dim3", feature = "f32"))] {
72//! use parry3d::query::{ContactManifold, TrackedContact};
73//! use parry3d::query::details::contact_manifold_ball_ball;
74//! use parry3d::shape::Ball;
75//! use parry3d::math::Pose;
76//!
77//! let ball1 = Ball::new(1.0);
78//! let ball2 = Ball::new(1.0);
79//! let mut manifold = ContactManifold::<(), ()>::new();
80//!
81//! // Initial contact computation
82//! let pos12_frame1 = Pose::translation(1.9, 0.0, 0.0);
83//! contact_manifold_ball_ball(&pos12_frame1, &ball1, &ball2, 0.1, &mut manifold);
84//!
85//! // On the next frame, try to update using spatial coherence
86//! let pos12_frame2 = Pose::translation(1.85, 0.0, 0.0);
87//!
88//! // Try to update contacts efficiently
89//! if !manifold.try_update_contacts(&pos12_frame2) {
90//! // Update failed (shapes moved too much or orientation changed significantly)
91//! // Fall back to full recomputation
92//! contact_manifold_ball_ball(&pos12_frame2, &ball1, &ball2, 0.1, &mut manifold);
93//! }
94//! # }
95//! ```
96//!
97//! # Contact Prediction
98//!
99//! The `prediction` parameter is a distance threshold that allows detecting contacts
100//! slightly before shapes actually touch. This is useful for:
101//!
102//! - **Continuous Collision Detection**: Predicting contacts helps prevent tunneling
103//! - **Speculative Contacts**: Physics engines can prepare for imminent collisions
104//! - **Contact Caching**: Maintaining contacts even when shapes briefly separate
105//!
106//! A typical prediction value might be 1-10% of the smallest shape dimension.
107//!
108//! # Shape-Specific Contact Computation
109//!
110//! This module provides specialized contact manifold computation functions for various
111//! shape pairs. Each function is optimized for the specific geometric properties of the
112//! shapes involved:
113//!
114//! - `contact_manifold_ball_ball`: Two spheres (simplest case, always 1 contact)
115//! - `contact_manifold_cuboid_cuboid`: Two boxes (up to 8 contacts in 3D)
116//! - `contact_manifold_capsule_capsule`: Two capsules
117//! - `contact_manifold_convex_ball`: Convex shape vs sphere
118//! - And many more specialized functions for different shape combinations
119//!
120//! # Working with Composite Shapes
121//!
122//! For composite shapes (triangle meshes, heightfields, compounds), contact manifold
123//! computation is more complex and requires workspace objects for efficient memory management:
124//!
125//! - `contact_manifolds_trimesh_shape`: Triangle mesh vs any shape
126//! - `contact_manifolds_heightfield_shape`: Heightfield terrain vs any shape
127//! - `contact_manifolds_composite_shape_shape`: Compound shape vs any shape
128//! - `contact_manifolds_voxels_shape`: Voxel grid vs any shape
129//!
130//! These functions use workspace objects to avoid repeated allocations.
131
132pub use self::contact_manifold::{ContactManifold, TrackedContact};
133pub use self::contact_manifolds_ball_ball::{
134 contact_manifold_ball_ball, contact_manifold_ball_ball_shapes,
135};
136pub use self::contact_manifolds_capsule_capsule::{
137 contact_manifold_capsule_capsule, contact_manifold_capsule_capsule_shapes,
138};
139pub use self::contact_manifolds_convex_ball::{
140 contact_manifold_convex_ball, contact_manifold_convex_ball_shapes,
141};
142// pub use self::contact_manifolds_cuboid_capsule::{
143// contact_manifold_cuboid_capsule, contact_manifold_cuboid_capsule_shapes,
144// };
145pub use self::contact_manifolds_composite_shape_composite_shape::contact_manifolds_composite_shape_composite_shape;
146pub use self::contact_manifolds_composite_shape_shape::contact_manifolds_composite_shape_shape;
147pub use self::contact_manifolds_cuboid_cuboid::{
148 contact_manifold_cuboid_cuboid, contact_manifold_cuboid_cuboid_shapes,
149};
150pub use self::contact_manifolds_cuboid_triangle::{
151 contact_manifold_cuboid_triangle, contact_manifold_cuboid_triangle_shapes,
152};
153pub use self::contact_manifolds_halfspace_pfm::{
154 contact_manifold_halfspace_pfm, contact_manifold_halfspace_pfm_shapes,
155};
156pub use self::contact_manifolds_heightfield_composite_shape::contact_manifolds_heightfield_composite_shape;
157pub use self::contact_manifolds_heightfield_shape::{
158 contact_manifolds_heightfield_shape, contact_manifolds_heightfield_shape_shapes,
159};
160pub use self::contact_manifolds_pfm_pfm::{
161 contact_manifold_pfm_pfm, contact_manifold_pfm_pfm_shapes,
162};
163pub use self::contact_manifolds_trimesh_shape::{
164 contact_manifolds_trimesh_shape, contact_manifolds_trimesh_shape_shapes,
165};
166pub use self::contact_manifolds_voxels_ball::contact_manifolds_voxels_ball_shapes;
167pub use self::contact_manifolds_voxels_composite_shape::{
168 contact_manifolds_voxels_composite_shape, contact_manifolds_voxels_composite_shape_shapes,
169};
170pub use self::contact_manifolds_voxels_shape::{
171 contact_manifolds_voxels_shape, contact_manifolds_voxels_shape_shapes,
172 VoxelsShapeContactManifoldsWorkspace,
173};
174pub(crate) use self::contact_manifolds_voxels_shape::{
175 CanonicalVoxelShape, VoxelsShapeSubDetector,
176};
177pub use self::contact_manifolds_voxels_voxels::{
178 contact_manifolds_voxels_voxels, contact_manifolds_voxels_voxels_shapes,
179};
180pub use self::contact_manifolds_workspace::{
181 ContactManifoldsWorkspace, TypedWorkspaceData, WorkspaceData,
182};
183pub use self::normals_constraint::{NormalConstraints, NormalConstraintsPair};
184
185use {
186 self::contact_manifolds_composite_shape_composite_shape::CompositeShapeCompositeShapeContactManifoldsWorkspace,
187 self::contact_manifolds_composite_shape_shape::CompositeShapeShapeContactManifoldsWorkspace,
188 self::contact_manifolds_heightfield_composite_shape::HeightFieldCompositeShapeContactManifoldsWorkspace,
189 self::contact_manifolds_heightfield_shape::HeightFieldShapeContactManifoldsWorkspace,
190 self::contact_manifolds_trimesh_shape::TriMeshShapeContactManifoldsWorkspace,
191};
192
193mod contact_manifold;
194mod contact_manifolds_ball_ball;
195mod contact_manifolds_capsule_capsule;
196mod contact_manifolds_convex_ball;
197// mod contact_manifolds_cuboid_capsule;
198mod contact_manifolds_composite_shape_composite_shape;
199mod contact_manifolds_composite_shape_shape;
200mod contact_manifolds_cuboid_cuboid;
201mod contact_manifolds_cuboid_triangle;
202mod contact_manifolds_halfspace_pfm;
203mod contact_manifolds_heightfield_composite_shape;
204mod contact_manifolds_heightfield_shape;
205mod contact_manifolds_pfm_pfm;
206mod contact_manifolds_trimesh_shape;
207mod contact_manifolds_voxels_ball;
208mod contact_manifolds_voxels_composite_shape;
209mod contact_manifolds_voxels_shape;
210mod contact_manifolds_voxels_voxels;
211mod contact_manifolds_workspace;
212mod normals_constraint;