Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 87 additions & 31 deletions .github/workflows/bevy-rapier.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,16 @@ jobs:
- uses: Swatinem/rust-cache@v2
with:
workspaces: bindings/bevy_rapier
save-if: ${{ github.ref == 'refs/heads/master' }}
- run: sudo apt update && sudo apt-get install pkg-config libx11-dev libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev
- name: Cargo doc
run: cargo doc --no-deps
test:
clippy:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
dim: [2, 3]
env:
RUSTFLAGS: -D warnings
steps:
Expand All @@ -75,26 +80,77 @@ jobs:
- uses: Swatinem/rust-cache@v2
with:
workspaces: bindings/bevy_rapier
key: clippy-${{ matrix.dim }}d
save-if: ${{ github.ref == 'refs/heads/master' }}
- run: sudo apt update && sudo apt-get install pkg-config libx11-dev libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev
- name: Clippy
run: cargo clippy --verbose -p bevy_rapier${{ matrix.dim }}d --examples
- name: Clippy (debug-render, simd, serde)
run: cargo clippy --verbose -p bevy_rapier${{ matrix.dim }}d --features debug-render-${{ matrix.dim }}d,simd8,serde-serialize,picking-backend
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
dim: [2, 3]
env:
RUSTFLAGS: -D warnings
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: bindings/bevy_rapier
key: test-${{ matrix.dim }}d
save-if: ${{ github.ref == 'refs/heads/master' }}
- run: sudo apt update && sudo apt-get install pkg-config libx11-dev libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev
- name: Test
run: cargo test --verbose -p bevy_rapier${{ matrix.dim }}d
# Builds Bevy with its default features, so it gets a job of its own.
ambiguity-detection:
runs-on: ubuntu-latest
env:
RUSTFLAGS: -D warnings
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: bindings/bevy_rapier
save-if: ${{ github.ref == 'refs/heads/master' }}
- run: sudo apt update && sudo apt-get install pkg-config libx11-dev libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev
- run: cargo install cargo-all-features
- name: Clippy for bevy_rapier2d
run: cargo clippy --verbose -p bevy_rapier2d --examples
- name: Clippy for bevy_rapier3d
run: cargo clippy --verbose -p bevy_rapier3d --examples
- name: Clippy for bevy_rapier2d (debug-render, simd, serde)
run: cargo clippy --verbose -p bevy_rapier2d --features debug-render-2d,simd8,serde-serialize,picking-backend
- name: Clippy for bevy_rapier3d (debug-render, simd, serde)
run: cargo clippy --verbose -p bevy_rapier3d --features debug-render-3d,simd8,serde-serialize,picking-backend
- name: Test for bevy_rapier2d
run: cargo test --verbose -p bevy_rapier2d
- name: Test for bevy_rapier3d
run: cargo test --verbose -p bevy_rapier3d
- name: Test for no conflicting system order ambiguity
run: cargo run --bin ambiguity_detection
# Each chunk checks a quarter of the (crate, feature set) pairs. The chunks share one cache,
# saved by the first one.
check-all-features:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
chunk: [1, 2, 3, 4]
env:
RUSTFLAGS: -D warnings
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@v2
with:
tool: cargo-all-features
- uses: Swatinem/rust-cache@v2
with:
workspaces: bindings/bevy_rapier
shared-key: bevy-rapier-all-features
save-if: ${{ github.ref == 'refs/heads/master' && matrix.chunk == 1 }}
- run: sudo apt update && sudo apt-get install pkg-config libx11-dev libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev
- name: Check all features individually
run: cargo check-all-features
run: cargo check-all-features --n-chunks 4 --chunk ${{ matrix.chunk }} --chunk-granularity feature
test-wasm:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
dim: [2, 3]
env:
RUSTFLAGS: -D warnings
steps:
Expand All @@ -106,10 +162,10 @@ jobs:
- uses: Swatinem/rust-cache@v2
with:
workspaces: bindings/bevy_rapier
- name: Clippy bevy_rapier2d
run: cd bevy_rapier2d && cargo clippy --verbose --features bevy/webgl2 --target wasm32-unknown-unknown
- name: Clippy bevy_rapier3d
run: cd bevy_rapier3d && cargo clippy --verbose --features bevy/webgl2 --target wasm32-unknown-unknown
key: wasm-${{ matrix.dim }}d
save-if: ${{ github.ref == 'refs/heads/master' }}
- name: Clippy
run: cd bevy_rapier${{ matrix.dim }}d && cargo clippy --verbose --features bevy/webgl2 --target wasm32-unknown-unknown
dependencies:
runs-on: ubuntu-latest
steps:
Expand All @@ -118,25 +174,25 @@ jobs:
uses: EmbarkStudios/cargo-deny-action@v2
with:
manifest-path: bindings/bevy_rapier/Cargo.toml
# Checks the Bevy documentation snippets compile against the in-tree bevy_rapier. Both
# snippet crates are standalone workspaces sharing one target directory.
# Checks the Bevy documentation snippets compile against the in-tree bevy_rapier. Each
# snippet crate is a standalone workspace.
website-bevy-snippets:
runs-on: ubuntu-latest
env:
CARGO_TARGET_DIR: ${{ github.workspace }}/website/docs-examples/target
strategy:
fail-fast: false
matrix:
dim: [2, 3]
defaults:
run:
working-directory: website/docs-examples
working-directory: website/docs-examples/${{ matrix.dim }}d/bevy
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: |
website/docs-examples/2d/bevy -> ../../target
website/docs-examples/3d/bevy -> ../../target
workspaces: website/docs-examples/${{ matrix.dim }}d/bevy
key: snippets-${{ matrix.dim }}d
save-if: ${{ github.ref == 'refs/heads/master' }}
- run: sudo apt update && sudo apt-get install pkg-config libx11-dev libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev
- name: Check the 2D snippets
run: cd 2d/bevy && cargo check --examples
- name: Check the 3D snippets
run: cd 3d/bevy && cargo check --examples
- name: Check the snippets
run: cargo check --examples
89 changes: 58 additions & 31 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,72 @@
## Unreleased
## v0.36.0 (24 September 2026)

