Skip to main content

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