rapier2d/
lib.rs

1//! # Rapier
2//!
3//! Rapier is a set of two Rust crates `rapier2d` and `rapier3d` for efficient cross-platform
4//! physics simulation. It target application include video games, animation, robotics, etc.
5//!
6//! Rapier has some unique features for collaborative applications:
7//! - The ability to snapshot the state of the physics engine, and restore it later.
8//! - The ability to run a perfectly deterministic simulation on different machine, as long as they
9//!   are compliant with the IEEE 754-2008 floating point standard.
10//!
11//! User documentation for Rapier is on [the official Rapier site](https://rapier.rs/docs/).
12
13#![deny(bare_trait_objects)]
14#![warn(missing_docs)]
15#![allow(clippy::too_many_arguments)]
16#![allow(clippy::needless_range_loop)] // TODO: remove this? I find that in the math code using indices adds clarity.
17#![allow(clippy::module_inception)]
18#![cfg_attr(feature = "simd-nightly", feature(portable_simd))]
19
20#[cfg(all(feature = "dim2", feature = "f32"))]
21pub extern crate parry2d as parry;
22#[cfg(all(feature = "dim2", feature = "f64"))]
23pub extern crate parry2d_f64 as parry;
24#[cfg(all(feature = "dim3", feature = "f32"))]
25pub extern crate parry3d as parry;
26#[cfg(all(feature = "dim3", feature = "f64"))]
27pub extern crate parry3d_f64 as parry;
28
29pub extern crate nalgebra as na;
30#[cfg(feature = "serde-serialize")]
31#[macro_use]
32extern crate serde;
33extern crate num_traits as num;
34
35pub use parry::glamx;
36
37#[cfg(feature = "parallel")]
38pub use rayon;
39
40#[cfg(all(
41    feature = "simd-is-enabled",
42    not(feature = "simd-stable"),
43    not(feature = "simd-nightly")
44))]
45std::compile_error!(
46    "The `simd-is-enabled` feature should not be enabled explicitly. Please enable the `simd-stable` or the `simd-nightly` feature instead."
47);
48#[cfg(all(feature = "simd-is-enabled", feature = "enhanced-determinism"))]
49std::compile_error!(
50    "SIMD cannot be enabled when the `enhanced-determinism` feature is also enabled."
51);
52
53macro_rules! enable_flush_to_zero(
54    () => {
55        let _flush_to_zero = crate::utils::FlushToZeroDenormalsAreZeroFlags::flush_denormal_to_zero();
56    }
57);
58
59#[allow(unused_macros)]
60macro_rules! gather(
61    ($callback: expr) => {
62        {
63            #[inline(always)]
64            #[allow(dead_code)]
65            #[cfg(not(feature = "simd-is-enabled"))]
66            fn create_arr<T>(mut callback: impl FnMut(usize) -> T) -> T {
67                callback(0usize)
68            }
69
70            #[inline(always)]
71            #[allow(dead_code)]
72            #[cfg(feature = "simd-is-enabled")]
73            fn create_arr<T>(mut callback: impl FnMut(usize) -> T) -> [T; SIMD_WIDTH] {
74                [callback(0usize), callback(1usize), callback(2usize), callback(3usize)]
75            }
76
77
78            create_arr($callback)
79        }
80    }
81);
82
83macro_rules! array(
84    ($callback: expr) => {
85        {
86            #[inline(always)]
87            #[allow(dead_code)]
88            fn create_arr<T>(mut callback: impl FnMut(usize) -> T) -> [T; SIMD_WIDTH] {
89                #[cfg(not(feature = "simd-is-enabled"))]
90                return [callback(0usize)];
91                #[cfg(feature = "simd-is-enabled")]
92                return [callback(0usize), callback(1usize), callback(2usize), callback(3usize)];
93            }
94
95            create_arr($callback)
96        }
97    }
98);
99
100#[allow(unused_macros)]
101macro_rules! par_iter {
102    ($t: expr) => {{
103        #[cfg(not(feature = "parallel"))]
104        let it = $t.iter();
105
106        #[cfg(feature = "parallel")]
107        let it = $t.par_iter();
108        it
109    }};
110}
111
112macro_rules! par_iter_mut {
113    ($t: expr) => {{
114        #[cfg(not(feature = "parallel"))]
115        let it = $t.iter_mut();
116
117        #[cfg(feature = "parallel")]
118        let it = $t.par_iter_mut();
119        it
120    }};
121}
122
123// macro_rules! par_chunks_mut {
124//     ($t: expr, $sz: expr) => {{
125//         #[cfg(not(feature = "parallel"))]
126//         let it = $t.chunks_mut($sz);
127//
128//         #[cfg(feature = "parallel")]
129//         let it = $t.par_chunks_mut($sz);
130//         it
131//     }};
132// }
133
134#[allow(unused_macros)]
135macro_rules! try_ret {
136    ($val: expr) => {
137        try_ret!($val, ())
138    };
139    ($val: expr, $ret: expr) => {
140        if let Some(val) = $val {
141            val
142        } else {
143            return $ret;
144        }
145    };
146}
147
148// macro_rules! try_continue {
149//     ($val: expr) => {
150//         if let Some(val) = $val {
151//             val
152//         } else {
153//             continue;
154//         }
155//     };
156// }
157
158pub(crate) const INVALID_U32: u32 = u32::MAX;
159pub(crate) const INVALID_USIZE: usize = INVALID_U32 as usize;
160
161/// The string version of Rapier.
162pub const VERSION: &str = env!("CARGO_PKG_VERSION");
163
164pub mod control;
165pub mod counters;
166pub mod data;
167pub mod dynamics;
168pub mod geometry;
169pub mod pipeline;
170pub mod utils;
171
172/// Elementary mathematical entities (vectors, matrices, isometries, etc).
173pub mod math {
174    pub use parry::math::*;
175
176    // Re-export glam from parry for direct access
177    pub use parry::glamx;
178
179    /// Creates a rotation from an angular vector.
180    ///
181    /// In 2D, the angular vector is a scalar angle in radians.
182    /// In 3D, the angular vector is a scaled axis-angle (axis * angle).
183    #[cfg(feature = "dim2")]
184    #[inline]
185    pub fn rotation_from_angle(angle: AngVector) -> Rotation {
186        Rotation::new(angle)
187    }
188
189    /// Creates a rotation from an angular vector.
190    ///
191    /// In 2D, the angular vector is a scalar angle in radians.
192    /// In 3D, the angular vector is a scaled axis-angle (axis * angle).
193    #[cfg(feature = "dim3")]
194    #[inline]
195    pub fn rotation_from_angle(angle: AngVector) -> Rotation {
196        Rotation::from_scaled_axis(angle)
197    }
198
199    // Generic nalgebra type aliases for SIMD/generic code (where N is SimdReal or similar)
200    // These use nalgebra types which support generic scalars
201    // Note: These override the non-generic versions above when used with <T> syntax
202
203    /// Generic vector type (nalgebra) for SoA SIMD code
204    #[cfg(feature = "dim2")]
205    pub type SimdVector<N> = na::Vector2<N>;
206    /// Generic vector type (nalgebra) for SoA SIMD code
207    #[cfg(feature = "dim3")]
208    pub type SimdVector<N> = na::Vector3<N>;
209    /// Generic angular vector type (nalgebra) for SoA SIMD code
210    #[cfg(feature = "dim2")]
211    pub type SimdAngVector<N> = N;
212    /// Generic angular vector type (nalgebra) for SoA SIMD code
213    #[cfg(feature = "dim3")]
214    pub type SimdAngVector<N> = na::Vector3<N>;
215    /// Generic point type (nalgebra) for SoA SIMD code
216    #[cfg(feature = "dim2")]
217    pub type SimdPoint<N> = na::Point2<N>;
218    /// Generic point type (nalgebra) for SoA SIMD code
219    #[cfg(feature = "dim3")]
220    pub type SimdPoint<N> = na::Point3<N>;
221    /// Generic isometry type (nalgebra) for SoA SIMD code
222    #[cfg(feature = "dim2")]
223    pub type SimdPose<N> = na::Isometry2<N>;
224    /// Generic isometry type (nalgebra) for SoA SIMD code
225    #[cfg(feature = "dim3")]
226    pub type SimdPose<N> = na::Isometry3<N>;
227    /// Generic rotation type (nalgebra) for SoA SIMD code
228    #[cfg(feature = "dim2")]
229    pub type SimdRotation<N> = na::UnitComplex<N>;
230    /// Generic rotation type (nalgebra) for SoA SIMD code
231    #[cfg(feature = "dim3")]
232    pub type SimdRotation<N> = na::UnitQuaternion<N>;
233    /// Generic angular inertia type for SoA SIMD code (scalar in 2D, SdpMatrix3 in 3D)
234    #[cfg(feature = "dim2")]
235    pub type SimdAngularInertia<N> = N;
236    /// Generic angular inertia type for SoA SIMD code (scalar in 2D, SdpMatrix3 in 3D)
237    #[cfg(feature = "dim3")]
238    pub type SimdAngularInertia<N> = parry::utils::SdpMatrix3<N>;
239    /// Generic 2D/3D square matrix for SoA SIMD code
240    #[cfg(feature = "dim2")]
241    pub type SimdMatrix<N> = na::Matrix2<N>;
242    /// Generic 2D/3D square matrix for SoA SIMD code
243    #[cfg(feature = "dim3")]
244    pub type SimdMatrix<N> = na::Matrix3<N>;
245
246    // Dimension types for nalgebra matrix operations (used in multibody code)
247    /// The dimension type constant (U2 for 2D).
248    #[cfg(feature = "dim2")]
249    pub type Dim = na::U2;
250    /// The dimension type constant (U3 for 3D).
251    #[cfg(feature = "dim3")]
252    pub type Dim = na::U3;
253    /// The angular dimension type constant (U1 for 2D).
254    #[cfg(feature = "dim2")]
255    pub type AngDim = na::U1;
256    /// The angular dimension type constant (U3 for 3D).
257    #[cfg(feature = "dim3")]
258    pub type AngDim = na::U3;
259
260    /// Dynamic vector type for multibody/solver code
261    pub type DVector = na::DVector<Real>;
262    /// Dynamic matrix type for multibody/solver code
263    pub type DMatrix = na::DMatrix<Real>;
264
265    /*
266     * 2D
267     */
268    /// Max number of pairs of contact points from the same
269    /// contact manifold that can be solved as part of a
270    /// single contact constraint.
271    #[cfg(feature = "dim2")]
272    pub const MAX_MANIFOLD_POINTS: usize = 2;
273
274    /// The type of a constraint Jacobian in twist coordinates.
275    #[cfg(feature = "dim2")]
276    pub type Jacobian<N> = na::Matrix3xX<N>;
277
278    /// The type of a slice of the constraint Jacobian in twist coordinates.
279    #[cfg(feature = "dim2")]
280    pub type JacobianView<'a, N> = na::MatrixView3xX<'a, N>;
281
282    /// The type of a mutable slice of the constraint Jacobian in twist coordinates.
283    #[cfg(feature = "dim2")]
284    pub type JacobianViewMut<'a, N> = na::MatrixViewMut3xX<'a, N>;
285
286    /// The type of impulse applied for friction constraints.
287    #[cfg(feature = "dim2")]
288    pub type TangentImpulse<N> = na::Vector1<N>;
289
290    /// The maximum number of possible rotations and translations of a rigid body.
291    #[cfg(feature = "dim2")]
292    pub const SPATIAL_DIM: usize = 3;
293
294    /// The maximum number of rotational degrees of freedom of a rigid-body.
295    #[cfg(feature = "dim2")]
296    pub const ANG_DIM: usize = 1;
297
298    /*
299     * 3D
300     */
301    /// Max number of pairs of contact points from the same
302    /// contact manifold that can be solved as part of a
303    /// single contact constraint.
304    #[cfg(feature = "dim3")]
305    pub const MAX_MANIFOLD_POINTS: usize = 4;
306
307    /// The type of a constraint Jacobian in twist coordinates.
308    #[cfg(feature = "dim3")]
309    pub type Jacobian<N> = na::Matrix6xX<N>;
310
311    /// The type of a slice of the constraint Jacobian in twist coordinates.
312    #[cfg(feature = "dim3")]
313    pub type JacobianView<'a, N> = na::MatrixView6xX<'a, N>;
314
315    /// The type of a mutable slice of the constraint Jacobian in twist coordinates.
316    #[cfg(feature = "dim3")]
317    pub type JacobianViewMut<'a, N> = na::MatrixViewMut6xX<'a, N>;
318
319    /// The type of impulse applied for friction constraints.
320    #[cfg(feature = "dim3")]
321    pub type TangentImpulse<N> = na::Vector2<N>;
322
323    /// The maximum number of possible rotations and translations of a rigid body.
324    #[cfg(feature = "dim3")]
325    pub const SPATIAL_DIM: usize = 6;
326
327    /// The maximum number of rotational degrees of freedom of a rigid-body.
328    #[cfg(feature = "dim3")]
329    pub const ANG_DIM: usize = 3;
330}
331
332/// Prelude containing the common types defined by Rapier.
333pub mod prelude {
334    pub use crate::dynamics::*;
335    pub use crate::geometry::*;
336    pub use crate::math::*;
337    pub use crate::pipeline::*;
338    pub use na::{point, vector};
339    pub extern crate nalgebra;
340}