### Added

- `Multibody::remove_dof_coupling`, `Multibody::retain_dof_couplings` and
`Multibody::clear_dof_couplings` to remove DoF couplings.
- `rapier3d-urdf`: `UrdfLink::urdf_link_index` and `UrdfJoint::urdf_joint_index` (and related) map the
loaded links and joints to their URDF counterparts, even when empty links are squeezed.
- `rapier3d-mjcf`: `MjcfContactHooks::is_excluded` and `MjcfContactHooks::pair_override` to query the
contact rules of a model.
- Soft bodies: `SoftBodySet`, `SoftBody` and `SoftBodyBuilder` (ropes, cloth, trimeshes, volumes…),
simulated together with rigid bodies, contacts and joints; also on `PhysicsWorld`.
- Soft-body materials with plasticity, tearing and cutting (`SoftBodySet::tear`/`cut`); torn-off
pieces become soft bodies and report a `SoftBodyTearEvent`.
- Soft-body clusters (`SoftBodySet::add_cluster`): rigid proxies that joints and colliders attach to.
- Deformable colliders: `ColliderSet::insert_deformable` binds a `DEFORMABLE` trimesh (3D) or
polyline (2D) to a soft body through a `SoftMeshBinding`.
- Experimental FEM soft-body solver behind the new `fem` feature (`SoftBodySolver::Fem`).
- `IntegrationParameters::soft_bodies`, soft-body debug-render modes, and soft bodies in snapshots.
- `RigidBody(Builder)::additional_pgs_iterations`: extra PGS iterations per substep for a body's island.
- `DebugRenderMode::PSEUDO_NORMALS` draws the pseudo-normals of trimeshes and polylines.
- `ColliderBuilder::polyline_with_flags`, `RigidBodyHandle::is_invalid`, and a public
`CoefficientCombineRule::combine`.
- `PhysicsWorld::detect_collisions` (collision detection without stepping) and
`PhysicsWorld::remove_body_with_colliders`.
- `CCDSolver::invalidate_fixed_targets_cache`, for users calling `CCDSolver::solve_continuous` directly.
- `Multibody::remove_dof_coupling`, `retain_dof_couplings` and `clear_dof_couplings`.
- `rapier3d-urdf`: `UrdfLink::urdf_link_index` and `UrdfJoint::urdf_joint_index` (and
`merged_urdf_joint_indices`) map loaded links and joints to their URDF counterparts.
- `rapier3d-mjcf`: `MjcfContactHooks::is_excluded` and `pair_override` query a model's contact rules.
- Testbed: drag bodies with the mouse, a "Debug" tab for the debug-render settings, and a
"Smooth mesh colliders" option (3D).
- New C bindings (`bindings/c`): 2D/3D, f32/f64, a C11 header with C++ helpers, and a CMake package.

### Modified

