Skip to content

Commit eda5e6f

Browse files
committed
Merge remote-tracking branch 'dimforge/master' into custom-shape
2 parents 528f766 + 3c98610 commit eda5e6f

40 files changed

+903
-157
lines changed

.github/workflows/main.yml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ on:
88

99
env:
1010
CARGO_TERM_COLOR: always
11-
RUST_CACHE_KEY: rust-cache-20240617
11+
RUST_CACHE_KEY: rust-cache-20240701
12+
CARGO_PROFILE_DEV_DEBUG: none
1213

1314
jobs:
1415
check-fmt:
@@ -20,6 +21,18 @@ jobs:
2021
components: rustfmt
2122
- name: Check formatting
2223
run: cargo fmt -- --check
24+
doc:
25+
runs-on: ubuntu-latest
26+
env:
27+
RUSTDOCFLAGS: -D warnings
28+
steps:
29+
- uses: actions/checkout@v4
30+
- uses: dtolnay/rust-toolchain@stable
31+
- uses: Swatinem/rust-cache@v2
32+
with:
33+
prefix-key: ${{ env.RUST_CACHE_KEY }}
34+
- name: Cargo doc
35+
run: cargo doc
2336
test:
2437
runs-on: ubuntu-latest
2538
env:

CHANGELOG.md

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,37 @@
11
# Changelog
22

3-
## v0.27.0-rc.1 (18 June 2024)
3+
## Unreleased
44

