Skip to main content

rapier_viewport_plugin/
lib.rs

1//! Rapier 3D physics plugin for viewport-lib.
2//!
3//! Wraps [`rapier3d`] behind the [`RuntimePlugin`](viewport_lib::RuntimePlugin)
4//! trait so it runs inside a `ViewportRuntime` alongside any other viewport-lib
5//! plugin. The crate is intentionally a thin adapter: it owns the lifecycle
6//! integration and the `NodeId` translation layer, and re-exports [`rapier3d`]
7//! and [`parry3d`] so consumers use rapier's own types and builders directly.
8//!
9//! # Quick start
10//!
11//! ```rust,ignore
12//! use rapier_viewport_plugin::{RapierPlugin, RapierContactEvent, rapier3d::prelude::*};
13//! use viewport_lib::{FixedTimestep, ViewportRuntime};
14//!
15//! let mut rapier = RapierPlugin::new();
16//!
17//! // Build bodies and colliders with rapier's own builders.
18//! let floor_body = RigidBodyBuilder::fixed().build();
19//! let floor_collider = ColliderBuilder::halfspace(Vector::z_axis()).build();
20//! rapier.add_body(floor_id, floor_body, floor_collider);
21//!
22//! let box_body = RigidBodyBuilder::dynamic()
23//!     .translation(glam::Vec3::new(0.0, 0.0, 5.0))
24//!     .build();
25//! let box_collider = ColliderBuilder::cuboid(0.5, 0.5, 0.5)
26//!     .restitution(0.4)
27//!     .active_events(ActiveEvents::COLLISION_EVENTS)
28//!     .build();
29//! rapier.add_body(box_id, box_body, box_collider);
30//!
31//! let (prepare, simulate) = rapier.clone().into_plugins();
32//! let runtime = ViewportRuntime::new()
33//!     .with_fixed_timestep(FixedTimestep::new(120.0))
34//!     .with_plugin(prepare)
35//!     .with_plugin(simulate);
36//!
37//! // Per-frame:
38//! //   let output = runtime.step(&mut scene, &mut selection, &frame_ctx);
39//! //   for ev in output.events.drain::<RapierContactEvent>() { ... }
40//! ```
41//!
42//! For anything not in the curated API -- impulses, velocity get/set, joints,
43//! collision groups, sensor flags, locked axes, the query pipeline, character
44//! controllers, etc. -- reach in through [`RapierPlugin::with_body_mut`],
45//! [`RapierPlugin::with_collider_mut`], or [`RapierPlugin::with_state_mut`].
46//!
47//! # Architecture
48//!
49//! Two `RuntimePlugin` implementors share a single `Arc<Mutex<RapierState>>`:
50//!
51//! | Phase    | Plugin                  | What it does                                                  |
52//! |----------|-------------------------|---------------------------------------------------------------|
53//! | Prepare  | `RapierPreparePlugin`   | Syncs fixed and kinematic body transforms from scene -> rapier |
54//! | Simulate | `RapierSimulatePlugin`  | Calls `PhysicsPipeline::step`, writes dynamic bodies back     |
55//!
56//! The user-facing [`RapierPlugin`] keeps a third reference to the same state,
57//! so bodies can be added or removed at runtime while the simulation runs.
58
59pub mod events;
60pub mod plugin;
61pub mod state;
62
63pub use events::RapierContactEvent;
64pub use plugin::{RapierPlugin, RapierPreparePlugin, RapierSimulatePlugin};
65pub use state::RapierState;
66
67/// Re-export of the [`rapier3d`] crate so plugin consumers don't need a
68/// separate dependency (and can't accidentally pull in a different version
69/// than the plugin was built against).
70pub use rapier3d;
71
72/// Re-export of the [`parry3d`] crate (rapier's collision-detection backend).
73/// Useful for constructing custom shapes or query filters to pass through the
74/// escape hatches on [`RapierPlugin`].
75pub use parry3d;