Skip to main content

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