- Update to parry 0.31: query results now report the hit sub-shape (e.g. the triangle of a trimesh).
- `PhysicsPipeline::step`, `RigidBodySet::remove`, `ColliderSet::remove`, `DebugRenderPipeline::render`
and `CCDSolver::solve_continuous` take the `SoftBodySet`.
- `EventHandler` has a new required method `handle_soft_body_tear_event`, and
`ChannelEventCollector::new` takes a sender for these events.
- `ContactPair::manifolds` and `solver_clusters` moved to `ContactPair::contacts`: use
`pair.manifolds()` or `pair.rigid()`.
- The rigid-contact fields of `ContactModificationContext` moved behind `ctx.rigid_mut()`.
- `SolverFlags::COMPUTE_IMPULSES` is renamed `COMPUTE_RIGID_IMPULSES`.
- `RigidBodyType::SoftFrame`: the rigid proxies of soft bodies, counted as dynamic by `is_dynamic`.
- `DebugRenderObject::SoftBody` variant, and new fields in `IntegrationParameters`,
`DebugRenderStyle` and `PhysicsWorld` (`soft_bodies`, `collision_pipeline`).
- `CCDSolver::solve_continuous` no longer takes `scene_changed`, and
`RigidBodyCcd::is_moving_fast` also takes the body's mass properties.
- Snapshots serialized with previous versions can't be loaded anymore.
- The `std` feature of `rapier2d` and `rapier2d-f64` now enables `parry2d/spade`.
- The C, Python, and JavaScript/TypeScript bindings moved to the `bindings/` directory.
- The `bevy_rapier2d` and `bevy_rapier3d` plugins now live in this repository, in `bindings/bevy_rapier`, and
build against the in-tree rapier crates.
- The `bevy_rapier2d` and `bevy_rapier3d` plugins now live in this repository, in `bindings/bevy_rapier`.
- Testbed: rigid-body axes are shown by default and polylines are drawn as thick lines (2D) or tubes (3D).

### Fixed

- `CollisionPipeline::step` no longer trips a debug assertion when a moving body touches another
collider.
- A zero-length step no longer corrupts the simulation: it only applies the user changes and runs
the collision detection.
- The CCD no longer sweeps against a stale list of fixed colliders after they were added, removed or
moved during a step where no body needed CCD.
- `KinematicCharacterController::solve_character_collision_impulses` now pushes every dynamic body
touched by a compound character, not only the last one.
- A step with `dt == 0` no longer produces NaNs: it only applies user changes and detects collisions.
- `CollisionPipeline::step` no longer trips a debug assertion when a moving body touches a collider.
- Enabling or disabling an impulse joint now updates the islands of its bodies.
- Multibody DoF couplings and disabled self-contacts are no longer lost when multibodies merge or split.
- `PhysicsPipeline::counters` now fills the contact pair, contact, and constraint counts.
- `rapier3d-urdf`: the fixed children of a squeezed empty link now stay rigidly attached together, and
the joint taking over the removed link's joint keeps its original pivot.
- 2D soft-body cluster proxies now follow counterclockwise rotations of their particles.
- The rigid colliders attached to soft-body cluster proxies no longer lag one step behind their proxy.
- The broad-phase AABBs of soft-body surfaces now match their end-of-step geometry.
- When the CCD splits a step, the end-of-step soft-body motion margin and soft-CCD AABBs now cover the
full next step instead of the last CCD pass.
- The CCD now also splits the first step of a fast body at its impact.
- The soft-body contact history driving the extra substeps now counts steps instead of CCD passes.
- The CCD fast-body check now divides the applied forces by the body's mass, so heavy bodies under
gravity are no longer flagged as fast.

### Modified

- The soft-body motion margin now only pads deformable colliders, not the rigid colliders of clusters.
- `RigidBodyCcd::is_moving_fast` now takes the mass-properties along with the forces.
- Multibody DoF couplings are no longer lost when multibodies merge or split, and disabled
self-contacts are no longer re-enabled when they merge.
- `PhysicsPipeline::counters` now fills the contact pair, contact and constraint counts.
- With `max_ccd_substeps > 1`: end-of-step AABBs cover the full next step, the step splitter uses
the current velocity, and heavy bodies under gravity are no longer flagged as fast.
- `SpringCoefficients` no longer divides by zero when `damping_ratio` is zero.
- `rapier3d-urdf`: `<origin rpy>` angles are now composed as fixed-axis roll-pitch-yaw, as specified.
- `rapier3d-urdf`: the fixed children of a squeezed empty link stay rigidly attached, and the joint
taking over the removed link's joint keeps its pivot.
- Testbed (3D): `camera_rotation` and `camera_fwd_dir` return the actual camera orientation.

