parry2d/query/nonlinear_shape_cast/
mod.rs

1//! Nonlinear shape casting with rotation for continuous collision detection.
2//!
3//! This module provides **nonlinear shape casting** - detecting when and where two shapes
4//! moving with both **translation and rotation** will first collide. This is essential for
5//! accurate continuous collision detection (CCD) when objects are spinning or tumbling.
6//!
7//! # What is Nonlinear Shape Casting?
8//!
9//! While linear shape casting (see [`cast_shapes`](crate::query::cast_shapes)) handles objects
10//! moving in straight lines, **nonlinear shape casting** accounts for rotational motion:
11//!
12//! - **Linear casting**: Objects translate only (constant velocity, straight path)
13//! - **Nonlinear casting**: Objects both translate and rotate (curved trajectory)
14//!
15//! When objects rotate during motion, their effective path through space becomes nonlinear,
16//! requiring more sophisticated algorithms to detect the first moment of contact.
17//!
18//! # When to Use Nonlinear vs Linear Shape Casting
19//!
20//! ## Use **Nonlinear** Shape Casting When:
21//!
22//! - Objects have **angular velocity** (spinning, rotating, tumbling)
23//! - Accurate rotation is critical (e.g., rotating blades, tumbling debris)
24//! - Objects can rotate significantly during the timestep
25//! - You need physically accurate CCD for rotational motion
26//!
27//! ## Use **Linear** Shape Casting When:
28//!
29//! - Objects only translate (no rotation)
30//! - Rotational effects are negligible for the timestep
31//! - Performance is critical and rotation can be approximated
32//! - You're implementing simple sweeping/sliding mechanics
33//!
34//! # Key Differences from Linear Shape Casting
35//!
36//! | Aspect | Linear (`cast_shapes`) | Nonlinear (`cast_shapes_nonlinear`) |
37//! |--------|------------------------|--------------------------------------|
38//! | **Motion** | Translation only | Translation + rotation |
39//! | **Path** | Straight line | Curved (helical) trajectory |
40//! | **Input** | Position + velocity | Position + velocity + angular velocity |
41//! | **Complexity** | Lower (simpler math) | Higher (rotational transforms) |
42//! | **Accuracy** | Perfect for non-rotating | Accurate for rotating objects |
43//! | **Performance** | Faster | Slower (more iterations) |
44//!
45//! # Main Types
46//!
47//! - [`cast_shapes_nonlinear`] - Main function for nonlinear shape casting
48//! - [`NonlinearRigidMotion`] - Describes an object's motion (position, velocities, rotation center)
49//!
50//! # Physics Background
51//!
52//! In rigid body physics, an object's motion has 6 degrees of freedom (3D):
53//! - **3 translational**: Linear velocity in x, y, z
54//! - **3 rotational**: Angular velocity around x, y, z axes
55//!
56//! Nonlinear shape casting simulates this complete motion to find collision times,
57//! ensuring no tunneling occurs even when objects spin at high angular velocities.
58//!
59//! # Example: Rotating vs Non-Rotating Collision
60//!
61//! ```rust
62//! # #[cfg(all(feature = "dim3", feature = "f32"))] {
63//! use parry3d::query::{cast_shapes, cast_shapes_nonlinear, ShapeCastOptions, NonlinearRigidMotion};
64//! use parry3d::shape::Cuboid;
65//! use parry3d::na::{Isometry3, Vector3};
66//!
67//! let cube1 = Cuboid::new(Vector3::new(1.0, 1.0, 1.0));
68//! let cube2 = Cuboid::new(Vector3::new(0.5, 0.5, 0.5));
69//!
70//! let pos1 = Isometry3::translation(0.0, 0.0, 0.0);
71//! let pos2 = Isometry3::translation(5.0, 0.0, 0.0);
72//!
73//! // Linear motion: cube moves right
74//! let vel1 = Vector3::new(1.0, 0.0, 0.0);
75//! let options = ShapeCastOptions::default();
76//!
77//! let linear_hit = cast_shapes(&pos1, &vel1, &cube1, &pos2, &Vector3::zeros(), &cube2, options);
78//!
79//! // Nonlinear motion: cube moves right AND spins around Y axis
80//! let motion1 = NonlinearRigidMotion::new(
81//!     pos1,
82//!     parry3d::na::Point3::origin(), // rotation center
83//!     vel1,                        // linear velocity
84//!     Vector3::new(0.0, 5.0, 0.0), // angular velocity (spinning fast)
85//! );
86//! let motion2 = NonlinearRigidMotion::constant_position(pos2);
87//!
88//! let nonlinear_hit = cast_shapes_nonlinear(
89//!     &motion1,
90//!     &cube1,
91//!     &motion2,
92//!     &cube2,
93//!     0.0,  // start time
94//!     10.0, // end time
95//!     true, // stop at penetration
96//! );
97//!
98//! // The spinning cube may collide at a different time due to rotation!
99//! // Its corners sweep out a larger effective volume as it spins.
100//! # }
101//! ```
102//!
103//! # Performance Considerations
104//!
105//! Nonlinear shape casting is computationally more expensive than linear casting:
106//!
107//! - More iterations needed for convergence (curved paths harder to solve)
108//! - Additional rotational transform calculations
109//! - More complex geometry at each time step
110//!
111//! **Optimization Tips:**
112//! - Use linear casting when angular velocity is near zero
113//! - Keep time intervals (`end_time - start_time`) reasonably small
114//! - Consider approximating slow rotations with linear motion
115//!
116//! # Common Use Cases
117//!
118//! 1. **Physics Simulations**: Accurate CCD for spinning rigid bodies
119//! 2. **Game Mechanics**: Rotating blades, spinning projectiles, tumbling objects
120//! 3. **Robotics**: Robotic arms with rotating joints
121//! 4. **Vehicle Physics**: Rolling wheels, spinning debris from impacts
122//! 5. **Animation**: Ensuring no intersections during animated rotations
123//!
124//! # See Also
125//!
126//! - [`cast_shapes`](crate::query::cast_shapes) - Linear shape casting (translation only)
127//! - [`ShapeCastHit`](crate::query::ShapeCastHit) - Result structure with impact information
128//! - [`contact`](crate::query::contact::contact()) - Static contact detection (no motion)
129
130#[cfg(feature = "alloc")]
131pub use self::nonlinear_shape_cast_composite_shape_shape::{
132    cast_shapes_nonlinear_composite_shape_shape, cast_shapes_nonlinear_shape_composite_shape,
133};
134#[cfg(feature = "alloc")]
135pub use self::nonlinear_shape_cast_voxels_shape::{
136    cast_shapes_nonlinear_shape_voxels, cast_shapes_nonlinear_voxels_shape,
137};
138//pub use self::nonlinear_shape_cast_halfspace_support_map::{cast_shapes_nonlinear_halfspace_support_map, cast_shapes_nonlinear_support_map_halfspace};
139pub use self::nonlinear_rigid_motion::NonlinearRigidMotion;
140pub use self::nonlinear_shape_cast::cast_shapes_nonlinear;
141pub use self::nonlinear_shape_cast_support_map_support_map::{
142    cast_shapes_nonlinear_support_map_support_map, NonlinearShapeCastMode,
143};
144
145#[cfg(feature = "alloc")]
146mod nonlinear_shape_cast_composite_shape_shape;
147#[cfg(feature = "alloc")]
148mod nonlinear_shape_cast_voxels_shape;
149//mod cast_shapes_nonlinear_halfspace_support_map;
150mod nonlinear_rigid_motion;
151mod nonlinear_shape_cast;
152mod nonlinear_shape_cast_support_map_support_map;