5-
**This is an update to Rapier 0.20 which includes several stability improvements
5+
### Added
6+
7+
- Added a `TriMeshFlags` parameter for `ComputedColliderShape`,
8+
its default value is `TriMeshFlags::MERGE_DUPLICATE_VERTICES`,
9+
which was its hardcoded behaviour.
10+
11+
## v0.27.0 (07 July 2024)
12+
13+
**This is an update from rapier 0.19 to Rapier 0.21 which includes several stability improvements
614
and new features. Please have a look at the
7-
[0.20 changelog](https://github.com/dimforge/rapier/blob/master/CHANGELOG.md) of Rapier.**
15+
[0.20 and 0.21 changelogs](https://github.com/dimforge/rapier/blob/master/CHANGELOG.md) of Rapier.**
816

917
### Modified
1018

11-
- Update to rapier `0.20`.
19+
- Update from rapier `0.19` to rapier `0.21`.
20+
- Update to nalgebra `0.33`.
1221
- Update to bevy `0.14`.
1322
- Renamed `has_any_active_contacts` to `has_any_active_contact` for better consistency with rapier.
1423
- `ColliderDebugColor`'s property is now a `bevy::color::Hsla`.
15-
- Added serialization support for `CollisionGroups`, `SolverGroups`, `ContactForceEventThreshold`, `ContactSkin`.
24+
- `ImpulseJoint::data` and `MultibodyJoint::data` are now a more detailed enum `TypedJoint` instead of a `GenericJoint`.
25+
You can still access its inner `GenericJoint` with `.as_ref()` or `as_mut()`.
26+
- `data` fields from all joints (`FixedJoint`, …) are now public, and their getters removed.
1627

1728
### Added
1829

1930
- Derive `Debug` for `LockedAxes`.
2031
- Expose `is_sliding_down_slope` to both `MoveShapeOutput` and `KinematicCharacterControllerOutput`.
2132
- Added a First Person Shooter `character_controller` example for `bevy_rapier3d`.
33+
- Added serialization support for `CollisionGroups`, `SolverGroups`, `ContactForceEventThreshold`, `ContactSkin`.
34+
- Added `RapierContext::context.impulse_revolute_joint_angle` to compute the angle along a revolute joint’s principal axis.
2235

2336
### Fix
2437

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[workspace]
2-
members = ["bevy_rapier2d", "bevy_rapier3d"]
2+
members = ["bevy_rapier2d", "bevy_rapier3d", "bevy_rapier_benches3d"]
33
resolver = "2"
44

55
[profile.dev]

bevy_rapier2d/Cargo.toml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bevy_rapier2d"
3-
version = "0.27.0-rc.1"
3+
version = "0.27.0"
44
authors = ["Sébastien Crozet <[email protected]>"]
55
description = "2-dimensional physics engine in Rust, official Bevy plugin."
66
documentation = "http://docs.rs/bevy_rapier2d"
@@ -44,21 +44,23 @@ headless = []
4444
async-collider = ["bevy/bevy_asset", "bevy/bevy_scene"]
4545

4646
[dependencies]
47-
bevy = { version = "0.14.0", default-features = false }
47+
bevy = { version = "0.14", default-features = false }
4848
nalgebra = { version = "0.33", features = ["convert-glam027"] }
4949
rapier2d = "0.22"
5050
bitflags = "2.4"
5151
log = "0.4"
5252
serde = { version = "1", features = ["derive"], optional = true }
5353

5454
[dev-dependencies]
55-
bevy = { version = "0.14.0", default-features = false, features = [
55+
bevy = { version = "0.14", default-features = false, features = [
5656
"x11",
5757
"bevy_state",
5858
] }
5959
oorandom = "11"
6060
approx = "0.5.1"
6161
glam = { version = "0.27", features = ["approx"] }
62+
bevy-inspector-egui = "0.25.1"
63+
bevy_egui = "0.28.0"
6264

6365
[package.metadata.docs.rs]
6466
# Enable all the features when building the docs on docs.rs

bevy_rapier2d/examples/debug_despawn2.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,7 @@ fn spawn_cube(commands: &mut Commands, game: &mut Game) {
174174
block_entities[*i],
175175
RevoluteJointBuilder::new()
176176
.local_anchor1(anchor_1)
177-
.local_anchor2(anchor_2)
178-
.build(),
177+
.local_anchor2(anchor_2),
179178
))
180179
.id();
181180
game.current_cube_joints.push(id);

bevy_rapier2d/examples/testbed2.rs

Lines changed: 81 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ mod player_movement2;
1212
mod rope_joint2;
1313

1414
use bevy::prelude::*;
15+
use bevy_egui::{egui, EguiContexts, EguiPlugin};
16+
use bevy_inspector_egui::quick::WorldInspectorPlugin;
1517
use bevy_rapier2d::prelude::*;
1618

17-
#[derive(Debug, Clone, Eq, PartialEq, Default, Hash, States)]
19+
#[derive(Debug, Reflect, Clone, Copy, Eq, PartialEq, Default, Hash, States)]
1820
pub enum Examples {
1921
#[default]
2022
None,
@@ -25,25 +27,61 @@ pub enum Examples {
2527
Events2,
2628
Joints2,
2729
JointsDespawn2,
28-
LockedRotation2,
30+
LockedRotations2,
2931
MultipleColliders2,
3032
PlayerMovement2,
3133
}
3234

33-
#[derive(Resource, Default)]
35+
#[derive(Resource, Default, Reflect)]
3436
struct ExamplesRes {
3537
entities_before: Vec<Entity>,
3638
}
3739

40+
#[derive(Resource, Debug, Default, Reflect)]
41+
struct ExampleSelected(pub usize);
42+
43+
#[derive(Debug, Reflect)]
44+
struct ExampleDefinition {
45+
pub state: Examples,
46+
pub name: &'static str,
47+
}
48+
49+
impl From<(Examples, &'static str)> for ExampleDefinition {
50+
fn from((state, name): (Examples, &'static str)) -> Self {
51+
Self { state, name }
52+
}
53+
}
54+
55+
#[derive(Resource, Debug, Reflect)]
56+
struct ExampleSet(pub Vec<ExampleDefinition>);
57+
3858
fn main() {
3959
let mut app = App::new();
40-
app.init_state::<Examples>()
41-
.init_resource::<ExamplesRes>()
60+
app.init_resource::<ExamplesRes>()
4261
.add_plugins((
4362
DefaultPlugins,
63+
EguiPlugin,
4464
RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(10.0),
4565
RapierDebugRenderPlugin::default(),
66+
WorldInspectorPlugin::new(),
4667
))
68+
.register_type::<Examples>()
69+
.register_type::<ExamplesRes>()
70+
.register_type::<ExampleSelected>()
71+
.init_state::<Examples>()
72+
.insert_resource(ExampleSet(vec![
73+
(Examples::Boxes2, "Boxes3").into(),
74+
(Examples::RopeJoint2, "RopeJoint2").into(),
75+
(Examples::DebugDespawn2, "DebugDespawn2").into(),
76+
(Examples::Despawn2, "Despawn3").into(),
77+
(Examples::Events2, "Events3").into(),
78+
(Examples::Joints2, "Joints3").into(),
79+
(Examples::JointsDespawn2, "JointsDespawn3").into(),
80+
(Examples::LockedRotations2, "LockedRotations3").into(),
81+
(Examples::MultipleColliders2, "MultipleColliders3").into(),
82+
(Examples::PlayerMovement2, "PlayerMovement2").into(),
83+
]))
84+
.init_resource::<ExampleSelected>()
4785
//
4886
//boxes2
4987
.add_systems(
@@ -116,13 +154,13 @@ fn main() {
116154
//
117155
//locked rotations
118156
.add_systems(
119-
OnEnter(Examples::LockedRotation2),
157+
OnEnter(Examples::LockedRotations2),
120158
(
121159
locked_rotations2::setup_graphics,
122160
locked_rotations2::setup_physics,
123161
),
124162
)
125-
.add_systems(OnExit(Examples::LockedRotation2), cleanup)
163+
.add_systems(OnExit(Examples::LockedRotations2), cleanup)
126164
//
127165
//multiple colliders
128166
.add_systems(
@@ -162,7 +200,14 @@ fn main() {
162200
},
163201
)
164202
.add_systems(OnExit(Examples::None), init)
165-
.add_systems(Update, check_toggle);
203+
.add_systems(
204+
Update,
205+
(
206+
ui_example_system,
207+
change_example.run_if(resource_changed::<ExampleSelected>),
208+
)
209+
.chain(),
210+
);
166211

167212
app.run();
168213
}
@@ -187,25 +232,34 @@ fn cleanup(world: &mut World) {
187232
}
188233
}
189234

190-
fn check_toggle(
191-
state: Res<State<Examples>>,
235+
fn change_example(
236+
example_selected: Res<ExampleSelected>,
237+
examples_available: Res<ExampleSet>,
192238
mut next_state: ResMut<NextState<Examples>>,
193-
mouse_input: Res<ButtonInput<MouseButton>>,
194239
) {
195-
if mouse_input.just_pressed(MouseButton::Left) {
196-
let next = match *state.get() {
197-
Examples::None => Examples::Boxes2,
198-
Examples::Boxes2 => Examples::RopeJoint2,
199-
Examples::RopeJoint2 => Examples::DebugDespawn2,
200-
Examples::DebugDespawn2 => Examples::Despawn2,
201-
Examples::Despawn2 => Examples::Events2,
202-
Examples::Events2 => Examples::Joints2,
203-
Examples::Joints2 => Examples::JointsDespawn2,
204-
Examples::JointsDespawn2 => Examples::LockedRotation2,
205-
Examples::LockedRotation2 => Examples::MultipleColliders2,
206-
Examples::MultipleColliders2 => Examples::PlayerMovement2,
207-
Examples::PlayerMovement2 => Examples::Boxes2,
208-
};
209-
next_state.set(next);
210-
}
240+
next_state.set(examples_available.0[example_selected.0].state);
241+
}
242+
243+
fn ui_example_system(
244+
mut contexts: EguiContexts,
245+
mut current_example: ResMut<ExampleSelected>,
246+
examples_available: Res<ExampleSet>,
247+
) {
248+
egui::Window::new("Testbed").show(contexts.ctx_mut(), |ui| {
249+
let mut changed = false;
250+
egui::ComboBox::from_label("example")
251+
.width(150.0)
252+
.selected_text(examples_available.0[current_example.0].name)
253+
.show_ui(ui, |ui| {
254+
for (id, value) in examples_available.0.iter().enumerate() {
255+
changed = ui
256+
.selectable_value(&mut current_example.0, id, value.name)
257+
.changed()
258+
|| changed;
259+
}
260+
});
261+
if ui.button("Next").clicked() {
262+
current_example.0 = (current_example.0 + 1) % examples_available.0.len();
263+
}
264+
});
211265
}

bevy_rapier3d/Cargo.toml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bevy_rapier3d"
3-
version = "0.27.0-rc.1"
3+
version = "0.27.0"
44
authors = ["Sébastien Crozet <[email protected]>"]
55
description = "3-dimensional physics engine in Rust, official Bevy plugin."
66
documentation = "http://docs.rs/bevy_rapier3d"
@@ -45,22 +45,34 @@ headless = []
4545
async-collider = ["bevy/bevy_asset", "bevy/bevy_scene"]
4646

4747
[dependencies]
48-
bevy = { version = "0.14.0", default-features = false }
48+
bevy = { version = "0.14", default-features = false }
4949
nalgebra = { version = "0.33", features = ["convert-glam027"] }
5050
rapier3d = "0.22"
5151
bitflags = "2.4"
5252
log = "0.4"
5353
serde = { version = "1", features = ["derive"], optional = true }
5454

5555
[dev-dependencies]
56-
bevy = { version = "0.14.0", default-features = false, features = [
56+
bevy = { version = "0.14", default-features = false, features = [
5757
"x11",
5858
"tonemapping_luts",
5959
"bevy_state",
6060
] }
6161
approx = "0.5.1"
6262
glam = { version = "0.27", features = ["approx"] }
63+
bevy-inspector-egui = "0.25.1"
64+
bevy_egui = "0.28.0"
65+
divan = "0.1"
66+
bevy_rapier_benches3d = { version = "0.1", path = "../bevy_rapier_benches3d" }
6367

6468
[package.metadata.docs.rs]
6569
# Enable all the features when building the docs on docs.rs
6670
features = ["debug-render-3d", "serde-serialize"]
71+
72+
[[bench]]
73+
name = "cubes"
74+
harness = false
75+
76+
[[bench]]
77+
name = "many_pyramids3"
78+
harness = false

bevy_rapier3d/benches/common.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use bevy::app::App;
2+
use bevy_rapier_benches3d::common::{default_app, wait_app_start};
3+
4+
pub fn bench_app_updates(bencher: divan::Bencher, setup: impl Fn(&mut App)) {
5+
let mut app = default_app();
6+
setup(&mut app);
7+
wait_app_start(&mut app);
8+
9+
bencher.bench_local(|| {
10+
app.update();
11+
});
12+
}

bevy_rapier3d/benches/cubes.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//! Translated from avian benchmark.
2+
//!
3+
//! <https://github.com/Jondolf/avian/blob/81290423e146264120cf9711af716f6faf669717/crates/avian3d/benches/cubes.rs>
4+
5+
mod common;
6+
7+
use common::bench_app_updates;
8+
9+
use bevy::prelude::*;
10+
use bevy_rapier3d::math::*;
11+
use bevy_rapier3d::prelude::*;
12+
13+
fn setup_cubes(app: &mut App, size: u32) {
14+
app.add_systems(Startup, move |mut commands: Commands| {
15+
commands.spawn((
16+
RigidBody::Fixed,
17+
Transform::from_translation(-2.0 * Vect::Z),
18+
Collider::cuboid(100.0, 1.0, 100.0),
19+
));
20+
for x in 0..size {
21+
for z in 0..size {
22+
commands.spawn((
23+
RigidBody::Dynamic,
24+
Transform::from_translation(Vec3::new(x as f32, 2.0, z as f32)),
25+
Collider::cuboid(1.0, 1.0, 1.0),
26+
));
27+
}
28+
}
29+
});
30+
}
31+
32+
#[divan::bench(sample_count = 60, sample_size = 1)]
33+
fn cubes_3x3(bencher: divan::Bencher) {
34+
bench_app_updates(bencher, |app| setup_cubes(app, 3))
35+
}
36+
#[divan::bench(sample_count = 60, sample_size = 1)]
37+
fn cubes_5x5(bencher: divan::Bencher) {
38+
bench_app_updates(bencher, |app| setup_cubes(app, 5))
39+
}
40+
#[divan::bench(sample_count = 60, sample_size = 1)]
41+
fn cubes_10x10(bencher: divan::Bencher) {
42+
bench_app_updates(bencher, |app| setup_cubes(app, 10))
43+
}
44+
#[divan::bench(sample_count = 60, sample_size = 1)]
45+
fn cubes_20x20(bencher: divan::Bencher) {
46+
bench_app_updates(bencher, |app| setup_cubes(app, 20))
47+
}
48+
49+
fn main() {
50+
// Run registered benchmarks.
51+
divan::main();
52+
}

0 commit comments

Comments
 (0)