bevy_xpbd_2d/lib.rs
1//! # Bevy XPBD (deprecated in favor of [Avian](https://github.com/Jondolf/avian))
2//!
3//! **⚠️ Bevy XPBD has been deprecated in favor of its successor [Avian](https://github.com/Jondolf/avian).
4//! No further development or maintenance will be done for Bevy XPBD.
5//! See [#346](https://github.com/Jondolf/avian/issues/346) for background.**
6//!
7//! ---
8//!
9//! **Bevy XPBD** is a 2D and 3D physics engine based on
10//! [*Extended Position Based Dynamics* (XPBD)](#what-is-xpbd) for
11//! the [Bevy game engine](https://bevyengine.org/).
12//!
13//! Check out the [GitHub repository](https://github.com/Jondolf/bevy_xpbd)
14//! for more information about the design, read the [Getting started](#getting-started)
15//! guide below to get up to speed, and take a look at the [Table of contents](#table-of-contents)
16//! for an overview of the engine's features and their documentation.
17//!
18//! You can also check out the [FAQ](#frequently-asked-questions), and if you encounter
19//! any further problems, consider saying hello on the [Bevy Discord](https://discord.gg/bevy)!
20//!
21//! ## Getting started
22//!
23//! This short guide should help you get started with Bevy XPBD.
24//!
25//! ### Add the dependency
26//!
27//! First, add `bevy_xpbd_2d` or `bevy_xpbd_3d` to the dependencies in your `Cargo.toml`:
28//!
29//! ```toml
30//! # For 2D applications:
31//! [dependencies]
32//! bevy_xpbd_2d = "0.5"
33//!
34//! # For 3D applications:
35//! [dependencies]
36//! bevy_xpbd_3d = "0.5"
37//!
38//! # If you want to use the most up-to-date version, you can follow the main branch:
39//! [dependencies]
40//! bevy_xpbd_3d = { git = "https://github.com/Jondolf/bevy_xpbd", branch = "main" }
41//! ```
42//!
43//! You can specify features by disabling the default features and manually adding
44//! the feature flags you want:
45//!
46//! ```toml
47//! [dependencies]
48//! # Add 3D Bevy XPBD with double-precision floating point numbers.
49//! # `parry-f64` enables collision detection using Parry.
50//! bevy_xpbd_3d = { version = "0.5", default-features = false, features = ["3d", "f64", "parry-f64"] }
51//! ```
52//!
53//! ### Feature flags
54//!
55//! | Feature | Description | Default feature |
56//! | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
57//! | `2d` | Enables 2D physics. Incompatible with `3d`. | Yes (`bevy_xpbd_2d`) |
58//! | `3d` | Enables 3D physics. Incompatible with `2d`. | Yes (`bevy_xpbd_3d`) |
59//! | `f32` | Enables `f32` precision for physics. Incompatible with `f64`. | Yes |
60//! | `f64` | Enables `f64` precision for physics. Incompatible with `f32`. | No |
61//! | `default-collider` | Enables the default [`Collider`]. Required for [spatial queries](spatial_query). Requires either the `parry-f32` or `parry-f64` feature. | Yes |
62//! | `parry-f32` | Enables the `f32` version of the Parry collision detection library. Also enables the `default-collider` feature. | Yes |
63//! | `parry-f64` | Enables the `f64` version of the Parry collision detection library. Also enables the `default-collider` feature. | No |
64#![cfg_attr(
65 feature = "3d",
66 doc = "| `collider-from-mesh` | Allows you to create [`Collider`]s from `Mesh`es. | Yes |"
67)]
68#![cfg_attr(
69 feature = "3d",
70 doc = "| `async-collider` | Allows you to generate [`Collider`]s from mesh handles and scenes. | Yes |"
71)]
72//! | `debug-plugin` | Enables physics debug rendering using the [`PhysicsDebugPlugin`]. The plugin must be added separately. | Yes |
73//! | `enhanced-determinism` | Enables increased determinism. | No |
74//! | `parallel` | Enables some extra multithreading, which improves performance for larger simulations but can add some overhead for smaller ones. | Yes |
75//! | `simd` | Enables [SIMD] optimizations. | No |
76//! | `serialize` | Enables support for serialization and deserialization using Serde. | No |
77//!
78//! [SIMD]: https://en.wikipedia.org/wiki/Single_instruction,_multiple_data
79//!
80//! ### Install the plugin
81//!
82//! Bevy XPBD is designed to be very modular. It is built from several [plugins] that
83//! manage different parts of the engine. These plugins can be easily initialized and configured through
84//! the [`PhysicsPlugins`] plugin group.
85//!
86//! ```no_run
87//! use bevy::prelude::*;
88#![cfg_attr(feature = "2d", doc = "use bevy_xpbd_2d::prelude::*;")]
89#![cfg_attr(feature = "3d", doc = "use bevy_xpbd_3d::prelude::*;")]
90//!
91//! fn main() {
92//! App::new()
93//! .add_plugins((DefaultPlugins, PhysicsPlugins::default()))
94//! // ...your other plugins, systems and resources
95//! .run();
96//! }
97//! ```
98//!
99//! Now you can use all of Bevy XPBD's [components] and [resources] to build whatever you want!
100//!
101//! For example, adding a [rigid body](RigidBody) with a [collider](Collider) is as simple as spawning an entity
102//! with the [`RigidBody`] and [`Collider`] components:
103//!
104//! ```
105//! use bevy::prelude::*;
106#![cfg_attr(feature = "2d", doc = "use bevy_xpbd_2d::prelude::*;")]
107#![cfg_attr(feature = "3d", doc = "use bevy_xpbd_3d::prelude::*;")]
108//!
109//! fn setup(mut commands: Commands) {
110#![cfg_attr(
111 feature = "2d",
112 doc = " commands.spawn((RigidBody::Dynamic, Collider::circle(0.5)));"
113)]
114#![cfg_attr(
115 feature = "3d",
116 doc = " commands.spawn((RigidBody::Dynamic, Collider::sphere(0.5)));"
117)]
118//! }
119//! ```
120//!
121//! You can find lots of [usage examples](https://github.com/Jondolf/bevy_xpbd#more-examples)
122//! in the project's [repository](https://github.com/Jondolf/bevy_xpbd).
123//!
124//! ## Table of contents
125//!
126//! Below is a structured overview of the documentation for the various
127//! features of the engine.
128//!
129//! ### Rigid bodies
130//!
131//! - [Rigid body types](RigidBody#rigid-body-types)
132//! - [Creating rigid bodies](RigidBody#creation)
133//! - [Movement](RigidBody#movement)
134//! - [Linear](LinearVelocity) and [angular](AngularVelocity) velocity
135//! - [Forces](ExternalForce), [torque](ExternalTorque), and [linear](ExternalImpulse) and [angular](ExternalAngularImpulse) impulses
136//! - [Gravity] and [gravity scale](GravityScale)
137//! - [Mass properties](RigidBody#mass-properties)
138//! - [Linear](LinearDamping) and [angular](AngularDamping) velocity damping
139//! - [Lock translational and rotational axes](LockedAxes)
140//! - [Dominance]
141//! - [Automatic deactivation with sleeping](Sleeping)
142//!
143//! ### Collision detection
144//!
145//! - [Colliders](Collider)
146//! - [Creation](Collider#creation)
147//! - [Density](ColliderDensity)
148//! - [Friction] and [restitution](Restitution) (bounciness)
149//! - [Collision layers](CollisionLayers)
150//! - [Sensors](Sensor)
151#![cfg_attr(
152 feature = "3d",
153 doc = " - Creating colliders from meshes with [`AsyncCollider`] and [`AsyncSceneCollider`]"
154)]
155//! - [Get colliding entities](CollidingEntities)
156//! - [Collision events](ContactReportingPlugin#collision-events)
157//! - [Accessing, filtering and modifying collisions](Collisions)
158//! - [Manual contact queries](contact_query)
159//!
160//! ### Constraints and joints
161//!
162//! - [Constraints](constraints) (advanced)
163//! - [Joints](joints)
164//! - [Fixed joint](FixedJoint)
165//! - [Distance joint](DistanceJoint)
166//! - [Prismatic joint](PrismaticJoint)
167//! - [Revolute joint](RevoluteJoint)
168//! - [Spherical joint](SphericalJoint)
169//!
170//! Joint motors and articulations are not supported yet, but they will be implemented in a future release.
171//!
172//! ### Spatial queries
173//!
174//! - [Spatial query types](spatial_query)
175//! - [Raycasting](spatial_query#raycasting) and [`RayCaster`]
176//! - [Shapecasting](spatial_query#shapecasting) and [`ShapeCaster`]
177//! - [Point projection](spatial_query#point-projection)
178//! - [Intersection tests](spatial_query#intersection-tests)
179//! - [Spatial query filters](SpatialQueryFilter)
180//! - [The `SpatialQuery` system parameter](SpatialQuery)
181//!
182//! ### Configuration
183//!
184//! - [Gravity]
185//! - [Physics timestep](Physics#usage)
186//! - [Physics speed](Physics#physics-speed)
187//! - [Configure simulation fidelity with substeps](SubstepCount)
188//! - [Render physics objects for debugging](PhysicsDebugPlugin)
189//!
190//! ### Scheduling
191//!
192//! - [Schedules and sets](PhysicsSetupPlugin#schedules-and-sets)
193//! - [`PhysicsSet`]
194//! - [`PhysicsSchedule`] and [`PhysicsStepSet`]
195//! - [`SubstepSchedule`] and [`SubstepSet`]
196//! - [`PostProcessCollisions`] schedule
197//! - [`PrepareSet`]
198//! - [Configure the schedule used for running physics](PhysicsPlugins#custom-schedule)
199//! - [Pausing, resuming and stepping physics](Physics#pausing-resuming-and-stepping-physics)
200//! - [Usage on servers](#can-the-engine-be-used-on-servers)
201//!
202//! ### Architecture
203//!
204//! - [List of plugins and their responsibilities](PhysicsPlugins)
205//! - [What is Extended Position Based Dynamics?](#what-is-xpbd)
206//! - Extending and modifying the engine
207//! - [Custom plugins](PhysicsPlugins#custom-plugins)
208//! - [Custom constraints](constraints#custom-constraints)
209//! - [Custom joints](joints#custom-joints)
210//!
211//! ## Frequently asked questions
212//!
213//! - [How does Bevy XPBD compare to Rapier and bevy_rapier?](#how-does-bevy-xpbd-compare-to-rapier-and-bevy_rapier)
214//! - [Why is nothing happening?](#why-is-nothing-happening)
215//! - [Why is everything moving so slowly?](#why-is-everything-moving-so-slowly)
216//! - [Why did my rigid body suddenly vanish?](#why-did-my-rigid-body-suddenly-vanish)
217//! - [Why is performance so bad?](#why-is-performance-so-bad)
218//! - [Why does my camera following jitter?](#why-does-my-camera-following-jitter)
219//! - [Is there a character controller?](#is-there-a-character-controller)
220//! - [Why are there separate `Position` and `Rotation` components?](#why-are-there-separate-position-and-rotation-components)
221//! - [Can the engine be used on servers?](#can-the-engine-be-used-on-servers)
222//! - [Something else?](#something-else)
223//!
224//! ### How does Bevy XPBD compare to Rapier and bevy_rapier?
225//!
226//! Rapier is the biggest and most used physics engine in the Rust ecosystem, and it is currently
227//! the most mature and feature-rich option.
228//!
229//! `bevy_rapier` is a great physics integration for Bevy, but it does have several problems:
230//!
231//! - It has to maintain a separate physics world and synchronize a ton of data with Bevy each frame
232//! - The source code is difficult to inspect, as the vast majority of it is glue code and wrappers
233//! for Bevy
234//! - It has poor docs.rs documentation, and the documentation on rapier.rs is often outdated and
235//! missing features
236//! - It is hard to extend as it's not very modular or composable in design
237//! - Overall, it doesn't have a native ECS-like feel outside of its public API
238//!
239//! Bevy XPBD on the other hand is built *for* Bevy *with* Bevy, and it uses the ECS for both the internals
240//! and the public API. This removes the need for a separate physics world, reduces overhead, and makes
241//! the source code much more approachable and easy to inspect for Bevy users.
242//!
243//! In part thanks to Bevy's modular architecture and the ECS, Bevy XPBD is also highly composable,
244//! as it consists of several independent plugins and provides lots of options for configuration and extensions,
245//! from [custom schedules](PhysicsPlugins#custom-schedule) and [plugins](PhysicsPlugins#custom-plugins) to
246//! [custom joints](joints#custom-joints) and [constraints](constraints#custom-constraints).
247//!
248//! In terms of the physics implementation, Rapier uses an impulse/velocity based solver, while Bevy XPBD uses
249//! [Extended Position Based Dynamics](#what-is-xpbd). On paper, XPBD should be more stable and robust,
250//! but it hasn't been widely adopted in mainstream usage yet.
251//!
252//! One of the biggest disadvantages of Bevy XPBD is that it is still very young, so it can have lots of bugs,
253//! some missing features, and fewer community resources and third party crates. However, it is growing quite
254//! rapidly, and it is already pretty close to feature-parity with Rapier.
255//!
256//! At the end of the day, both engines are very solid options. If you are looking for a more mature and tested
257//! physics integration, `bevy_rapier` is the better choice, but if you prefer an engine with less overhead
258//! and a more native Bevy integration, consider using Bevy XPBD. Their core APIs are also quite similar,
259//! so switching between them should be straightforward.
260//!
261//! ### Why is nothing happening?
262//!
263//! Make sure you have added the [`PhysicsPlugins`] plugin group and you have given your rigid bodies
264//! a [`RigidBody`] component. See the [getting started](#getting-started) section.
265//!
266//! ### Why is everything moving so slowly?
267//!
268//! If your application is in 2D, you might be using pixels as length units. This will require you to use
269//! larger velocities and forces than you would in 3D. Make sure you set [`Gravity`] to some larger value
270//! as well, because its magnitude is 9.81 by default, which is tiny in pixels.
271//!
272//! Bevy XPBD doesn't have a "physics scale" yet, but it will most likely be added in the future
273//! so that it's possible to define some kind of pixels per meter configuration.
274//!
275//! ### Why did my rigid body suddenly vanish?
276//!
277//! Make sure to [give your rigid bodies some mass](RigidBody#adding-mass-properties), either by adding a [`Collider`]
278//! or a [`MassPropertiesBundle`]. If your bodies don't have any mass, any physical interaction is likely to
279//! instantly give them infinite velocity.
280//!
281//! Bevy XPBD should automatically print warnings when it detects bodies with an invalid mass or inertia.
282//!
283//! ### Why is performance so bad?
284//!
285//! Make sure you are building your project in release mode using `cargo build --release`.
286//!
287//! You can further optimize builds by setting the number of codegen units in your `Cargo.toml` to 1,
288//! although this will also increase build times.
289//!
290//! ```toml
291//! [profile.release]
292//! codegen-units = 1
293//! ```
294//!
295//! Note that Bevy XPBD simply isn't very optimized yet, and it mostly runs on a single thread for now.
296//! This will be addressed in future releases.
297//!
298//! ### Why does my camera following jitter?
299//!
300//! When you write a system that makes the camera follow a physics entity, you might notice some jitter.
301//!
302//! To fix this, the system needs to:
303//!
304//! - Run after physics so that it has the up-to-date position of the player.
305//! - Run before transform propagation so that your changes to the camera's `Transform` are written
306//! to the camera's `GlobalTransform` before the end of the frame.
307//!
308//! The following ordering constraints should resolve the issue.
309//!
310//! ```
311//! # use bevy::prelude::*;
312//! # use bevy::transform::TransformSystem;
313#![cfg_attr(feature = "2d", doc = "# use bevy_xpbd_2d::prelude::*;")]
314#![cfg_attr(feature = "3d", doc = "# use bevy_xpbd_3d::prelude::*;")]
315//! #
316//! # fn main() {
317//! # let mut app = App::new();
318//! #
319//! app.add_systems(
320//! PostUpdate,
321//! camera_follow_player
322//! .after(PhysicsSet::Sync)
323//! .before(TransformSystem::TransformPropagate),
324//! );
325//! # }
326//! #
327//! # fn camera_follow_player() {}
328//! ```
329//!
330//! ### Is there a character controller?
331//!
332//! Bevy XPBD does not have a built-in character controller, so if you need one,
333//! you will need to implement it yourself. However, third party character controllers
334//! like [`bevy_tnua`](https://github.com/idanarye/bevy-tnua) support Bevy XPBD, and [`bevy_mod_wanderlust`](https://github.com/PROMETHIA-27/bevy_mod_wanderlust)
335//! and others are also likely to get Bevy XPBD support soon.
336//!
337//! For custom character controllers, you can take a look at the
338#![cfg_attr(
339 feature = "2d",
340 doc = "[`dynamic_character_2d`] and [`kinematic_character_2d`] examples to get started."
341)]
342#![cfg_attr(
343 feature = "3d",
344 doc = "[`dynamic_character_3d`] and [`kinematic_character_3d`] examples to get started."
345)]
346//!
347#![cfg_attr(
348 feature = "2d",
349 doc = "[`dynamic_character_2d`]: https://github.com/Jondolf/bevy_xpbd/tree/main/crates/bevy_xpbd_2d/examples/dynamic_character_2d
350[`kinematic_character_2d`]: https://github.com/Jondolf/bevy_xpbd/tree/main/crates/bevy_xpbd_2d/examples/kinematic_character_2d"
351)]
352#![cfg_attr(
353 feature = "3d",
354 doc = "[`dynamic_character_3d`]: https://github.com/Jondolf/bevy_xpbd/tree/main/crates/bevy_xpbd_3d/examples/dynamic_character_3d
355[`kinematic_character_3d`]: https://github.com/Jondolf/bevy_xpbd/tree/main/crates/bevy_xpbd_3d/examples/kinematic_character_3d"
356)]
357//!
358//! ### Why are there separate `Position` and `Rotation` components?
359//!
360//! While `Transform` can be used for the vast majority of things, Bevy XPBD internally
361//! uses separate [`Position`] and [`Rotation`] components. These are automatically
362//! kept in sync by the [`SyncPlugin`].
363//!
364//! There are several reasons why the separate components are currently used.
365//!
366//! - Position and rotation should be global from the physics engine's point of view.
367//! - Transform scale and shearing can cause issues and rounding errors in physics.
368//! - Transform hierarchies can be problematic.
369//! - There is no `f64` version of `Transform`.
370//! - There is no 2D version of `Transform` (yet), and having a 2D version can optimize several computations.
371//! - When position and rotation are separate, we can technically have more systems running in parallel.
372//! - Only rigid bodies have rotation, particles typically don't (although we don't make a distinction yet).
373//!
374//! In external projects however, using [`Position`] and [`Rotation`] is only necessary when you
375//! need to manage positions in the [`SubstepSchedule`]. Elsewhere, you should be able to use `Transform`.
376//!
377//! There is also a possibility that we will revisit this if/when Bevy has a `Transform2d` component.
378//! Using `Transform` feels more idiomatic and simple, so it would be nice if it could be used directly
379//! as long as we can get around the drawbacks.
380//!
381//! ### Can the engine be used on servers?
382//!
383//! Yes! Networking often requires running the simulation in a specific schedule, and in Bevy XPBD you can
384//! [set the schedule that runs physics](PhysicsPlugins#custom-schedule) and [configure the timestep](Physics)
385//! to whatever you want.
386//!
387//! One configuration is to run the client in `FixedUpdate`, and to use a fixed timestep for [`Time<Physics>`](Physics)
388//! on both the server and the client to make sure the physics simulation is only advanced by one step
389//! each time the schedule runs.
390//!
391//! Note that while Bevy XPBD should be locally deterministic, it can produce slightly different results on different
392//! machines.
393//!
394//! ### Something else?
395//!
396//! Physics engines are very large and Bevy XPBD is young, so stability issues and bugs are to be expected.
397//!
398//! If you encounter issues, please consider first taking a look at the
399//! [issues on GitHub](https://github.com/Jondolf/bevy_xpbd/issues) and
400//! [open a new issue](https://github.com/Jondolf/bevy_xpbd/issues/new) if there already isn't one regarding your problem.
401//!
402//! You can also come and say hello on the [Bevy Discord server](https://discord.com/invite/gMUk5Ph).
403//! There you can find a bevy_xpbd thread on the crate-help channel where you can ask questions.
404//!
405//! ## What is XPBD?
406//!
407//! *XPBD* or *Extended Position Based Dynamics* is a physics simulation method that extends
408//! the traditional *PBD* to be more physically accurate and less dependent on time step size
409//! and iteration count.
410//!
411//! Unlike force or impulse based physics simulation methods, XPBD mostly operates at the position-level,
412//! which can produce more stable and reliable results, while allowing straightforward coupling
413//! of [rigid bodies](RigidBody), soft bodies and fluids.
414//!
415//! ### Simulation loop
416//!
417//! At a high level, XPBD consists of a broad phase followed by a substepping loop that handles position
418//! [integration](integrator), [constraint solving](solver), velocity updates, and a velocity solver that
419//! handles dynamic friction and restitution.
420//!
421//! It looks roughly like this:
422//!
423//! ```ignore
424//! while simulating:
425//! // Substep size
426//! h = ∆t / substep_count
427//!
428//! // Broad phase
429//! broad_collision_pairs = collect_collision_pairs()
430//!
431//! for substep_count:
432//! // Integrate
433//! for n particles and bodies:
434//! // Integrate position
435//! x_prev = x
436//! v = v + h * f_ext / m
437//! x = x + h * v
438//!
439//! // Integrate rotation
440//! q_prev = q
441//! ω = ω + h * I^-1 * (τ_ext - (ω x (I * ω)))
442//! q = q + h * 0.5 * [ω_x, ω_y, ω_z, 0] * q
443//! q = q / |q|
444//!
445//! // Narrow phase
446//! for pair in broad_collision_pairs:
447//! compute_contacts(pair)
448//!
449//! // Solve constraints (contacts, joints etc.)
450//! solve_constraints(particles and bodies)
451//!
452//! // Update velocities
453//! for n particles and bodies:
454//! v = (x - x_prev) / h
455//! ∆q = q * q_prev^-1
456//! ω = 2 * [∆q_x, ∆q_y, ∆q_z] / h
457//! ω = ∆q_w >= 0 ? ω : -ω
458//!
459//! // Solve velocity constraints (dynamic friction and restitution)
460//! solve_velocities(particles and bodies)
461//! ```
462//!
463//! where `h` is the substep size, `q` is the [rotation](Rotation) as a quaternion,
464//! `ω` is the [angular velocity](AngularVelocity), `I` is the [angular inertia tensor](`Inertia`) and `τ` is the
465//! [external torque](ExternalTorque).
466//!
467//! In Bevy XPBD, the simulation loop is handled by various plugins. The [`PhysicsSetupPlugin`] sets up
468//! the Bevy schedules[^1][^2] and sets[^3][^4][^5], the [`BroadPhasePlugin`] manages the broad phase, the [`IntegratorPlugin`]
469//! handles XPBD integration, and so on. You can find all of the plugins and their responsibilities [here](PhysicsPlugins).
470//!
471//! ### See also
472//!
473//! - [XPBD integration step](integrator)
474//! - [Constraints and how to create them](constraints)
475//! - [Schedules and sets used for the simulation loop](PhysicsSetupPlugin#schedules-and-sets)
476//!
477//! ### Learning resources
478//!
479//! If you want to learn more about XPBD, I recommend taking a look at some of the papers.
480//! Especially the first one from 2020 was used heavily for the simulation loop and constraints in Bevy XPBD.
481//!
482//! - XPBD: Müller M, Macklin M, Chentanez N, Jeschke S, Kim T. 2020. *[Detailed Rigid Body Simulation with Extended Position Based Dynamics](https://matthias-research.github.io/pages/publications/PBDBodies.pdf)*.
483//! - XPBD: Macklin M, Müller M, Chentanez N. 2016. *[XPBD: Position-Based Simulation of Compliant Constrained Dynamics](http://mmacklin.com/xpbd.pdf)*.
484//!
485//! The papers are quite academic, so you might instead prefer some videos and articles.
486//! The first one by Ten Minute Physics (Matthias Müller, one of the XPBD researchers) is great for understanding
487//! how XPBD differs from other simulation methods and how the constraints work.
488//!
489//! - Video: Ten Minute Physics. 2022. *[Getting ready to simulate the world with XPBD](https://youtu.be/jrociOAYqxA)*.
490//! - Notes: Nolan Tait. *[Bevy Physics: XPBD](https://taintedcoders.com/bevy/xpbd/)*.
491//! - Tutorial series: Johan Helsing. *[Tutorial: Making a physics engine with Bevy](https://johanhelsing.studio/posts/bevy-xpbd)*.
492//! (inspired this project)
493//!
494//! ## License
495//!
496//! Bevy XPBD is free and open source. All code in the Bevy XPBD repository is dual-licensed under either:
497//!
498//! - MIT License ([LICENSE-MIT](https://github.com/Jondolf/bevy_xpbd/blob/main/LICENSE-MIT)
499//! or <http://opensource.org/licenses/MIT>)
500//! - Apache License, Version 2.0 ([LICENSE-APACHE](https://github.com/Jondolf/bevy_xpbd/blob/main/LICENSE-APACHE)
501//! or <http://www.apache.org/licenses/LICENSE-2.0>)
502//!
503//! at your option.
504//!
505//! [^1]: [`PhysicsSchedule`]
506//!
507//! [^2]: [`SubstepSchedule`]
508//!
509//! [^3]: [`PhysicsSet`]
510//!
511//! [^4]: [`PhysicsStepSet`]
512//!
513//! [^5]: [`SubstepSet`]
514
515#![allow(rustdoc::invalid_rust_codeblocks)]
516#![warn(clippy::doc_markdown, missing_docs)]
517
518#[cfg(all(not(feature = "f32"), not(feature = "f64")))]
519compile_error!("either feature \"f32\" or \"f64\" must be enabled");
520
521#[cfg(all(feature = "f32", feature = "f64"))]
522compile_error!("feature \"f32\" and feature \"f64\" cannot be enabled at the same time");
523
524#[cfg(all(not(feature = "2d"), not(feature = "3d")))]
525compile_error!("either feature \"2d\" or \"3d\" must be enabled");
526
527#[cfg(all(feature = "2d", feature = "3d"))]
528compile_error!("feature \"2d\" and feature \"3d\" cannot be enabled at the same time");
529
530#[cfg(all(
531 feature = "default-collider",
532 feature = "f32",
533 not(feature = "parry-f32")
534))]
535compile_error!(
536 "feature \"default-collider\" requires the feature \"parry-f32\" when \"f32\" is enabled"
537);
538
539#[cfg(all(
540 feature = "default-collider",
541 feature = "f64",
542 not(feature = "parry-f64")
543))]
544compile_error!(
545 "feature \"default-collider\" requires the feature \"parry-f64\" when \"f64\" is enabled"
546);
547
548#[cfg(all(feature = "2d", feature = "parry-f32"))]
549pub extern crate parry2d as parry;
550
551#[cfg(all(feature = "2d", feature = "parry-f64"))]
552pub extern crate parry2d_f64 as parry;
553
554#[cfg(all(feature = "3d", feature = "parry-f32"))]
555pub extern crate parry3d as parry;
556
557#[cfg(all(feature = "3d", feature = "parry-f64"))]
558pub extern crate parry3d_f64 as parry;
559
560pub mod components;
561pub mod constraints;
562pub mod math;
563pub mod plugins;
564pub mod resources;
565
566/// Re-exports common components, bundles, resources, plugins and types.
567pub mod prelude {
568 #[cfg(feature = "debug-plugin")]
569 pub use crate::plugins::debug::*;
570 pub use crate::{
571 components::*,
572 constraints::{joints::*, *},
573 plugins::{
574 collision::{
575 broad_phase::BroadCollisionPairs,
576 contact_reporting::{Collision, CollisionEnded, CollisionStarted},
577 narrow_phase::NarrowPhaseConfig,
578 *,
579 },
580 prepare::{init_transforms, update_mass_properties, PrepareConfig, PreparePlugin},
581 setup::*,
582 solver::solve_constraint,
583 spatial_query::*,
584 *,
585 },
586 resources::*,
587 PhysicsSet, PostProcessCollisions,
588 };
589 pub(crate) use crate::{math::*, *};
590 pub use bevy_xpbd_derive::*;
591}
592
593mod utils;
594
595#[cfg(test)]
596mod tests;
597
598use bevy::{
599 app::PluginGroupBuilder,
600 ecs::schedule::{LogLevel, ScheduleLabel},
601 prelude::*,
602};
603#[allow(unused_imports)]
604use prelude::*;
605
606/// Responsible for advancing the physics simulation. This is run in [`PhysicsSet::StepSimulation`].
607///
608/// See [`PhysicsStepSet`] for the system sets that are run in this schedule.
609#[derive(Debug, Hash, PartialEq, Eq, Clone, ScheduleLabel)]
610pub struct PhysicsSchedule;
611
612/// The substepping schedule that runs in [`PhysicsStepSet::Substeps`].
613/// The number of substeps per physics step is configured through the [`SubstepCount`] resource.
614///
615/// See [`SubstepSet`] for the system sets that are run in this schedule.
616#[derive(Debug, Hash, PartialEq, Eq, Clone, ScheduleLabel)]
617pub struct SubstepSchedule;
618
619/// A schedule where you can add systems to filter or modify collisions
620/// using the [`Collisions`] resource.
621///
622/// The schedule is empty by default and runs in [`SubstepSet::PostProcessCollisions`].
623///
624/// ## Example
625///
626/// Below is an example of how you could add a system that filters collisions.
627///
628/// ```no_run
629/// use bevy::prelude::*;
630#[cfg_attr(feature = "2d", doc = "use bevy_xpbd_2d::prelude::*;")]
631#[cfg_attr(feature = "3d", doc = "use bevy_xpbd_3d::prelude::*;")]
632///
633/// #[derive(Component)]
634/// struct Invulnerable;
635///
636/// fn main() {
637/// App::new()
638/// .add_plugins((DefaultPlugins, PhysicsPlugins::default()))
639/// .add_systems(PostProcessCollisions, filter_collisions)
640/// .run();
641/// }
642///
643/// fn filter_collisions(mut collisions: ResMut<Collisions>, query: Query<(), With<Invulnerable>>) {
644/// // Remove collisions where one of the colliders has an `Invulnerable` component.
645/// // In a real project, this could be done more efficiently with collision layers.
646/// collisions.retain(|contacts| {
647/// !query.contains(contacts.entity1) && !query.contains(contacts.entity2)
648/// });
649/// }
650/// ```
651#[derive(Debug, Hash, PartialEq, Eq, Clone, ScheduleLabel)]
652pub struct PostProcessCollisions;
653
654/// High-level system sets for the main phases of the physics engine.
655/// You can use these to schedule your own systems before or after physics is run without
656/// having to worry about implementation details.
657///
658/// 1. `Prepare`: Responsible for initializing [rigid bodies](RigidBody) and [colliders](Collider) and
659/// updating several components.
660/// 2. `StepSimulation`: Responsible for advancing the simulation by running the steps in [`PhysicsStepSet`].
661/// 3. `Sync`: Responsible for synchronizing physics components with other data, like keeping [`Position`]
662/// and [`Rotation`] in sync with `Transform`.
663///
664/// ## See also
665///
666/// - [`PhysicsSchedule`]: Responsible for advancing the simulation in [`PhysicsSet::StepSimulation`].
667/// - [`PhysicsStepSet`]: System sets for the steps of the actual physics simulation loop, like
668/// the broad phase and the substepping loop.
669/// - [`SubstepSchedule`]: Responsible for running the substepping loop in [`PhysicsStepSet::Substeps`].
670/// - [`SubstepSet`]: System sets for the steps of the substepping loop, like position integration and
671/// the constraint solver.
672/// - [`PostProcessCollisions`]: Responsible for running the post-process collisions group in
673/// [`SubstepSet::PostProcessCollisions`]. Empty by default.
674#[derive(SystemSet, Clone, Copy, Debug, PartialEq, Eq, Hash)]
675pub enum PhysicsSet {
676 /// Responsible for initializing [rigid bodies](RigidBody) and [colliders](Collider) and
677 /// updating several components.
678 ///
679 /// See [`PreparePlugin`].
680 Prepare,
681 /// Responsible for advancing the simulation by running the steps in [`PhysicsStepSet`].
682 /// Systems in this set are run in the [`PhysicsSchedule`].
683 StepSimulation,
684 /// Responsible for synchronizing physics components with other data, like keeping [`Position`]
685 /// and [`Rotation`] in sync with `Transform`.
686 ///
687 /// See [`SyncPlugin`].
688 Sync,
689}
690
691/// System sets for the main steps in the physics simulation loop. These are typically run in the [`PhysicsSchedule`].
692///
693/// 1. Broad phase
694/// 2. Substeps
695/// 1. Integrate
696/// 2. Narrow phase
697/// 3. Solve positional and angular constraints
698/// 4. Update velocities
699/// 5. Solve velocity constraints (dynamic friction and restitution)
700/// 3. Report contacts (send collision events)
701/// 4. Sleeping
702/// 5. Spatial queries
703#[derive(SystemSet, Clone, Copy, Debug, PartialEq, Eq, Hash)]
704pub enum PhysicsStepSet {
705 /// Responsible for collecting pairs of potentially colliding entities into [`BroadCollisionPairs`] using
706 /// [AABB](ColliderAabb) intersection tests.
707 ///
708 /// See [`BroadPhasePlugin`].
709 BroadPhase,
710 /// Responsible for substepping, which is an inner loop inside a physics step.
711 ///
712 /// See [`SubstepSet`] and [`SubstepSchedule`].
713 Substeps,
714 /// Responsible for sending collision events and updating [`CollidingEntities`].
715 ///
716 /// See [`ContactReportingPlugin`].
717 ReportContacts,
718 /// Responsible for controlling when bodies should be deactivated and marked as [`Sleeping`].
719 ///
720 /// See [`SleepingPlugin`].
721 Sleeping,
722 /// Responsible for spatial queries like [raycasting](`RayCaster`) and shapecasting.
723 ///
724 /// See [`SpatialQueryPlugin`].
725 SpatialQuery,
726}
727
728/// System sets for the the steps in the inner substepping loop. These are typically run in the [`SubstepSchedule`].
729///
730/// 1. Integrate
731/// 2. Narrow phase
732/// 3. Post-process collisions
733/// 4. Solve positional and angular constraints
734/// 5. Update velocities
735/// 6. Solve velocity constraints (dynamic friction and restitution)
736/// 7. Store contact impulses in [`Collisions`].
737/// 8. Apply [`AccumulatedTranslation`] to positions.
738#[derive(SystemSet, Clone, Copy, Debug, PartialEq, Eq, Hash)]
739pub enum SubstepSet {
740 /// Responsible for integrating Newton's 2nd law of motion,
741 /// applying forces and moving entities according to their velocities.
742 ///
743 /// See [`IntegratorPlugin`].
744 Integrate,
745 /// Responsible for computing contacts between entities and sending collision events.
746 ///
747 /// See [`NarrowPhasePlugin`].
748 NarrowPhase,
749 /// Responsible for running the [`PostProcessCollisions`] schedule to allow user-defined systems
750 /// to filter and modify collisions.
751 ///
752 /// If you want to modify or remove collisions after [`SubstepSet::NarrowPhase`], you can
753 /// add custom systems to this set, or to [`PostProcessCollisions`].
754 ///
755 /// See [`NarrowPhasePlugin`].
756 PostProcessCollisions,
757 /// The [solver] iterates through [constraints] and solves them.
758 ///
759 /// **Note**: If you want to [create your own constraints](constraints#custom-constraints),
760 /// you should add them in [`SubstepSet::SolveUserConstraints`]
761 /// to avoid system order ambiguities.
762 ///
763 /// See [`SolverPlugin`].
764 SolveConstraints,
765 /// The [solver] iterates through custom [constraints] created by the user and solves them.
766 ///
767 /// You can [create new constraints](constraints#custom-constraints) by implementing [`XpbdConstraint`]
768 /// for a component and adding the [constraint system](solve_constraint) to this set.
769 ///
770 /// See [`SolverPlugin`].
771 SolveUserConstraints,
772 /// Responsible for updating velocities after [constraint](constraints) solving.
773 ///
774 /// See [`SolverPlugin`].
775 UpdateVelocities,
776 /// Responsible for applying dynamic friction, restitution and joint damping at the end of the
777 /// substepping loop.
778 ///
779 /// See [`SolverPlugin`].
780 SolveVelocities,
781 /// Contact impulses computed by the solver are stored in contacts in [`Collisions`].
782 ///
783 /// See [`SolverPlugin`].
784 StoreImpulses,
785 /// Responsible for applying translation accumulated during the substep.
786 ///
787 /// See [`SolverPlugin`].
788 ApplyTranslation,
789}