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
5 changes: 4 additions & 1 deletion .github/workflows/rapier-ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,11 @@ jobs:
RUSTFLAGS: -D warnings
steps:
- uses: actions/checkout@v4
- run: sudo apt-get install -y cmake libxcb-composite0-dev
# Builds and verifies each crate the same way `cargo publish` does,
# catching bugs hidden by workspace feature unification.
- name: publish dry-run
run: ./publish-all.sh
run: ./publish.sh --dry-run
# Builds the docusaurus website (user guides + docs site).
website-build:
runs-on: ubuntu-latest
Expand Down
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
## Unreleased
## v0.33.0 (05 June 2026)

### Added

- New `mjcf-rs` and `rapier3d-mjcf` crates: a pure-Rust (no `libmujoco`/FFI) loader for the MuJoCo
MJCF XML format. `mjcf-rs` parses MJCF into a typed AST — resolving `<include>`, `<default>`
class inheritance, angle units, and the several rotation specs (`quat`, `axisangle`, `euler`,
`xyaxes`, `zaxis`) — and `rapier3d-mjcf` converts a model into rigid-bodies, colliders, and
joints via `MjcfRobot`. Meshes load behind the `stl`/`wavefront`/`msh` features, and visual
meshes support per-vertex normals with optional smoothing ([#936](https://github.com/dimforge/rapier/pull/936), [#943](https://github.com/dimforge/rapier/pull/943)).
- Python bindings for Rapier 2D/3D (`rapier-py-*` crates under `python/`), generated and published
as installable wheels ([#938](https://github.com/dimforge/rapier/pull/938)).
- New `PhysicsWorld` convenience wrapper bundling `RigidBodySet`, `ColliderSet`, the broad/narrow
phases, islands, joints, the CCD solver, gravity, and integration parameters in a single struct,
for simpler setup of basic simulations. It also exposes helpers for waking bodies (`wake_up`,
Expand Down Expand Up @@ -42,6 +50,8 @@

### Modified

- Unify version numbers for `rapier3d-urdf`, `rapier3d-meshloader`, and `rapier3d-mjcf` so they
follow the same versioning as the other libraries in the workspace.
- **Breaking (CCD solver direct callers only):** `CCDSolver::find_first_impact` and
`CCDSolver::predict_impacts_at_next_positions` now take an extra `hooks: &dyn PhysicsHooks`
argument. `PhysicsPipeline::step` callers are unaffected.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ default-members = [
resolver = "2"

[workspace.package]
version = "0.32.0"
version = "0.33.0"
authors = ["Sébastien Crozet <sebcrozet@dimforge.com>"]
homepage = "https://rapier.rs"
repository = "https://github.com/dimforge/rapier"
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ AI coding is extensively used for the implementation and maintenance of the foll
`rapier3d-mjcf`, as well as the Python bindings (`python/rapier-py*`), including their tests, examples, and docs.

We actively use AI assistance (with human reviews) for the following tasks:
- Documentation generation.
- Changelogs generation.
- Tests generation.
- CI configuration and scripts.
- Documentation generation.
- Changelogs generation.
- Tests generation.
- CI configuration and scripts.

We accept contributions involving AI coding as long as:
- They are verified to work properly by a human.
- The code quality is up to human-written code standards.
- Include non-regression tests whenever applicable (which itself can be AI-generated).
- They are verified to work properly by a human.
- The code quality is up to human-written code standards.
- Include non-regression tests whenever applicable (which itself can be AI-generated).

## Resources and discussions

Expand Down
12 changes: 6 additions & 6 deletions crates/rapier3d-meshloader/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[package]
name = "rapier3d-meshloader"
version = "0.13.0"
version.workspace = true
authors = ["Sébastien Crozet <sebcrozet@dimforge.com>"]
description = "STL file loader for the 3D rapier physics engine."
documentation = "https://docs.rs/rapier3d-meshloader"
homepage = "https://rapier.rs"
repository = "https://github.com/dimforge/rapier"
homepage.workspace = true
repository.workspace = true
readme = "README.md"
categories = [
"science",
Expand All @@ -15,8 +15,8 @@ categories = [
"wasm",
]
keywords = ["physics", "joints", "multibody", "robotics", "urdf"]
license = "Apache-2.0"
edition = "2024"
license.workspace = true
edition.workspace = true

[features]
default = ["stl", "collada", "wavefront"]
Expand All @@ -29,4 +29,4 @@ thiserror = "2"
profiling = "1.0"
mesh-loader = "0.1.13"

rapier3d = { version = "0.32.0", path = "../rapier3d" }
rapier3d = { version = "0.33.0", path = "../rapier3d" }
14 changes: 7 additions & 7 deletions crates/rapier3d-mjcf/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[package]
name = "rapier3d-mjcf"
version = "0.1.0"
version.workspace = true
authors = ["Sébastien Crozet <sebcrozet@dimforge.com>"]
description = "MuJoCo MJCF loader for the 3D rapier physics engine."
documentation = "https://docs.rs/rapier3d-mjcf"
homepage = "https://rapier.rs"
repository = "https://github.com/dimforge/rapier"
homepage.workspace = true
repository.workspace = true
readme = "README.md"
categories = [
"science",
Expand All @@ -15,8 +15,8 @@ categories = [
"wasm",
]
keywords = ["physics", "joints", "multibody", "robotics", "mjcf"]
license = "Apache-2.0"
edition = "2024"
license.workspace = true
edition.workspace = true

[features]
default = []
Expand All @@ -34,8 +34,8 @@ anyhow = "1"
bitflags = "2"

mjcf-rs = { version = "0.1.0", path = "../mjcf-rs" }
rapier3d = { version = "0.32.0", path = "../rapier3d" }
rapier3d-meshloader = { version = "0.13.0", path = "../rapier3d-meshloader", default-features = false, optional = true }
rapier3d = { version = "0.33.0", path = "../rapier3d" }
rapier3d-meshloader = { version = "0.33.0", path = "../rapier3d-meshloader", default-features = false, optional = true }

[dev-dependencies]
tempfile = "3"
14 changes: 7 additions & 7 deletions crates/rapier3d-urdf/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[package]
name = "rapier3d-urdf"
version = "0.13.0"
version.workspace = true
authors = ["Sébastien Crozet <sebcrozet@dimforge.com>"]
description = "URDF file loader for the 3D rapier physics engine."
documentation = "https://docs.rs/rapier3d-urdf"
homepage = "https://rapier.rs"
repository = "https://github.com/dimforge/rapier"
homepage.workspace = true
repository.workspace = true
readme = "README.md"
categories = [
"science",
Expand All @@ -15,8 +15,8 @@ categories = [
"wasm",
]
keywords = ["physics", "joints", "multibody", "robotics", "urdf"]
license = "Apache-2.0"
edition = "2024"
license.workspace = true
edition.workspace = true

[features]
stl = ["dep:rapier3d-meshloader", "rapier3d-meshloader/stl", "__meshloader_is_enabled"]
Expand All @@ -31,5 +31,5 @@ anyhow = "1"
bitflags = "2"
urdf-rs = "0.9"

rapier3d = { version = "0.32.0", path = "../rapier3d" }
rapier3d-meshloader = { version = "0.13.0", path = "../rapier3d-meshloader", default-features = false, optional = true }
rapier3d = { version = "0.33.0", path = "../rapier3d" }
rapier3d-meshloader = { version = "0.33.0", path = "../rapier3d-meshloader", default-features = false, optional = true }
4 changes: 2 additions & 2 deletions crates/rapier_testbed2d-f64/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rapier_testbed2d-f64"
version = "0.32.0"
version = "0.33.0"
authors = ["Sébastien Crozet <sebcrozet@dimforge.com>"]
description = "Testbed for the Rapier 2-dimensional physics engine in Rust."
homepage = "http://rapier.rs"
Expand Down Expand Up @@ -67,5 +67,5 @@ env_logger = "0.11"
[dependencies.rapier]
package = "rapier2d-f64"
path = "../rapier2d-f64"
version = "0.32.0"
version = "0.33.0"
features = ["serde-serialize", "debug-render", "profiler"]
4 changes: 2 additions & 2 deletions crates/rapier_testbed2d/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rapier_testbed2d"
version = "0.32.0"
version = "0.33.0"
authors = ["Sébastien Crozet <sebcrozet@dimforge.com>"]
description = "Testbed for the Rapier 2-dimensional physics engine in Rust."
homepage = "http://rapier.rs"
Expand Down Expand Up @@ -67,5 +67,5 @@ env_logger = "0.11"
[dependencies.rapier]
package = "rapier2d"
path = "../rapier2d"
version = "0.32.0"
version = "0.33.0"
features = ["serde-serialize", "debug-render", "profiler"]
4 changes: 2 additions & 2 deletions crates/rapier_testbed3d-f64/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rapier_testbed3d-f64"
version = "0.32.0"
version = "0.33.0"
authors = ["Sébastien Crozet <sebcrozet@dimforge.com>"]
description = "Testbed for the Rapier 3-dimensional physics engine in Rust."
homepage = "http://rapier.rs"
Expand Down Expand Up @@ -68,5 +68,5 @@ env_logger = "0.11"
[dependencies.rapier]
package = "rapier3d-f64"
path = "../rapier3d-f64"
version = "0.32.0"
version = "0.33.0"
features = ["serde-serialize", "debug-render", "profiler"]
4 changes: 2 additions & 2 deletions crates/rapier_testbed3d/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rapier_testbed3d"
version = "0.32.0"
version = "0.33.0"
authors = ["Sébastien Crozet <sebcrozet@dimforge.com>"]
description = "Testbed for the Rapier 3-dimensional physics engine in Rust."
homepage = "http://rapier.rs"
Expand Down Expand Up @@ -69,5 +69,5 @@ env_logger = "0.11"
[dependencies.rapier]
package = "rapier3d"
path = "../rapier3d"
version = "0.32.0"
version = "0.33.0"
features = ["serde-serialize", "debug-render", "profiler"]
1 change: 1 addition & 0 deletions examples2d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
authors = ["Sébastien Crozet <sebcrozet@dimforge.com>"]
edition = "2024"
default-run = "all_examples2"
publish = false

[features]
parallel = ["rapier2d/parallel", "rapier_testbed2d/parallel"]
Expand Down
1 change: 1 addition & 0 deletions examples3d-f64/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
authors = ["Sébastien Crozet <sebcrozet@dimforge.com>"]
edition = "2024"
default-run = "all_examples3-f64"
publish = false

[features]
parallel = ["rapier3d-f64/parallel", "rapier_testbed3d-f64/parallel"]
Expand Down
1 change: 1 addition & 0 deletions examples3d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
authors = ["Sébastien Crozet <sebcrozet@dimforge.com>"]
edition = "2024"
default-run = "all_examples3"
publish = false

[features]
parallel = ["rapier3d/parallel", "rapier_testbed3d/parallel"]
Expand Down
14 changes: 0 additions & 14 deletions publish-all.sh

This file was deleted.

97 changes: 97 additions & 0 deletions publish.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#! /bin/bash
#
# Publishes every rapier crate to crates.io with a single
# `cargo publish --workspace` invocation:
#
# - rapier2d / rapier3d / rapier2d-f64 / rapier3d-f64
# - rapier_testbed2d / rapier_testbed3d / rapier_testbed2d-f64 / rapier_testbed3d-f64
# - rapier3d-meshloader / rapier3d-urdf / mjcf-rs / rapier3d-mjcf
#
# Cargo computes the dependency order itself and waits for each crate to become
# available on the registry before publishing the ones that depend on it. The
# example crates and the python-binding crates are marked `publish = false`, so
# `--workspace` skips them.
#
# Why this script exists
# ----------------------
# The four main crates share a single source tree at `<repo>/src`, referenced
# from each manifest as `path = "../../src/lib.rs"`. The four testbed crates
# likewise share `<repo>/src_testbed` via `path = "../../src_testbed/lib.rs"`.
# Those paths point outside the crate directory, which `cargo publish` refuses
# to package.
#
# To work around it *only during publishing*, this script temporarily, for each
# affected crate:
# 1. rewrites the `[lib] path` to a crate-local one (e.g. `src/lib.rs`), and
# 2. creates a symlink inside the crate pointing at the shared source tree.
#
# Cargo follows the symlink and bundles the real source into each `.crate`. A
# trap restores the manifests and removes the symlinks on exit (including on
# error or Ctrl-C), leaving the tree exactly as it was.
#
# Extra arguments are forwarded to `cargo publish`, e.g.:
# ./publish.sh --dry-run
# ./publish.sh --token "$CARGO_TOKEN"
#
# Requires cargo >= 1.90 (for `cargo publish --workspace`).

set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$ROOT"

# Crates sharing `src/lib.rs`.
SRC_CRATES=(rapier2d rapier3d rapier2d-f64 rapier3d-f64)
# Crates sharing `src_testbed/lib.rs`.
TESTBED_CRATES=(rapier_testbed2d rapier_testbed3d rapier_testbed2d-f64 rapier_testbed3d-f64)

# Refuse to run on a dirty tree: the only diff during publishing must be our own
# temporary edits, so the restore at the end is guaranteed to be correct.
if [ -n "$(git status --porcelain)" ]; then
echo "error: working tree is not clean. Commit or stash changes before publishing." >&2
exit 1
fi

backup_dir="$(mktemp -d)"

cleanup() {
for crate in "${SRC_CRATES[@]}" "${TESTBED_CRATES[@]}"; do
# Remove the symlink we created (only if it is in fact a symlink).
for link in "crates/$crate/src" "crates/$crate/src_testbed"; do
[ -L "$link" ] && rm -f "$link"
done
# Restore the original manifest.
if [ -f "$backup_dir/$crate.Cargo.toml" ]; then
cp "$backup_dir/$crate.Cargo.toml" "crates/$crate/Cargo.toml"
fi
done
rm -rf "$backup_dir"
}
trap cleanup EXIT INT TERM

# Apply the temporary symlink layout: `shared_dir` lives at the repo root and is
# linked into each crate, while the manifest's `[lib] path` is made crate-local.
link_shared() {
local crate="$1" shared_dir="$2"
local manifest="crates/$crate/Cargo.toml"

cp "$manifest" "$backup_dir/$crate.Cargo.toml"

local tmp
tmp="$(mktemp)"
sed "s#path = \"\.\./\.\./$shared_dir/lib.rs\"#path = \"$shared_dir/lib.rs\"#" "$manifest" > "$tmp"
mv "$tmp" "$manifest"

ln -s "../../$shared_dir" "crates/$crate/$shared_dir"
}

for crate in "${SRC_CRATES[@]}"; do
link_shared "$crate" src
done
for crate in "${TESTBED_CRATES[@]}"; do
link_shared "$crate" src_testbed
done

# Publish the whole workspace. `--allow-dirty` is required because our temporary
# edits make the tree dirty; the clean-tree check above keeps that safe.
cargo publish --workspace --allow-dirty "$@"
2 changes: 1 addition & 1 deletion python/rapier-testbed/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "rapier-testbed"
version = "0.32.0"
version = "0.33.0"
description = "Panda3D-based visual testbed and example gallery for the Rapier Python bindings."
readme = "README.md"
license = { text = "Apache-2.0" }
Expand Down
11 changes: 0 additions & 11 deletions scripts/publish-extra-formats.sh

This file was deleted.

Loading
Loading