## v0.35.3 (28 August 2026)

Expand Down
26 changes: 13 additions & 13 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ exclude = ["bindings/typescript", "bindings/bevy_rapier"]
resolver = "2"

[workspace.package]
version = "0.35.3"
version = "0.36.0"
authors = ["Sébastien Crozet <sebcrozet@dimforge.com>"]
homepage = "https://rapier.rs"
repository = "https://github.com/dimforge/rapier"
Expand Down Expand Up @@ -131,18 +131,18 @@ getrandom = { version = "0.2", features = ["js"] }
wasm-bindgen = "0.2"

# Internal crates (paths are relative to the workspace root)
rapier2d = { version = "0.35.2", path = "crates/rapier2d" }
rapier2d-f64 = { version = "0.35.2", path = "crates/rapier2d-f64" }
rapier3d = { version = "0.35.2", path = "crates/rapier3d" }
rapier3d-f64 = { version = "0.35.2", path = "crates/rapier3d-f64" }
rapier_testbed2d = { version = "0.35.2", path = "crates/rapier_testbed2d" }
rapier_testbed2d-f64 = { version = "0.35.2", path = "crates/rapier_testbed2d-f64" }
rapier_testbed3d = { version = "0.35.2", path = "crates/rapier_testbed3d" }
rapier_testbed3d-f64 = { version = "0.35.2", path = "crates/rapier_testbed3d-f64" }
rapier3d-urdf = { version = "0.35.2", path = "crates/rapier3d-urdf" }
rapier3d-meshloader = { version = "0.35.2", path = "crates/rapier3d-meshloader", default-features = false }
mjcf-rs = { version = "0.35.2", path = "crates/mjcf-rs" }
rapier3d-mjcf = { version = "0.35.2", path = "crates/rapier3d-mjcf" }
rapier2d = { version = "0.36.0", path = "crates/rapier2d" }
rapier2d-f64 = { version = "0.36.0", path = "crates/rapier2d-f64" }
rapier3d = { version = "0.36.0", path = "crates/rapier3d" }
rapier3d-f64 = { version = "0.36.0", path = "crates/rapier3d-f64" }
rapier_testbed2d = { version = "0.36.0", path = "crates/rapier_testbed2d" }
rapier_testbed2d-f64 = { version = "0.36.0", path = "crates/rapier_testbed2d-f64" }
rapier_testbed3d = { version = "0.36.0", path = "crates/rapier_testbed3d" }
rapier_testbed3d-f64 = { version = "0.36.0", path = "crates/rapier_testbed3d-f64" }
rapier3d-urdf = { version = "0.36.0", path = "crates/rapier3d-urdf" }
rapier3d-meshloader = { version = "0.36.0", path = "crates/rapier3d-meshloader", default-features = false }
mjcf-rs = { version = "0.36.0", path = "crates/mjcf-rs" }
rapier3d-mjcf = { version = "0.36.0", path = "crates/rapier3d-mjcf" }

# Dev
bincode = "1"
Expand Down
10 changes: 5 additions & 5 deletions bindings/bevy_rapier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ resolver = "2"

[workspace.dependencies]
# Build against the rapier crates of this repository so bevy_rapier always tracks the in-tree engine.
rapier2d = { version = "0.35.3", path = "../../crates/rapier2d" }
rapier3d = { version = "0.35.3", path = "../../crates/rapier3d" }
rapier3d-urdf = { version = "0.35.3", path = "../../crates/rapier3d-urdf" }
rapier3d-mjcf = { version = "0.35.3", path = "../../crates/rapier3d-mjcf" }
rapier3d-meshloader = { version = "0.35.3", path = "../../crates/rapier3d-meshloader", default-features = false }
rapier2d = { version = "0.36.0", path = "../../crates/rapier2d" }
rapier3d = { version = "0.36.0", path = "../../crates/rapier3d" }
rapier3d-urdf = { version = "0.36.0", path = "../../crates/rapier3d-urdf" }
rapier3d-mjcf = { version = "0.36.0", path = "../../crates/rapier3d-mjcf" }
rapier3d-meshloader = { version = "0.36.0", path = "../../crates/rapier3d-meshloader", default-features = false }

[profile.dev]
# Use slightly better optimization by default, as examples otherwise seem laggy.
Expand Down
2 changes: 1 addition & 1 deletion bindings/c/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.35.3+c.2
0.36.0+c.0
Loading
Loading