Skip to content

Commit

Permalink
Merge remote-tracking branch 'vri/RapierContext_Component' into conte…
Browse files Browse the repository at this point in the history
…xt-component
  • Loading branch information
AnthonyTornetta committed Jul 27, 2024
2 parents dffa4b4 + cf165bd commit 1b6bf5f
Show file tree
Hide file tree
Showing 25 changed files with 609 additions and 79 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

## Unreleased

### Fix

- Fix a crash when using `TimestepMode::Interpolated` and removing colliders
during a frame which would not run a simulation step.

### Added

- Added a `TriMeshFlags` parameter for `ComputedColliderShape`,
its default value is `TriMeshFlags::MERGE_DUPLICATE_VERTICES`,
which was its hardcoded behaviour.

### Modified

- `RapierContext`, `RapierConfiguration` and `RenderToSimulationTime` are now a `Component`
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["bevy_rapier2d", "bevy_rapier3d"]
members = ["bevy_rapier2d", "bevy_rapier3d", "bevy_rapier_benches3d"]
resolver = "2"

[profile.dev]
Expand Down
2 changes: 2 additions & 0 deletions bevy_rapier2d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ bevy = { version = "0.14", default-features = false, features = [
oorandom = "11"
approx = "0.5.1"
glam = { version = "0.27", features = ["approx"] }
bevy-inspector-egui = "0.25.1"
bevy_egui = "0.28.0"

[package.metadata.docs.rs]
# Enable all the features when building the docs on docs.rs
Expand Down
108 changes: 81 additions & 27 deletions bevy_rapier2d/examples/testbed2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ mod player_movement2;
mod rope_joint2;

use bevy::prelude::*;
use bevy_egui::{egui, EguiContexts, EguiPlugin};
use bevy_inspector_egui::quick::WorldInspectorPlugin;
use bevy_rapier2d::prelude::*;

#[derive(Debug, Clone, Eq, PartialEq, Default, Hash, States)]
#[derive(Debug, Reflect, Clone, Copy, Eq, PartialEq, Default, Hash, States)]
pub enum Examples {
#[default]
None,
Expand All @@ -25,25 +27,61 @@ pub enum Examples {
Events2,
Joints2,
JointsDespawn2,
LockedRotation2,
LockedRotations2,
MultipleColliders2,
PlayerMovement2,
}

#[derive(Resource, Default)]
#[derive(Resource, Default, Reflect)]
struct ExamplesRes {
entities_before: Vec<Entity>,
}

#[derive(Resource, Debug, Default, Reflect)]
struct ExampleSelected(pub usize);

#[derive(Debug, Reflect)]
struct ExampleDefinition {
pub state: Examples,
pub name: &'static str,
}

impl From<(Examples, &'static str)> for ExampleDefinition {
fn from((state, name): (Examples, &'static str)) -> Self {
Self { state, name }
}
}

#[derive(Resource, Debug, Reflect)]
struct ExampleSet(pub Vec<ExampleDefinition>);

fn main() {
let mut app = App::new();
app.init_state::<Examples>()
.init_resource::<ExamplesRes>()
app.init_resource::<ExamplesRes>()
.add_plugins((
DefaultPlugins,
EguiPlugin,
RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(10.0),
RapierDebugRenderPlugin::default(),
WorldInspectorPlugin::new(),
))
.register_type::<Examples>()
.register_type::<ExamplesRes>()
.register_type::<ExampleSelected>()
.init_state::<Examples>()
.insert_resource(ExampleSet(vec![
(Examples::Boxes2, "Boxes3").into(),
(Examples::RopeJoint2, "RopeJoint2").into(),
(Examples::DebugDespawn2, "DebugDespawn2").into(),
(Examples::Despawn2, "Despawn3").into(),
(Examples::Events2, "Events3").into(),
(Examples::Joints2, "Joints3").into(),
(Examples::JointsDespawn2, "JointsDespawn3").into(),
(Examples::LockedRotations2, "LockedRotations3").into(),
(Examples::MultipleColliders2, "MultipleColliders3").into(),
(Examples::PlayerMovement2, "PlayerMovement2").into(),
]))
.init_resource::<ExampleSelected>()
//
//boxes2
.add_systems(
Expand Down Expand Up @@ -116,13 +154,13 @@ fn main() {
//
//locked rotations
.add_systems(
OnEnter(Examples::LockedRotation2),
OnEnter(Examples::LockedRotations2),
(
locked_rotations2::setup_graphics,
locked_rotations2::setup_physics,
),
)
.add_systems(OnExit(Examples::LockedRotation2), cleanup)
.add_systems(OnExit(Examples::LockedRotations2), cleanup)
//
//multiple colliders
.add_systems(
Expand Down Expand Up @@ -164,7 +202,14 @@ fn main() {
},
)
.add_systems(OnExit(Examples::None), init)
.add_systems(Update, check_toggle);
.add_systems(
Update,
(
ui_example_system,
change_example.run_if(resource_changed::<ExampleSelected>),
)
.chain(),
);

app.run();
}
Expand All @@ -189,25 +234,34 @@ fn cleanup(world: &mut World) {
}
}

fn check_toggle(
state: Res<State<Examples>>,
fn change_example(
example_selected: Res<ExampleSelected>,
examples_available: Res<ExampleSet>,
mut next_state: ResMut<NextState<Examples>>,
mouse_input: Res<ButtonInput<MouseButton>>,
) {
if mouse_input.just_pressed(MouseButton::Left) {
let next = match *state.get() {
Examples::None => Examples::Boxes2,
Examples::Boxes2 => Examples::RopeJoint2,
Examples::RopeJoint2 => Examples::DebugDespawn2,
Examples::DebugDespawn2 => Examples::Despawn2,
Examples::Despawn2 => Examples::Events2,
Examples::Events2 => Examples::Joints2,
Examples::Joints2 => Examples::JointsDespawn2,
Examples::JointsDespawn2 => Examples::LockedRotation2,
Examples::LockedRotation2 => Examples::MultipleColliders2,
Examples::MultipleColliders2 => Examples::PlayerMovement2,
Examples::PlayerMovement2 => Examples::Boxes2,
};
next_state.set(next);
}
next_state.set(examples_available.0[example_selected.0].state);
}

fn ui_example_system(
mut contexts: EguiContexts,
mut current_example: ResMut<ExampleSelected>,
examples_available: Res<ExampleSet>,
) {
egui::Window::new("Testbed").show(contexts.ctx_mut(), |ui| {
let mut changed = false;
egui::ComboBox::from_label("example")
.width(150.0)
.selected_text(examples_available.0[current_example.0].name)
.show_ui(ui, |ui| {
for (id, value) in examples_available.0.iter().enumerate() {
changed = ui
.selectable_value(&mut current_example.0, id, value.name)
.changed()
|| changed;
}
});
if ui.button("Next").clicked() {
current_example.0 = (current_example.0 + 1) % examples_available.0.len();
}
});
}
12 changes: 12 additions & 0 deletions bevy_rapier3d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,19 @@ bevy = { version = "0.14", default-features = false, features = [
] }
approx = "0.5.1"
glam = { version = "0.27", features = ["approx"] }
bevy-inspector-egui = "0.25.1"
bevy_egui = "0.28.0"
divan = "0.1"
bevy_rapier_benches3d = { version = "0.1", path = "../bevy_rapier_benches3d" }

[package.metadata.docs.rs]
# Enable all the features when building the docs on docs.rs
features = ["debug-render-3d", "serde-serialize"]

[[bench]]
name = "cubes"
harness = false

[[bench]]
name = "many_pyramids3"
harness = false
12 changes: 12 additions & 0 deletions bevy_rapier3d/benches/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use bevy::app::App;
use bevy_rapier_benches3d::common::{default_app, wait_app_start};

pub fn bench_app_updates(bencher: divan::Bencher, setup: impl Fn(&mut App)) {
let mut app = default_app();
setup(&mut app);
wait_app_start(&mut app);

bencher.bench_local(|| {
app.update();
});
}
52 changes: 52 additions & 0 deletions bevy_rapier3d/benches/cubes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//! Translated from avian benchmark.
//!
//! <https://github.com/Jondolf/avian/blob/81290423e146264120cf9711af716f6faf669717/crates/avian3d/benches/cubes.rs>

mod common;

use common::bench_app_updates;

use bevy::prelude::*;
use bevy_rapier3d::math::*;
use bevy_rapier3d::prelude::*;

fn setup_cubes(app: &mut App, size: u32) {
app.add_systems(Startup, move |mut commands: Commands| {
commands.spawn((
RigidBody::Fixed,
Transform::from_translation(-2.0 * Vect::Z),
Collider::cuboid(100.0, 1.0, 100.0),
));
for x in 0..size {
for z in 0..size {
commands.spawn((
RigidBody::Dynamic,
Transform::from_translation(Vec3::new(x as f32, 2.0, z as f32)),
Collider::cuboid(1.0, 1.0, 1.0),
));
}
}
});
}

#[divan::bench(sample_count = 60, sample_size = 1)]
fn cubes_3x3(bencher: divan::Bencher) {
bench_app_updates(bencher, |app| setup_cubes(app, 3))
}
#[divan::bench(sample_count = 60, sample_size = 1)]
fn cubes_5x5(bencher: divan::Bencher) {
bench_app_updates(bencher, |app| setup_cubes(app, 5))
}
#[divan::bench(sample_count = 60, sample_size = 1)]
fn cubes_10x10(bencher: divan::Bencher) {
bench_app_updates(bencher, |app| setup_cubes(app, 10))
}
#[divan::bench(sample_count = 60, sample_size = 1)]
fn cubes_20x20(bencher: divan::Bencher) {
bench_app_updates(bencher, |app| setup_cubes(app, 20))
}

fn main() {
// Run registered benchmarks.
divan::main();
}
28 changes: 28 additions & 0 deletions bevy_rapier3d/benches/many_pyramids3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//! Translated from rapier benchmark.
//!
//! <https://github.com/dimforge/rapier/blob/87ada34008f4a1a313ccf8c3040040bab4f10e69/benchmarks3d/many_pyramids3.rs>

mod common;

use bevy_rapier_benches3d::pyramids::setup_pyramids;
use common::bench_app_updates;

#[divan::bench(sample_count = 60, sample_size = 1)]
fn pyramid_1_with_height_2(bencher: divan::Bencher) {
bench_app_updates(bencher, |app| setup_pyramids(app, 1, 2));
}