From 925671d0b38720ddd73fcf55f68304dda670f686 Mon Sep 17 00:00:00 2001 From: Jondolf Date: Sat, 8 Jul 2023 16:39:58 +0300 Subject: [PATCH 1/8] Initial update to Bevy 0.11 --- Cargo.toml | 8 ++ README.md | 5 +- crates/bevy_xpbd_2d/Cargo.toml | 6 +- crates/bevy_xpbd_2d/examples/chain_2d.rs | 7 +- .../bevy_xpbd_2d/examples/collision_layers.rs | 5 +- .../bevy_xpbd_2d/examples/fixed_joint_2d.rs | 5 +- crates/bevy_xpbd_2d/examples/move_marbles.rs | 7 +- .../examples/prismatic_joint_2d.rs | 5 +- crates/bevy_xpbd_2d/examples/ray_caster.rs | 7 +- .../examples/revolute_joint_2d.rs | 5 +- crates/bevy_xpbd_3d/Cargo.toml | 6 +- crates/bevy_xpbd_3d/examples/chain_3d.rs | 7 +- crates/bevy_xpbd_3d/examples/cubes.rs | 7 +- crates/bevy_xpbd_3d/examples/cubess.rs | 119 ++++++++++++++++++ .../examples/custom_broad_phase.rs | 6 +- .../examples/custom_constraint.rs | 7 +- .../bevy_xpbd_3d/examples/fixed_joint_3d.rs | 5 +- .../examples/prismatic_joint_3d.rs | 5 +- .../examples/revolute_joint_3d.rs | 5 +- crates/examples_common_2d/Cargo.toml | 7 +- crates/examples_common_2d/src/lib.rs | 22 +--- crates/examples_common_3d/Cargo.toml | 7 +- crates/examples_common_3d/src/lib.rs | 22 +--- src/collision.rs | 6 +- src/constraints/mod.rs | 2 +- src/lib.rs | 3 +- src/plugins/debug.rs | 4 +- src/plugins/integrator.rs | 2 +- src/plugins/mod.rs | 46 ++++++- src/plugins/prepare.rs | 3 +- src/plugins/setup.rs | 41 ++++-- src/plugins/solver.rs | 2 +- src/plugins/sync.rs | 2 +- src/tests.rs | 21 ++-- 34 files changed, 284 insertions(+), 133 deletions(-) create mode 100644 crates/bevy_xpbd_3d/examples/cubess.rs diff --git a/Cargo.toml b/Cargo.toml index e0953e5c..8135f738 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,5 +5,13 @@ members = [ ] resolver = "2" +[patch.crates-io] +bevy = { git = "https://github.com/bevyengine/bevy" } +nalgebra = { git = "https://github.com/dimforge/nalgebra" } +parry2d = { git = "https://github.com/Jondolf/parry", branch = "update-nalgebra" } +parry2d-f64 = { git = "https://github.com/Jondolf/parry", branch = "update-nalgebra" } +parry3d = { git = "https://github.com/Jondolf/parry", branch = "update-nalgebra" } +parry3d-f64 = { git = "https://github.com/Jondolf/parry", branch = "update-nalgebra" } + [profile.dev] opt-level = 1 # Use slightly better optimization, so examples work diff --git a/README.md b/README.md index 4fe4caec..d6024ce2 100644 --- a/README.md +++ b/README.md @@ -69,9 +69,8 @@ use bevy_xpbd_3d::prelude::*; fn main() { App::new() - .add_plugins(DefaultPlugins) - .add_plugins(PhysicsPlugins) - .add_startup_system(setup) + .add_plugins((DefaultPlugins, PhysicsPlugins::default())) + .add_systems(Startup, setup) .run(); } diff --git a/crates/bevy_xpbd_2d/Cargo.toml b/crates/bevy_xpbd_2d/Cargo.toml index 3de53217..8b10c423 100644 --- a/crates/bevy_xpbd_2d/Cargo.toml +++ b/crates/bevy_xpbd_2d/Cargo.toml @@ -28,17 +28,17 @@ required-features = [ "2d" ] [dependencies] bevy_xpbd_derive = { path = "../bevy_xpbd_derive", version = "0.1" } -bevy = { version = "0.10.1", default-features = false } +bevy = { version = "0.11.0-dev", default-features = false } bevy_prototype_debug_lines = { version = "0.10.1", optional = true } parry2d = { version = "0.13.1", optional = true } parry2d-f64 = { version = "0.13.1", optional = true } -nalgebra = { version = "0.32.2", features = [ "convert-glam023" ] } +nalgebra = { version = "0.32.2", features = [ "convert-glam024" ] } derive_more = "0.99" [dev-dependencies] examples_common_2d = { path = "../examples_common_2d" } approx = "0.5" -glam = { version = "0.23", features = [ "approx" ] } +glam = { version = "0.24", features = [ "approx" ] } insta = "1.0" itertools = "0.10" diff --git a/crates/bevy_xpbd_2d/examples/chain_2d.rs b/crates/bevy_xpbd_2d/examples/chain_2d.rs index 6039fb90..6fdfea24 100644 --- a/crates/bevy_xpbd_2d/examples/chain_2d.rs +++ b/crates/bevy_xpbd_2d/examples/chain_2d.rs @@ -6,13 +6,12 @@ use examples_common_2d::XpbdExamplePlugin; fn main() { App::new() - .add_plugins(DefaultPlugins) - .add_plugin(XpbdExamplePlugin) + .add_plugins((DefaultPlugins, XpbdExamplePlugin)) .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) .insert_resource(SubstepCount(50)) .insert_resource(Gravity(Vector::NEG_Y * 1000.0)) - .add_startup_system(setup) - .add_system(follow_mouse) + .add_systems(Startup, setup) + .add_systems(Update, follow_mouse) .run(); } diff --git a/crates/bevy_xpbd_2d/examples/collision_layers.rs b/crates/bevy_xpbd_2d/examples/collision_layers.rs index a5c7084f..8ce622c1 100644 --- a/crates/bevy_xpbd_2d/examples/collision_layers.rs +++ b/crates/bevy_xpbd_2d/examples/collision_layers.rs @@ -6,11 +6,10 @@ use examples_common_2d::XpbdExamplePlugin; fn main() { App::new() - .add_plugins(DefaultPlugins) - .add_plugin(XpbdExamplePlugin) + .add_plugins((DefaultPlugins, XpbdExamplePlugin)) .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) .insert_resource(Gravity(Vector::NEG_Y * 1000.0)) - .add_startup_system(setup) + .add_systems(Startup, setup) .run(); } diff --git a/crates/bevy_xpbd_2d/examples/fixed_joint_2d.rs b/crates/bevy_xpbd_2d/examples/fixed_joint_2d.rs index ec792c8a..dbcaf31b 100644 --- a/crates/bevy_xpbd_2d/examples/fixed_joint_2d.rs +++ b/crates/bevy_xpbd_2d/examples/fixed_joint_2d.rs @@ -4,12 +4,11 @@ use examples_common_2d::XpbdExamplePlugin; fn main() { App::new() - .add_plugins(DefaultPlugins) - .add_plugin(XpbdExamplePlugin) + .add_plugins((DefaultPlugins, XpbdExamplePlugin)) .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) .insert_resource(SubstepCount(50)) .insert_resource(Gravity(Vector::NEG_Y * 1000.0)) - .add_startup_system(setup) + .add_systems(Startup, setup) .run(); } diff --git a/crates/bevy_xpbd_2d/examples/move_marbles.rs b/crates/bevy_xpbd_2d/examples/move_marbles.rs index 6d489a61..50e313b7 100644 --- a/crates/bevy_xpbd_2d/examples/move_marbles.rs +++ b/crates/bevy_xpbd_2d/examples/move_marbles.rs @@ -6,13 +6,12 @@ use examples_common_2d::XpbdExamplePlugin; fn main() { App::new() - .add_plugins(DefaultPlugins) - .add_plugin(XpbdExamplePlugin) + .add_plugins((DefaultPlugins, XpbdExamplePlugin)) .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) .insert_resource(SubstepCount(6)) .insert_resource(Gravity(Vector::NEG_Y * 1000.0)) - .add_startup_system(setup) - .add_system(movement) + .add_systems(Startup, setup) + .add_systems(Update, movement) .run(); } diff --git a/crates/bevy_xpbd_2d/examples/prismatic_joint_2d.rs b/crates/bevy_xpbd_2d/examples/prismatic_joint_2d.rs index c5aa987d..9bc31532 100644 --- a/crates/bevy_xpbd_2d/examples/prismatic_joint_2d.rs +++ b/crates/bevy_xpbd_2d/examples/prismatic_joint_2d.rs @@ -4,12 +4,11 @@ use examples_common_2d::XpbdExamplePlugin; fn main() { App::new() - .add_plugins(DefaultPlugins) - .add_plugin(XpbdExamplePlugin) + .add_plugins((DefaultPlugins, XpbdExamplePlugin)) .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) .insert_resource(SubstepCount(50)) .insert_resource(Gravity(Vector::NEG_Y * 1000.0)) - .add_startup_system(setup) + .add_systems(Startup, setup) .run(); } diff --git a/crates/bevy_xpbd_2d/examples/ray_caster.rs b/crates/bevy_xpbd_2d/examples/ray_caster.rs index ee806822..3e97527a 100644 --- a/crates/bevy_xpbd_2d/examples/ray_caster.rs +++ b/crates/bevy_xpbd_2d/examples/ray_caster.rs @@ -11,11 +11,10 @@ use examples_common_2d::{bevy_prototype_debug_lines::*, *}; fn main() { App::new() - .add_plugins(DefaultPlugins) - .add_plugin(XpbdExamplePlugin) + .add_plugins((DefaultPlugins, XpbdExamplePlugin)) .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) - .add_system(render_rays) - .add_startup_system(setup) + .add_systems(render_rays) + .add_systems(Startup, setup) .run(); } diff --git a/crates/bevy_xpbd_2d/examples/revolute_joint_2d.rs b/crates/bevy_xpbd_2d/examples/revolute_joint_2d.rs index 2b202e1f..177c6289 100644 --- a/crates/bevy_xpbd_2d/examples/revolute_joint_2d.rs +++ b/crates/bevy_xpbd_2d/examples/revolute_joint_2d.rs @@ -4,12 +4,11 @@ use examples_common_2d::XpbdExamplePlugin; fn main() { App::new() - .add_plugins(DefaultPlugins) - .add_plugin(XpbdExamplePlugin) + .add_plugins((DefaultPlugins, XpbdExamplePlugin)) .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) .insert_resource(SubstepCount(50)) .insert_resource(Gravity(Vector::NEG_Y * 1000.0)) - .add_startup_system(setup) + .add_systems(Startup, setup) .run(); } diff --git a/crates/bevy_xpbd_3d/Cargo.toml b/crates/bevy_xpbd_3d/Cargo.toml index 32531a81..59472cee 100644 --- a/crates/bevy_xpbd_3d/Cargo.toml +++ b/crates/bevy_xpbd_3d/Cargo.toml @@ -28,17 +28,17 @@ required-features = [ "3d" ] [dependencies] bevy_xpbd_derive = { path = "../bevy_xpbd_derive", version = "0.1" } -bevy = { version = "0.10.1", default-features = false } +bevy = { version = "0.11.0-dev", default-features = false } bevy_prototype_debug_lines = { version = "0.10.1", optional = true, features = [ "3d" ] } parry3d = { version = "0.13.1", optional = true } parry3d-f64 = { version = "0.13.1", optional = true } -nalgebra = { version = "0.32.2", features = [ "convert-glam023" ] } +nalgebra = { version = "0.32.2", features = [ "convert-glam024" ] } derive_more = "0.99" [dev-dependencies] examples_common_3d = { path = "../examples_common_3d" } approx = "0.5" -glam = { version = "0.23", features = [ "approx" ] } +glam = { version = "0.24", features = [ "approx" ] } insta = "1.0" itertools = "0.10" diff --git a/crates/bevy_xpbd_3d/examples/chain_3d.rs b/crates/bevy_xpbd_3d/examples/chain_3d.rs index decef44b..27325cda 100644 --- a/crates/bevy_xpbd_3d/examples/chain_3d.rs +++ b/crates/bevy_xpbd_3d/examples/chain_3d.rs @@ -6,8 +6,7 @@ use examples_common_3d::XpbdExamplePlugin; fn main() { App::new() - .add_plugins(DefaultPlugins) - .add_plugin(XpbdExamplePlugin) + .add_plugins((DefaultPlugins, XpbdExamplePlugin)) .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) .insert_resource(Msaa::Sample4) .insert_resource(AmbientLight { @@ -16,8 +15,8 @@ fn main() { }) .insert_resource(SubstepCount(80)) .insert_resource(Gravity(Vector::NEG_Y * 9.81 * 2.0)) - .add_startup_system(setup) - .add_system(movement) + .add_systems(Startup, setup) + .add_systems(Update, movement) .run(); } diff --git a/crates/bevy_xpbd_3d/examples/cubes.rs b/crates/bevy_xpbd_3d/examples/cubes.rs index 4babb5a3..02a7dfa5 100644 --- a/crates/bevy_xpbd_3d/examples/cubes.rs +++ b/crates/bevy_xpbd_3d/examples/cubes.rs @@ -6,12 +6,11 @@ use examples_common_3d::XpbdExamplePlugin; fn main() { App::new() - .add_plugins(DefaultPlugins) - .add_plugin(XpbdExamplePlugin) + .add_plugins((DefaultPlugins, XpbdExamplePlugin)) .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) .insert_resource(Msaa::Sample4) - .add_startup_system(setup) - .add_system(movement) + .add_systems(Startup, setup) + .add_systems(Update, movement) .run(); } diff --git a/crates/bevy_xpbd_3d/examples/cubess.rs b/crates/bevy_xpbd_3d/examples/cubess.rs new file mode 100644 index 00000000..99a42142 --- /dev/null +++ b/crates/bevy_xpbd_3d/examples/cubess.rs @@ -0,0 +1,119 @@ +#![allow(clippy::unnecessary_cast)] + +use bevy::prelude::*; +use bevy_xpbd_3d::prelude::*; +use examples_common_3d::XpbdExamplePlugin; + +fn main() { + App::new() + .add_plugins((DefaultPlugins, XpbdExamplePlugin)) + .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) + .insert_resource(Msaa::Sample4) + .add_systems(Startup, setup) + .add_systems(Update, movement) + .run(); +} + +#[derive(Component)] +struct Cube; + +fn setup( + mut commands: Commands, + mut materials: ResMut>, + mut meshes: ResMut>, +) { + let cube_mesh = meshes.add(Mesh::from(shape::Cube { size: 1.0 })); + for x in -15..15 { + for y in -2..0 { + for z in -15..15 { + commands.spawn(( + PbrBundle { + mesh: cube_mesh.clone(), + material: materials.add(Color::rgb(0.7, 0.7, 0.8).into()), + transform: Transform::from_scale(Vec3::new(5.0, 1.25, 5.0)), + ..default() + }, + RigidBody::Kinematic, + LinearVelocity(Vec3::NEG_Y * 0.01), + Position(Vector::new( + x as Scalar * 4.0, + y as Scalar * 1.0, + z as Scalar * 4.0, + )), + Collider::cuboid(5.0, 1.25, 5.0), + )); + } + } + } + + let cube_size = 2.0; + + // Spawn cube stacks + for x in -2..2 { + for y in -2..2 { + for z in -2..2 { + let pos = Vector::new( + x as Scalar * (cube_size + 0.1), + y as Scalar * (cube_size + 0.1), + z as Scalar * (cube_size + 0.1), + ); + commands.spawn(( + PbrBundle { + mesh: cube_mesh.clone(), + material: materials.add(Color::rgb(0.2, 0.7, 0.9).into()), + transform: Transform::from_scale(Vec3::splat(cube_size as f32)), + ..default() + }, + RigidBody::Dynamic, + Position(pos + Vector::Y * 5.0), + Collider::cuboid(cube_size, cube_size, cube_size), + Cube, + )); + } + } + } + commands.spawn(RayCaster::new(Vec3::NEG_Y, Vec3::X).with_max_hits(1000000)); + commands.spawn(RayCaster::new(Vec3::NEG_Y, Vec3::X).with_max_hits(1000000)); + commands.spawn(RayCaster::new(Vec3::NEG_Y, Vec3::X).with_max_hits(1000000)); + commands.spawn(RayCaster::new(Vec3::NEG_Y, Vec3::X).with_max_hits(1000000)); + commands.spawn(RayCaster::new(Vec3::NEG_Y, Vec3::X).with_max_hits(1000000)); + commands.spawn(RayCaster::new(Vec3::NEG_Y, Vec3::X).with_max_hits(1000000)); + + // Directional light + commands.spawn(DirectionalLightBundle { + directional_light: DirectionalLight { + illuminance: 20_000.0, + shadows_enabled: true, + ..default() + }, + transform: Transform::default().looking_at(Vec3::new(-1.0, -2.5, -1.5), Vec3::Y), + ..default() + }); + + // Camera + commands.spawn(Camera3dBundle { + transform: Transform::from_translation(Vec3::new(0.0, 12.0, 40.0)) + .looking_at(Vec3::Y * 5.0, Vec3::Y), + ..default() + }); +} + +fn movement( + keyboard_input: Res>, + mut query: Query<&mut LinearVelocity, With>, +) { + for mut lin_vel in &mut query { + if keyboard_input.pressed(KeyCode::Up) { + lin_vel.z -= 0.15; + } + if keyboard_input.pressed(KeyCode::Down) { + lin_vel.z += 0.15; + } + if keyboard_input.pressed(KeyCode::Left) { + lin_vel.x -= 0.15; + } + if keyboard_input.pressed(KeyCode::Right) { + lin_vel.x += 0.15; + } + } +} diff --git a/crates/bevy_xpbd_3d/examples/custom_broad_phase.rs b/crates/bevy_xpbd_3d/examples/custom_broad_phase.rs index 3358a95d..f5f18339 100644 --- a/crates/bevy_xpbd_3d/examples/custom_broad_phase.rs +++ b/crates/bevy_xpbd_3d/examples/custom_broad_phase.rs @@ -11,13 +11,13 @@ fn main() { // Add PhysicsPlugins and replace default broad phase with our custom broad phase app.add_plugins( - PhysicsPlugins + PhysicsPlugins::default() .build() .disable::() .add(BruteForceBroadPhasePlugin), ); - app.add_startup_system(setup).run(); + app.add_systems(Startup, setup).run(); } // Modified from Bevy's 3d_scene example, a cube falling to the ground with velocity @@ -77,7 +77,7 @@ impl Plugin for BruteForceBroadPhasePlugin { .expect("add PhysicsSchedule first"); // Add the broad phase system into the broad phase set - physics_schedule.add_system(collect_collision_pairs.in_set(PhysicsSet::BroadPhase)); + physics_schedule.add_systems(collect_collision_pairs.in_set(PhysicsSet::BroadPhase)); } } diff --git a/crates/bevy_xpbd_3d/examples/custom_constraint.rs b/crates/bevy_xpbd_3d/examples/custom_constraint.rs index fadf866e..ef84fd16 100644 --- a/crates/bevy_xpbd_3d/examples/custom_constraint.rs +++ b/crates/bevy_xpbd_3d/examples/custom_constraint.rs @@ -5,15 +5,14 @@ fn main() { let mut app = App::new(); // Add plugins and startup system - app.add_plugins(DefaultPlugins) - .add_plugins(PhysicsPlugins) - .add_startup_system(setup); + app.add_plugins((DefaultPlugins, PhysicsPlugins::default())) + .add_systems(Startup, setup); // Get physics substep schedule and add our custom distance constraint let substeps = app .get_schedule_mut(SubstepSchedule) .expect("add SubstepSchedule first"); - substeps.add_system( + substeps.add_systems( solve_constraint::.in_set(SubstepSet::SolveUserConstraints), ); diff --git a/crates/bevy_xpbd_3d/examples/fixed_joint_3d.rs b/crates/bevy_xpbd_3d/examples/fixed_joint_3d.rs index 57c1d102..339089bc 100644 --- a/crates/bevy_xpbd_3d/examples/fixed_joint_3d.rs +++ b/crates/bevy_xpbd_3d/examples/fixed_joint_3d.rs @@ -4,12 +4,11 @@ use examples_common_3d::XpbdExamplePlugin; fn main() { App::new() - .add_plugins(DefaultPlugins) - .add_plugin(XpbdExamplePlugin) + .add_plugins((DefaultPlugins, XpbdExamplePlugin)) .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) .insert_resource(Msaa::Sample4) .insert_resource(SubstepCount(50)) - .add_startup_system(setup) + .add_systems(Startup, setup) .run(); } diff --git a/crates/bevy_xpbd_3d/examples/prismatic_joint_3d.rs b/crates/bevy_xpbd_3d/examples/prismatic_joint_3d.rs index d0f0dab5..fa15fd51 100644 --- a/crates/bevy_xpbd_3d/examples/prismatic_joint_3d.rs +++ b/crates/bevy_xpbd_3d/examples/prismatic_joint_3d.rs @@ -4,12 +4,11 @@ use examples_common_3d::XpbdExamplePlugin; fn main() { App::new() - .add_plugins(DefaultPlugins) - .add_plugin(XpbdExamplePlugin) + .add_plugins((DefaultPlugins, XpbdExamplePlugin)) .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) .insert_resource(Msaa::Sample4) .insert_resource(SubstepCount(50)) - .add_startup_system(setup) + .add_systems(Startup, setup) .run(); } diff --git a/crates/bevy_xpbd_3d/examples/revolute_joint_3d.rs b/crates/bevy_xpbd_3d/examples/revolute_joint_3d.rs index 3ba2901a..0724abed 100644 --- a/crates/bevy_xpbd_3d/examples/revolute_joint_3d.rs +++ b/crates/bevy_xpbd_3d/examples/revolute_joint_3d.rs @@ -4,12 +4,11 @@ use examples_common_3d::XpbdExamplePlugin; fn main() { App::new() - .add_plugins(DefaultPlugins) - .add_plugin(XpbdExamplePlugin) + .add_plugins((DefaultPlugins, XpbdExamplePlugin)) .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) .insert_resource(Msaa::Sample4) .insert_resource(SubstepCount(50)) - .add_startup_system(setup) + .add_systems(Startup, setup) .run(); } diff --git a/crates/examples_common_2d/Cargo.toml b/crates/examples_common_2d/Cargo.toml index c938f0af..42e11790 100644 --- a/crates/examples_common_2d/Cargo.toml +++ b/crates/examples_common_2d/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" debug-plugin = [] [dependencies] -bevy = { version = "0.10.1", default-features = false, features = [ +bevy = { version = "0.11.0-dev", default-features = false, features = [ "bevy_core_pipeline", "bevy_text", "bevy_ui", @@ -15,9 +15,10 @@ bevy = { version = "0.10.1", default-features = false, features = [ "bevy_render", "bevy_sprite", "bevy_pbr", + "tonemapping_luts", + "ktx2", + "zstd", "bevy_winit", "x11", # github actions runners don't have libxkbcommon installed, so can't use wayland ] } -bevy_screen_diagnostics = "0.2" -bevy_prototype_debug_lines = "0.10.1" bevy_xpbd_2d = { path = "../bevy_xpbd_2d", default-features = false } diff --git a/crates/examples_common_2d/src/lib.rs b/crates/examples_common_2d/src/lib.rs index 43eb6688..36f306f1 100644 --- a/crates/examples_common_2d/src/lib.rs +++ b/crates/examples_common_2d/src/lib.rs @@ -1,8 +1,4 @@ -pub extern crate bevy_prototype_debug_lines; - use bevy::prelude::*; -use bevy_prototype_debug_lines::DebugLinesPlugin; -use bevy_screen_diagnostics::{ScreenDiagnosticsPlugin, ScreenFrameDiagnosticsPlugin}; use bevy_xpbd_2d::prelude::*; #[derive(Default)] @@ -10,18 +6,12 @@ pub struct XpbdExamplePlugin; impl Plugin for XpbdExamplePlugin { fn build(&self, app: &mut App) { - app.add_plugins(PhysicsPlugins) - .add_plugin(ScreenDiagnosticsPlugin::default()) - .add_plugin(ScreenFrameDiagnosticsPlugin) + app.add_plugins(PhysicsPlugins::default()) .add_state::() - .add_system(bevy_xpbd_2d::pause.in_schedule(OnEnter(AppState::Paused))) - .add_system(bevy_xpbd_2d::resume.in_schedule(OnExit(AppState::Paused))) - .add_system(pause_button) - .add_system(step_button.run_if(in_state(AppState::Paused))); - #[cfg(not(feature = "debug-plugin"))] - { - app.add_plugin(DebugLinesPlugin::default()); - } + .add_systems(OnEnter(AppState::Paused), bevy_xpbd_2d::pause) + .add_systems(OnExit(AppState::Paused), bevy_xpbd_2d::resume) + .add_systems(Update, pause_button) + .add_systems(Update, step_button.run_if(in_state(AppState::Paused))); } } @@ -38,7 +28,7 @@ fn pause_button( keys: Res>, ) { if keys.just_pressed(KeyCode::P) { - let new_state = match current_state.0 { + let new_state = match current_state.get() { AppState::Paused => AppState::Running, AppState::Running => AppState::Paused, }; diff --git a/crates/examples_common_3d/Cargo.toml b/crates/examples_common_3d/Cargo.toml index 69103b40..df564254 100644 --- a/crates/examples_common_3d/Cargo.toml +++ b/crates/examples_common_3d/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" debug-plugin = [] [dependencies] -bevy = { version = "0.10.1", default-features = false, features = [ +bevy = { version = "0.11.0-dev", default-features = false, features = [ "bevy_core_pipeline", "bevy_text", "bevy_ui", @@ -15,9 +15,10 @@ bevy = { version = "0.10.1", default-features = false, features = [ "bevy_render", "bevy_sprite", "bevy_pbr", + "tonemapping_luts", + "ktx2", + "zstd", "bevy_winit", "x11", # github actions runners don't have libxkbcommon installed, so can't use wayland ] } -bevy_screen_diagnostics = "0.2" -bevy_prototype_debug_lines = "0.10.1" bevy_xpbd_3d = { path = "../bevy_xpbd_3d", default-features = false } diff --git a/crates/examples_common_3d/src/lib.rs b/crates/examples_common_3d/src/lib.rs index bb285524..e72a7b85 100644 --- a/crates/examples_common_3d/src/lib.rs +++ b/crates/examples_common_3d/src/lib.rs @@ -1,8 +1,4 @@ -pub extern crate bevy_prototype_debug_lines; - use bevy::prelude::*; -use bevy_prototype_debug_lines::DebugLinesPlugin; -use bevy_screen_diagnostics::{ScreenDiagnosticsPlugin, ScreenFrameDiagnosticsPlugin}; use bevy_xpbd_3d::prelude::*; #[derive(Default)] @@ -10,18 +6,12 @@ pub struct XpbdExamplePlugin; impl Plugin for XpbdExamplePlugin { fn build(&self, app: &mut App) { - app.add_plugins(PhysicsPlugins) - .add_plugin(ScreenDiagnosticsPlugin::default()) - .add_plugin(ScreenFrameDiagnosticsPlugin) + app.add_plugins(PhysicsPlugins::default()) .add_state::() - .add_system(bevy_xpbd_3d::pause.in_schedule(OnEnter(AppState::Paused))) - .add_system(bevy_xpbd_3d::resume.in_schedule(OnExit(AppState::Paused))) - .add_system(pause_button) - .add_system(step_button.run_if(in_state(AppState::Paused))); - #[cfg(not(feature = "debug-plugin"))] - { - app.add_plugin(DebugLinesPlugin::default()); - } + .add_systems(OnEnter(AppState::Paused), bevy_xpbd_3d::pause) + .add_systems(OnExit(AppState::Paused), bevy_xpbd_3d::resume) + .add_systems(Update, pause_button) + .add_systems(Update, step_button.run_if(in_state(AppState::Paused))); } } @@ -38,7 +28,7 @@ fn pause_button( keys: Res>, ) { if keys.just_pressed(KeyCode::P) { - let new_state = match current_state.0 { + let new_state = match current_state.get() { AppState::Paused => AppState::Running, AppState::Running => AppState::Paused, }; diff --git a/src/collision.rs b/src/collision.rs index 8256a553..9df4c506 100644 --- a/src/collision.rs +++ b/src/collision.rs @@ -3,15 +3,15 @@ use crate::prelude::*; /// A [collision event](Collider#collision-events) that is sent for each contact pair during the narrow phase. -#[derive(Clone, Debug, PartialEq)] +#[derive(Event, Clone, Debug, PartialEq)] pub struct Collision(pub Contact); /// A [collision event](Collider#collision-events) that is sent when two entities start colliding. -#[derive(Clone, Debug, PartialEq)] +#[derive(Event, Clone, Debug, PartialEq)] pub struct CollisionStarted(pub Entity, pub Entity); /// A [collision event](Collider#collision-events) that is sent when two entities stop colliding. -#[derive(Clone, Debug, PartialEq)] +#[derive(Event, Clone, Debug, PartialEq)] pub struct CollisionEnded(pub Entity, pub Entity); /// Data related to a contact between two bodies. diff --git a/src/constraints/mod.rs b/src/constraints/mod.rs index 0d4bd80f..30462886 100644 --- a/src/constraints/mod.rs +++ b/src/constraints/mod.rs @@ -73,7 +73,7 @@ //! .expect("add SubstepSchedule first"); //! //! // Add custom constraint -//! substeps.add_system( +//! substeps.add_systems( //! solve_constraint::.in_set(SubstepSet::SolveUserConstraints), //! ); //! ``` diff --git a/src/lib.rs b/src/lib.rs index fd080fdb..9b0e47be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -101,8 +101,7 @@ //! //! fn main() { //! App::new() -//! .add_plugins(DefaultPlugins) -//! .add_plugins(PhysicsPlugins) +//! .add_plugins((DefaultPlugins, PhysicsPlugins::default())) //! // ...your other plugins, systems and resources //! .run(); //! } diff --git a/src/plugins/debug.rs b/src/plugins/debug.rs index 93e29f05..779ad8d1 100644 --- a/src/plugins/debug.rs +++ b/src/plugins/debug.rs @@ -16,10 +16,10 @@ impl Plugin for PhysicsDebugPlugin { app.add_plugin(DebugLinesPlugin::default()) .init_resource::() .register_type::() - .add_system( + .add_systems( debug_render_aabbs.run_if(|config: Res| config.render_aabbs), ) - .add_system( + .add_systems( debug_render_contacts .run_if(|config: Res| config.render_contacts), ); diff --git a/src/plugins/integrator.rs b/src/plugins/integrator.rs index 1695714f..fc4130ca 100644 --- a/src/plugins/integrator.rs +++ b/src/plugins/integrator.rs @@ -22,7 +22,7 @@ impl Plugin for IntegratorPlugin { .add_systems((integrate_pos, integrate_rot).in_set(SubstepSet::Integrate)); app.get_schedule_mut(PhysicsSchedule) .expect("add PhysicsSchedule first") - .add_system( + .add_systems( clear_external_force_and_torque .after(PhysicsSet::Substeps) .before(PhysicsSet::Sleeping), diff --git a/src/plugins/mod.rs b/src/plugins/mod.rs index 69b868c9..e863e80d 100644 --- a/src/plugins/mod.rs +++ b/src/plugins/mod.rs @@ -67,6 +67,25 @@ use bevy::prelude::*; /// /// You can also find more information regarding the engine's general plugin architecture [here](plugins). /// +/// ## Custom schedule +/// +/// You can run the [`PhysicsSchedule`] in any schedule you want. +/// You can set the schedule when adding the plugin group: +/// +/// ```no_run +/// use bevy::prelude::*; +/// # #[cfg(feature = "2d")] +/// # use bevy_xpbd_2d::prelude::*; +/// # #[cfg(feature = "3d")] +/// use bevy_xpbd_3d::prelude::*; +/// +/// fn main() { +/// App::new() +/// .add_plugins((DefaultPlugins, PhysicsPlugins::new(FixedUpdate))) +/// .run(); +/// } +/// ``` +/// /// ## Custom plugins /// /// First, create a new plugin. If you want to run your systems in the engine's schedules, get either the [`PhysicsSchedule`] @@ -92,7 +111,7 @@ use bevy::prelude::*; /// .expect("add PhysicsSchedule first"); /// /// // Add the system into the broad phase system set -/// physics_schedule.add_system(collect_collision_pairs.in_set(PhysicsSet::BroadPhase)); +/// physics_schedule.add_systems(collect_collision_pairs.in_set(PhysicsSet::BroadPhase)); /// } /// } /// @@ -122,7 +141,7 @@ use bevy::prelude::*; /// /// // Add PhysicsPlugins and replace default broad phase with our custom broad phase /// app.add_plugins( -/// PhysicsPlugins +/// PhysicsPlugins::default() /// .build() /// .disable::() /// .add(CustomBroadPhasePlugin), @@ -134,7 +153,26 @@ use bevy::prelude::*; /// /// You can find a full working example /// [here](https://github.com/Jondolf/bevy_xpbd/blob/main/crates/bevy_xpbd_3d/examples/custom_broad_phase.rs). -pub struct PhysicsPlugins; +pub struct PhysicsPlugins { + schedule: Box, +} + +impl PhysicsPlugins { + /// Creates a [`PhysicsPlugins`] plugin group using the given schedule for running the [`PhysicsSchedule`]. + /// + /// The default schedule is `PostUpdate`. + pub fn new(schedule: S) -> Self { + Self { + schedule: Box::new(schedule), + } + } +} + +impl Default for PhysicsPlugins { + fn default() -> Self { + Self::new(PostUpdate) + } +} impl PluginGroup for PhysicsPlugins { fn build(self) -> PluginGroupBuilder { @@ -147,7 +185,7 @@ impl PluginGroup for PhysicsPlugins { } builder - .add(PhysicsSetupPlugin) + .add(PhysicsSetupPlugin::new(self.schedule)) .add(PreparePlugin) .add(BroadPhasePlugin) .add(IntegratorPlugin) diff --git a/src/plugins/prepare.rs b/src/plugins/prepare.rs index 8a705635..4d507775 100644 --- a/src/plugins/prepare.rs +++ b/src/plugins/prepare.rs @@ -19,8 +19,9 @@ pub struct PreparePlugin; impl Plugin for PreparePlugin { fn build(&self, app: &mut bevy::prelude::App) { - app.configure_set(ComponentInitSet.in_set(PhysicsSet::Prepare)); + app.configure_set(Update, ComponentInitSet.in_set(PhysicsSet::Prepare)); app.add_systems( + Update, (init_rigid_bodies, init_mass_properties, init_colliders).in_set(ComponentInitSet), ); diff --git a/src/plugins/setup.rs b/src/plugins/setup.rs index 0b0fb688..0be8d623 100644 --- a/src/plugins/setup.rs +++ b/src/plugins/setup.rs @@ -2,6 +2,8 @@ //! //! See [`PhysicsSetupPlugin`]. +use bevy::transform::TransformSystem; + use crate::prelude::*; /// Sets up the physics engine by initializing the necessary schedules, sets and resources. @@ -25,7 +27,26 @@ use crate::prelude::*; /// and it typically handles things like collision detection and constraint solving. /// /// [Substepping sets](SubstepSet) are added by the solver plugin if it is enabled. See [`SolverPlugin`] for more information. -pub struct PhysicsSetupPlugin; +pub struct PhysicsSetupPlugin { + schedule: Box, +} + +impl PhysicsSetupPlugin { + /// Creates a [`PhysicsSetupPlugin`] using the given schedule for running the [`PhysicsSchedule`]. + /// + /// The default schedule is `PostUpdate`. + pub fn new(schedule: S) -> Self { + Self { + schedule: Box::new(schedule), + } + } +} + +impl Default for PhysicsSetupPlugin { + fn default() -> Self { + Self::new(PostUpdate) + } +} impl Plugin for PhysicsSetupPlugin { fn build(&self, app: &mut App) { @@ -108,17 +129,19 @@ impl Plugin for PhysicsSetupPlugin { app.add_schedule(SubstepSchedule, substep_schedule); // Add system set for running physics schedule + let schedule = &self.schedule; app.configure_set( - FixedUpdateSet - .before(CoreSet::Update) - .in_base_set(CoreSet::PreUpdate), + schedule.dyn_clone(), + FixedUpdateSet.before(TransformSystem::TransformPropagate), + ); + app.add_systems( + schedule.dyn_clone(), + run_physics_schedule.in_set(FixedUpdateSet), ); - app.add_system(run_physics_schedule.in_set(FixedUpdateSet)); - app.add_system( - run_substep_schedule - .in_set(PhysicsSet::Substeps) - .in_schedule(PhysicsSchedule), + app.add_systems( + PhysicsSchedule, + run_substep_schedule.in_set(PhysicsSet::Substeps), ); } } diff --git a/src/plugins/solver.rs b/src/plugins/solver.rs index 7d0a3c15..f3b83d6c 100644 --- a/src/plugins/solver.rs +++ b/src/plugins/solver.rs @@ -216,7 +216,7 @@ fn penetration_constraints( /// .get_schedule_mut(SubstepSchedule) /// .expect("add SubstepSchedule first"); /// -/// substeps.add_system( +/// substeps.add_systems( /// solve_constraint:: /// .in_set(SubstepSet::SolveUserConstraints), /// ); diff --git a/src/plugins/sync.rs b/src/plugins/sync.rs index ac8aed83..18167c82 100644 --- a/src/plugins/sync.rs +++ b/src/plugins/sync.rs @@ -17,7 +17,7 @@ impl Plugin for SyncPlugin { fn build(&self, app: &mut bevy::prelude::App) { app.get_schedule_mut(PhysicsSchedule) .expect("add PhysicsSchedule first") - .add_system(sync_transforms.in_set(PhysicsSet::Sync)); + .add_systems(sync_transforms.in_set(PhysicsSet::Sync)); } } diff --git a/src/tests.rs b/src/tests.rs index da14f33d..b208f095 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -23,9 +23,11 @@ macro_rules! setup_insta { fn create_app() -> App { let mut app = App::new(); - app.add_plugins(MinimalPlugins); - app.add_plugins(PhysicsPlugins); - app.add_plugin(LogPlugin::default()); + app.add_plugins(( + MinimalPlugins, + PhysicsPlugins::default(), + LogPlugin::default(), + )); app.insert_resource(TimeUpdateStrategy::ManualInstant(Instant::now())); app } @@ -77,7 +79,6 @@ fn setup_cubes_simulation(mut commands: Commands) { #[test] fn it_loads_plugin_without_errors() -> Result<(), Box> { let mut app = create_app(); - app.setup(); for _ in 0..500 { tick_60_fps(&mut app); @@ -92,7 +93,7 @@ fn body_with_velocity_moves() { app.insert_resource(Gravity::ZERO); - app.add_startup_system(|mut commands: Commands| { + app.add_systems(Startup, |mut commands: Commands| { // move right at 1 unit per second commands.spawn(( SpatialBundle::default(), @@ -101,8 +102,6 @@ fn body_with_velocity_moves() { )); }); - app.setup(); - const UPDATES: usize = 500; for _ in 0..UPDATES { @@ -141,9 +140,7 @@ fn cubes_simulation_is_deterministic_across_machines() { setup_insta!(); let mut app = create_app(); - app.add_startup_system(setup_cubes_simulation); - - app.setup(); + app.add_systems(Startup, setup_cubes_simulation); const SECONDS: usize = 10; const UPDATES: usize = 60 * SECONDS; @@ -168,9 +165,7 @@ fn cubes_simulation_is_locally_deterministic() { fn run_cubes() -> Vec<(Id, Transform)> { let mut app = create_app(); - app.add_startup_system(setup_cubes_simulation); - - app.setup(); + app.add_systems(Startup, setup_cubes_simulation); const SECONDS: usize = 5; const UPDATES: usize = 60 * SECONDS; From 44c1fceb7fd42c99cf44908efc1a6ea0bd10321c Mon Sep 17 00:00:00 2001 From: Jondolf Date: Sun, 9 Jul 2023 14:14:53 +0300 Subject: [PATCH 2/8] Update Parry and Nalgebra --- Cargo.toml | 5 ----- crates/bevy_xpbd_2d/Cargo.toml | 6 +++--- crates/bevy_xpbd_3d/Cargo.toml | 6 +++--- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8135f738..3d1a64e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,11 +7,6 @@ resolver = "2" [patch.crates-io] bevy = { git = "https://github.com/bevyengine/bevy" } -nalgebra = { git = "https://github.com/dimforge/nalgebra" } -parry2d = { git = "https://github.com/Jondolf/parry", branch = "update-nalgebra" } -parry2d-f64 = { git = "https://github.com/Jondolf/parry", branch = "update-nalgebra" } -parry3d = { git = "https://github.com/Jondolf/parry", branch = "update-nalgebra" } -parry3d-f64 = { git = "https://github.com/Jondolf/parry", branch = "update-nalgebra" } [profile.dev] opt-level = 1 # Use slightly better optimization, so examples work diff --git a/crates/bevy_xpbd_2d/Cargo.toml b/crates/bevy_xpbd_2d/Cargo.toml index 8b10c423..057d949d 100644 --- a/crates/bevy_xpbd_2d/Cargo.toml +++ b/crates/bevy_xpbd_2d/Cargo.toml @@ -30,9 +30,9 @@ required-features = [ "2d" ] bevy_xpbd_derive = { path = "../bevy_xpbd_derive", version = "0.1" } bevy = { version = "0.11.0-dev", default-features = false } bevy_prototype_debug_lines = { version = "0.10.1", optional = true } -parry2d = { version = "0.13.1", optional = true } -parry2d-f64 = { version = "0.13.1", optional = true } -nalgebra = { version = "0.32.2", features = [ "convert-glam024" ] } +parry2d = { version = "0.13", optional = true } +parry2d-f64 = { version = "0.13", optional = true } +nalgebra = { version = "0.32", features = [ "convert-glam024" ] } derive_more = "0.99" [dev-dependencies] diff --git a/crates/bevy_xpbd_3d/Cargo.toml b/crates/bevy_xpbd_3d/Cargo.toml index 59472cee..5e89af4f 100644 --- a/crates/bevy_xpbd_3d/Cargo.toml +++ b/crates/bevy_xpbd_3d/Cargo.toml @@ -30,9 +30,9 @@ required-features = [ "3d" ] bevy_xpbd_derive = { path = "../bevy_xpbd_derive", version = "0.1" } bevy = { version = "0.11.0-dev", default-features = false } bevy_prototype_debug_lines = { version = "0.10.1", optional = true, features = [ "3d" ] } -parry3d = { version = "0.13.1", optional = true } -parry3d-f64 = { version = "0.13.1", optional = true } -nalgebra = { version = "0.32.2", features = [ "convert-glam024" ] } +parry3d = { version = "0.13", optional = true } +parry3d-f64 = { version = "0.13", optional = true } +nalgebra = { version = "0.32", features = [ "convert-glam024" ] } derive_more = "0.99" [dev-dependencies] From 81c02ff6e69d446c35fce6f8a6ff028b8fbed896 Mon Sep 17 00:00:00 2001 From: Jondolf Date: Sun, 9 Jul 2023 20:48:22 +0300 Subject: [PATCH 3/8] Remove accidental example --- crates/bevy_xpbd_3d/examples/cubess.rs | 119 ------------------------- 1 file changed, 119 deletions(-) delete mode 100644 crates/bevy_xpbd_3d/examples/cubess.rs diff --git a/crates/bevy_xpbd_3d/examples/cubess.rs b/crates/bevy_xpbd_3d/examples/cubess.rs deleted file mode 100644 index 99a42142..00000000 --- a/crates/bevy_xpbd_3d/examples/cubess.rs +++ /dev/null @@ -1,119 +0,0 @@ -#![allow(clippy::unnecessary_cast)] - -use bevy::prelude::*; -use bevy_xpbd_3d::prelude::*; -use examples_common_3d::XpbdExamplePlugin; - -fn main() { - App::new() - .add_plugins((DefaultPlugins, XpbdExamplePlugin)) - .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) - .insert_resource(Msaa::Sample4) - .add_systems(Startup, setup) - .add_systems(Update, movement) - .run(); -} - -#[derive(Component)] -struct Cube; - -fn setup( - mut commands: Commands, - mut materials: ResMut>, - mut meshes: ResMut>, -) { - let cube_mesh = meshes.add(Mesh::from(shape::Cube { size: 1.0 })); - for x in -15..15 { - for y in -2..0 { - for z in -15..15 { - commands.spawn(( - PbrBundle { - mesh: cube_mesh.clone(), - material: materials.add(Color::rgb(0.7, 0.7, 0.8).into()), - transform: Transform::from_scale(Vec3::new(5.0, 1.25, 5.0)), - ..default() - }, - RigidBody::Kinematic, - LinearVelocity(Vec3::NEG_Y * 0.01), - Position(Vector::new( - x as Scalar * 4.0, - y as Scalar * 1.0, - z as Scalar * 4.0, - )), - Collider::cuboid(5.0, 1.25, 5.0), - )); - } - } - } - - let cube_size = 2.0; - - // Spawn cube stacks - for x in -2..2 { - for y in -2..2 { - for z in -2..2 { - let pos = Vector::new( - x as Scalar * (cube_size + 0.1), - y as Scalar * (cube_size + 0.1), - z as Scalar * (cube_size + 0.1), - ); - commands.spawn(( - PbrBundle { - mesh: cube_mesh.clone(), - material: materials.add(Color::rgb(0.2, 0.7, 0.9).into()), - transform: Transform::from_scale(Vec3::splat(cube_size as f32)), - ..default() - }, - RigidBody::Dynamic, - Position(pos + Vector::Y * 5.0), - Collider::cuboid(cube_size, cube_size, cube_size), - Cube, - )); - } - } - } - commands.spawn(RayCaster::new(Vec3::NEG_Y, Vec3::X).with_max_hits(1000000)); - commands.spawn(RayCaster::new(Vec3::NEG_Y, Vec3::X).with_max_hits(1000000)); - commands.spawn(RayCaster::new(Vec3::NEG_Y, Vec3::X).with_max_hits(1000000)); - commands.spawn(RayCaster::new(Vec3::NEG_Y, Vec3::X).with_max_hits(1000000)); - commands.spawn(RayCaster::new(Vec3::NEG_Y, Vec3::X).with_max_hits(1000000)); - commands.spawn(RayCaster::new(Vec3::NEG_Y, Vec3::X).with_max_hits(1000000)); - - // Directional light - commands.spawn(DirectionalLightBundle { - directional_light: DirectionalLight { - illuminance: 20_000.0, - shadows_enabled: true, - ..default() - }, - transform: Transform::default().looking_at(Vec3::new(-1.0, -2.5, -1.5), Vec3::Y), - ..default() - }); - - // Camera - commands.spawn(Camera3dBundle { - transform: Transform::from_translation(Vec3::new(0.0, 12.0, 40.0)) - .looking_at(Vec3::Y * 5.0, Vec3::Y), - ..default() - }); -} - -fn movement( - keyboard_input: Res>, - mut query: Query<&mut LinearVelocity, With>, -) { - for mut lin_vel in &mut query { - if keyboard_input.pressed(KeyCode::Up) { - lin_vel.z -= 0.15; - } - if keyboard_input.pressed(KeyCode::Down) { - lin_vel.z += 0.15; - } - if keyboard_input.pressed(KeyCode::Left) { - lin_vel.x -= 0.15; - } - if keyboard_input.pressed(KeyCode::Right) { - lin_vel.x += 0.15; - } - } -} From 7de150616b0256ee1ee99c58d6594a4e769825f2 Mon Sep 17 00:00:00 2001 From: Jondolf Date: Sun, 9 Jul 2023 22:05:40 +0300 Subject: [PATCH 4/8] Change gap between cubes in `cubes` example --- crates/bevy_xpbd_3d/examples/cubes.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_xpbd_3d/examples/cubes.rs b/crates/bevy_xpbd_3d/examples/cubes.rs index 02a7dfa5..6197326d 100644 --- a/crates/bevy_xpbd_3d/examples/cubes.rs +++ b/crates/bevy_xpbd_3d/examples/cubes.rs @@ -44,9 +44,9 @@ fn setup( for y in -2..2 { for z in -2..2 { let pos = Vector::new( - x as Scalar * (cube_size + 0.1), - y as Scalar * (cube_size + 0.1), - z as Scalar * (cube_size + 0.1), + x as Scalar * (cube_size + 0.05), + y as Scalar * (cube_size + 0.05), + z as Scalar * (cube_size + 0.05), ); commands.spawn(( PbrBundle { From a29100cf97f7e195d92170e7a190aeda430aed98 Mon Sep 17 00:00:00 2001 From: Jondolf Date: Sun, 9 Jul 2023 23:00:13 +0300 Subject: [PATCH 5/8] Update to Bevy 0.11 release --- Cargo.toml | 3 --- crates/bevy_xpbd_2d/Cargo.toml | 2 +- crates/bevy_xpbd_3d/Cargo.toml | 2 +- crates/examples_common_2d/Cargo.toml | 2 +- crates/examples_common_3d/Cargo.toml | 2 +- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3d1a64e6..e0953e5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,5 @@ members = [ ] resolver = "2" -[patch.crates-io] -bevy = { git = "https://github.com/bevyengine/bevy" } - [profile.dev] opt-level = 1 # Use slightly better optimization, so examples work diff --git a/crates/bevy_xpbd_2d/Cargo.toml b/crates/bevy_xpbd_2d/Cargo.toml index 057d949d..586dde96 100644 --- a/crates/bevy_xpbd_2d/Cargo.toml +++ b/crates/bevy_xpbd_2d/Cargo.toml @@ -28,7 +28,7 @@ required-features = [ "2d" ] [dependencies] bevy_xpbd_derive = { path = "../bevy_xpbd_derive", version = "0.1" } -bevy = { version = "0.11.0-dev", default-features = false } +bevy = { version = "0.11", default-features = false } bevy_prototype_debug_lines = { version = "0.10.1", optional = true } parry2d = { version = "0.13", optional = true } parry2d-f64 = { version = "0.13", optional = true } diff --git a/crates/bevy_xpbd_3d/Cargo.toml b/crates/bevy_xpbd_3d/Cargo.toml index 5e89af4f..3a31895a 100644 --- a/crates/bevy_xpbd_3d/Cargo.toml +++ b/crates/bevy_xpbd_3d/Cargo.toml @@ -28,7 +28,7 @@ required-features = [ "3d" ] [dependencies] bevy_xpbd_derive = { path = "../bevy_xpbd_derive", version = "0.1" } -bevy = { version = "0.11.0-dev", default-features = false } +bevy = { version = "0.11", default-features = false } bevy_prototype_debug_lines = { version = "0.10.1", optional = true, features = [ "3d" ] } parry3d = { version = "0.13", optional = true } parry3d-f64 = { version = "0.13", optional = true } diff --git a/crates/examples_common_2d/Cargo.toml b/crates/examples_common_2d/Cargo.toml index 42e11790..3e424387 100644 --- a/crates/examples_common_2d/Cargo.toml +++ b/crates/examples_common_2d/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" debug-plugin = [] [dependencies] -bevy = { version = "0.11.0-dev", default-features = false, features = [ +bevy = { version = "0.11", default-features = false, features = [ "bevy_core_pipeline", "bevy_text", "bevy_ui", diff --git a/crates/examples_common_3d/Cargo.toml b/crates/examples_common_3d/Cargo.toml index df564254..925a2f89 100644 --- a/crates/examples_common_3d/Cargo.toml +++ b/crates/examples_common_3d/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" debug-plugin = [] [dependencies] -bevy = { version = "0.11.0-dev", default-features = false, features = [ +bevy = { version = "0.11", default-features = false, features = [ "bevy_core_pipeline", "bevy_text", "bevy_ui", From d1c6483648f5939b7865b8f55771b2e722ac26d0 Mon Sep 17 00:00:00 2001 From: Jondolf Date: Sun, 9 Jul 2023 23:50:17 +0300 Subject: [PATCH 6/8] Replace `bevy_prototype_debug_lines` with `bevy_gizmos` --- crates/bevy_xpbd_2d/Cargo.toml | 3 +- crates/bevy_xpbd_2d/examples/ray_caster.rs | 20 +++----- crates/bevy_xpbd_3d/Cargo.toml | 3 +- crates/examples_common_2d/Cargo.toml | 1 + crates/examples_common_3d/Cargo.toml | 1 + src/math/mod.rs | 7 +++ src/plugins/debug.rs | 59 +++++++++++++--------- 7 files changed, 52 insertions(+), 42 deletions(-) diff --git a/crates/bevy_xpbd_2d/Cargo.toml b/crates/bevy_xpbd_2d/Cargo.toml index 586dde96..555cba48 100644 --- a/crates/bevy_xpbd_2d/Cargo.toml +++ b/crates/bevy_xpbd_2d/Cargo.toml @@ -16,7 +16,7 @@ default = [ "2d", "f32", "collider-from-mesh" ] 2d = [] f32 = [ "dep:parry2d" ] f64 = [ "dep:parry2d-f64" ] -debug-plugin = [ "dep:bevy_prototype_debug_lines", "examples_common_2d/debug-plugin" ] +debug-plugin = [ "bevy/bevy_gizmos" ] simd = [ "parry2d?/simd-stable", "parry2d-f64?/simd-stable" ] enhanced-determinism = [ "parry2d?/enhanced-determinism", "parry2d-f64?/enhanced-determinism" ] collider-from-mesh = [ "bevy/bevy_render" ] @@ -29,7 +29,6 @@ required-features = [ "2d" ] [dependencies] bevy_xpbd_derive = { path = "../bevy_xpbd_derive", version = "0.1" } bevy = { version = "0.11", default-features = false } -bevy_prototype_debug_lines = { version = "0.10.1", optional = true } parry2d = { version = "0.13", optional = true } parry2d-f64 = { version = "0.13", optional = true } nalgebra = { version = "0.32", features = [ "convert-glam024" ] } diff --git a/crates/bevy_xpbd_2d/examples/ray_caster.rs b/crates/bevy_xpbd_2d/examples/ray_caster.rs index 3e97527a..c5ba3d58 100644 --- a/crates/bevy_xpbd_2d/examples/ray_caster.rs +++ b/crates/bevy_xpbd_2d/examples/ray_caster.rs @@ -7,13 +7,13 @@ use bevy::{prelude::*, sprite::MaterialMesh2dBundle}; use bevy_xpbd_2d::prelude::*; -use examples_common_2d::{bevy_prototype_debug_lines::*, *}; +use examples_common_2d::*; fn main() { App::new() .add_plugins((DefaultPlugins, XpbdExamplePlugin)) .insert_resource(ClearColor(Color::rgb(0.05, 0.05, 0.1))) - .add_systems(render_rays) + .add_systems(Update, render_rays) .add_systems(Startup, setup) .run(); } @@ -57,27 +57,21 @@ fn setup( )); } -fn render_rays(mut rays: Query<(&mut RayCaster, &mut RayHits)>, mut lines: ResMut) { +fn render_rays(mut rays: Query<(&mut RayCaster, &mut RayHits)>, mut gizmos: Gizmos) { for (ray, hits) in &mut rays { // Convert to Vec3 for lines - let origin = ray.global_origin().extend(0.0).as_f32(); - let direction = ray.global_direction().extend(0.0).as_f32(); + let origin = ray.global_origin().as_f32(); + let direction = ray.global_direction().as_f32(); for hit in hits.iter() { - lines.line_colored( + gizmos.line_2d( origin, origin + direction * hit.time_of_impact as f32, - 0.001, Color::GREEN, ); } if hits.is_empty() { - lines.line_colored( - origin, - origin + direction * 1_000_000.0, - 0.001, - Color::ORANGE_RED, - ); + gizmos.line_2d(origin, origin + direction * 1_000_000.0, Color::ORANGE_RED); } } } diff --git a/crates/bevy_xpbd_3d/Cargo.toml b/crates/bevy_xpbd_3d/Cargo.toml index 3a31895a..c1153685 100644 --- a/crates/bevy_xpbd_3d/Cargo.toml +++ b/crates/bevy_xpbd_3d/Cargo.toml @@ -16,7 +16,7 @@ default = [ "3d", "f32", "collider-from-mesh" ] 3d = [] f32 = [ "dep:parry3d" ] f64 = [ "dep:parry3d-f64" ] -debug-plugin = [ "dep:bevy_prototype_debug_lines", "examples_common_3d/debug-plugin" ] +debug-plugin = [ "bevy/bevy_gizmos" ] simd = [ "parry3d?/simd-stable", "parry3d-f64?/simd-stable" ] enhanced-determinism = [ "parry3d?/enhanced-determinism", "parry3d-f64?/enhanced-determinism" ] collider-from-mesh = [ "bevy/bevy_render" ] @@ -29,7 +29,6 @@ required-features = [ "3d" ] [dependencies] bevy_xpbd_derive = { path = "../bevy_xpbd_derive", version = "0.1" } bevy = { version = "0.11", default-features = false } -bevy_prototype_debug_lines = { version = "0.10.1", optional = true, features = [ "3d" ] } parry3d = { version = "0.13", optional = true } parry3d-f64 = { version = "0.13", optional = true } nalgebra = { version = "0.32", features = [ "convert-glam024" ] } diff --git a/crates/examples_common_2d/Cargo.toml b/crates/examples_common_2d/Cargo.toml index 3e424387..33c8c39f 100644 --- a/crates/examples_common_2d/Cargo.toml +++ b/crates/examples_common_2d/Cargo.toml @@ -15,6 +15,7 @@ bevy = { version = "0.11", default-features = false, features = [ "bevy_render", "bevy_sprite", "bevy_pbr", + "bevy_gizmos", "tonemapping_luts", "ktx2", "zstd", diff --git a/crates/examples_common_3d/Cargo.toml b/crates/examples_common_3d/Cargo.toml index 925a2f89..27b8c08a 100644 --- a/crates/examples_common_3d/Cargo.toml +++ b/crates/examples_common_3d/Cargo.toml @@ -15,6 +15,7 @@ bevy = { version = "0.11", default-features = false, features = [ "bevy_render", "bevy_sprite", "bevy_pbr", + "bevy_gizmos", "tonemapping_luts", "ktx2", "zstd", diff --git a/src/math/mod.rs b/src/math/mod.rs index c3eb69aa..76955570 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -50,6 +50,13 @@ impl AsF32 for bevy::math::DVec2 { } } +impl AsF32 for bevy::math::Vec2 { + type F32 = Self; + fn as_f32(&self) -> Self::F32 { + *self + } +} + impl AsF32 for bevy::math::Vec4 { type F32 = Self; fn as_f32(&self) -> Self::F32 { diff --git a/src/plugins/debug.rs b/src/plugins/debug.rs index 779ad8d1..c1b96557 100644 --- a/src/plugins/debug.rs +++ b/src/plugins/debug.rs @@ -4,7 +4,6 @@ use crate::prelude::*; use bevy::prelude::*; -use bevy_prototype_debug_lines::*; /// Renders physics objects and events like [AABBs](ColliderAabb) and [contacts](Collision) for debugging purposes. /// @@ -13,15 +12,23 @@ pub struct PhysicsDebugPlugin; impl Plugin for PhysicsDebugPlugin { fn build(&self, app: &mut App) { - app.add_plugin(DebugLinesPlugin::default()) - .init_resource::() + app.init_resource::() + .insert_resource(GizmoConfig { + line_width: 1.0, + ..default() + }) .register_type::() .add_systems( - debug_render_aabbs.run_if(|config: Res| config.render_aabbs), + PostUpdate, + debug_render_aabbs + .run_if(|config: Res| config.render_aabbs) + .after(PhysicsSet::Sync), ) .add_systems( + PostUpdate, debug_render_contacts - .run_if(|config: Res| config.render_contacts), + .run_if(|config: Res| config.render_contacts) + .after(PhysicsSet::Sync), ); } } @@ -45,48 +52,50 @@ impl Default for PhysicsDebugConfig { } } -fn debug_render_aabbs(aabbs: Query<&ColliderAabb>, mut shapes: ResMut) { +fn debug_render_aabbs(aabbs: Query<&ColliderAabb>, mut gizmos: Gizmos) { #[cfg(feature = "2d")] for aabb in aabbs.iter() { - shapes.rect().min_max( - Vector::from(aabb.mins).as_f32(), - Vector::from(aabb.maxs).as_f32(), + gizmos.cuboid( + Transform::from_scale(Vector::from(aabb.extents()).extend(0.0).as_f32()) + .with_translation(Vector::from(aabb.center()).extend(0.0).as_f32()), + Color::WHITE, ); } #[cfg(feature = "3d")] for aabb in aabbs.iter() { - shapes.cuboid().min_max( - Vector::from(aabb.mins).as_f32(), - Vector::from(aabb.maxs).as_f32(), + gizmos.cuboid( + Transform::from_scale(Vector::from(aabb.extents()).as_f32()) + .with_translation(Vector::from(aabb.center()).as_f32()), + Color::WHITE, ); } } #[allow(clippy::unnecessary_cast)] -fn debug_render_contacts(mut collisions: EventReader, mut lines: ResMut) { +fn debug_render_contacts(mut collisions: EventReader, mut gizmos: Gizmos) { #[cfg(feature = "2d")] for Collision(contact) in collisions.iter() { - let p1 = contact.point1.extend(0.0).as_f32(); - let p2 = contact.point2.extend(0.0).as_f32(); + let p1 = contact.point1.as_f32(); + let p2 = contact.point2.as_f32(); - lines.line_colored(p1 - Vec3::X * 0.3, p1 + Vec3::X * 0.3, 0.01, Color::CYAN); - lines.line_colored(p1 - Vec3::Y * 0.3, p1 + Vec3::Y * 0.3, 0.01, Color::CYAN); + gizmos.line_2d(p1 - Vec2::X * 0.3, p1 + Vec2::X * 0.3, Color::CYAN); + gizmos.line_2d(p1 - Vec2::Y * 0.3, p1 + Vec2::Y * 0.3, Color::CYAN); - lines.line_colored(p2 - Vec3::X * 0.3, p2 + Vec3::X * 0.3, 0.01, Color::CYAN); - lines.line_colored(p2 - Vec3::Y * 0.3, p2 + Vec3::Y * 0.3, 0.01, Color::CYAN); + gizmos.line_2d(p2 - Vec2::X * 0.3, p2 + Vec2::X * 0.3, Color::CYAN); + gizmos.line_2d(p2 - Vec2::Y * 0.3, p2 + Vec2::Y * 0.3, Color::CYAN); } #[cfg(feature = "3d")] for Collision(contact) in collisions.iter() { let p1 = contact.point1.as_f32(); let p2 = contact.point2.as_f32(); - lines.line_colored(p1 - Vec3::X * 0.3, p1 + Vec3::X * 0.3, 0.01, Color::CYAN); - lines.line_colored(p1 - Vec3::Y * 0.3, p1 + Vec3::Y * 0.3, 0.01, Color::CYAN); - lines.line_colored(p1 - Vec3::Z * 0.3, p1 + Vec3::Z * 0.3, 0.01, Color::CYAN); + gizmos.line(p1 - Vec3::X * 0.3, p1 + Vec3::X * 0.3, Color::CYAN); + gizmos.line(p1 - Vec3::Y * 0.3, p1 + Vec3::Y * 0.3, Color::CYAN); + gizmos.line(p1 - Vec3::Z * 0.3, p1 + Vec3::Z * 0.3, Color::CYAN); - lines.line_colored(p2 - Vec3::X * 0.3, p2 + Vec3::X * 0.3, 0.01, Color::CYAN); - lines.line_colored(p2 - Vec3::Y * 0.3, p2 + Vec3::Y * 0.3, 0.01, Color::CYAN); - lines.line_colored(p2 - Vec3::Z * 0.3, p2 + Vec3::Z * 0.3, 0.01, Color::CYAN); + gizmos.line(p2 - Vec3::X * 0.3, p2 + Vec3::X * 0.3, Color::CYAN); + gizmos.line(p2 - Vec3::Y * 0.3, p2 + Vec3::Y * 0.3, Color::CYAN); + gizmos.line(p2 - Vec3::Z * 0.3, p2 + Vec3::Z * 0.3, Color::CYAN); } } From 524ffde6bd8b2ba06459c0302f2e2b308023d290 Mon Sep 17 00:00:00 2001 From: Jondolf Date: Mon, 10 Jul 2023 00:27:40 +0300 Subject: [PATCH 7/8] Add FPS counter for examples --- crates/examples_common_2d/Cargo.toml | 4 +-- crates/examples_common_2d/src/lib.rs | 44 ++++++++++++++++++++++++++-- crates/examples_common_3d/Cargo.toml | 4 +-- crates/examples_common_3d/src/lib.rs | 44 ++++++++++++++++++++++++++-- 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/crates/examples_common_2d/Cargo.toml b/crates/examples_common_2d/Cargo.toml index 33c8c39f..322c05c1 100644 --- a/crates/examples_common_2d/Cargo.toml +++ b/crates/examples_common_2d/Cargo.toml @@ -3,9 +3,6 @@ name = "examples_common_2d" version = "0.1.0" edition = "2021" -[features] -debug-plugin = [] - [dependencies] bevy = { version = "0.11", default-features = false, features = [ "bevy_core_pipeline", @@ -16,6 +13,7 @@ bevy = { version = "0.11", default-features = false, features = [ "bevy_sprite", "bevy_pbr", "bevy_gizmos", + "default_font", "tonemapping_luts", "ktx2", "zstd", diff --git a/crates/examples_common_2d/src/lib.rs b/crates/examples_common_2d/src/lib.rs index 36f306f1..59b166ae 100644 --- a/crates/examples_common_2d/src/lib.rs +++ b/crates/examples_common_2d/src/lib.rs @@ -1,4 +1,8 @@ -use bevy::prelude::*; +use bevy::{ + diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin}, + prelude::*, + text::DEFAULT_FONT_HANDLE, +}; use bevy_xpbd_2d::prelude::*; #[derive(Default)] @@ -6,10 +10,12 @@ pub struct XpbdExamplePlugin; impl Plugin for XpbdExamplePlugin { fn build(&self, app: &mut App) { - app.add_plugins(PhysicsPlugins::default()) + app.add_plugins((PhysicsPlugins::default(), FrameTimeDiagnosticsPlugin)) .add_state::() + .add_systems(Startup, setup) .add_systems(OnEnter(AppState::Paused), bevy_xpbd_2d::pause) .add_systems(OnExit(AppState::Paused), bevy_xpbd_2d::resume) + .add_systems(Update, update_fps_text) .add_systems(Update, pause_button) .add_systems(Update, step_button.run_if(in_state(AppState::Paused))); } @@ -41,3 +47,37 @@ fn step_button(mut physics_loop: ResMut, keys: Res>) physics_loop.step(); } } + +#[derive(Component)] +struct FpsText; + +fn setup(mut commands: Commands) { + commands.spawn(( + TextBundle::from_section( + "FPS: ", + TextStyle { + font: DEFAULT_FONT_HANDLE.typed(), + font_size: 20.0, + color: Color::TOMATO, + }, + ) + .with_style(Style { + position_type: PositionType::Absolute, + top: Val::Px(5.0), + left: Val::Px(5.0), + ..default() + }), + FpsText, + )); +} + +fn update_fps_text(diagnostics: Res, mut query: Query<&mut Text, With>) { + for mut text in &mut query { + if let Some(fps) = diagnostics.get(FrameTimeDiagnosticsPlugin::FPS) { + if let Some(value) = fps.smoothed() { + // Update the value of the second section + text.sections[0].value = format!("FPS: {value:.2}"); + } + } + } +} diff --git a/crates/examples_common_3d/Cargo.toml b/crates/examples_common_3d/Cargo.toml index 27b8c08a..fd954aed 100644 --- a/crates/examples_common_3d/Cargo.toml +++ b/crates/examples_common_3d/Cargo.toml @@ -3,9 +3,6 @@ name = "examples_common_3d" version = "0.1.0" edition = "2021" -[features] -debug-plugin = [] - [dependencies] bevy = { version = "0.11", default-features = false, features = [ "bevy_core_pipeline", @@ -16,6 +13,7 @@ bevy = { version = "0.11", default-features = false, features = [ "bevy_sprite", "bevy_pbr", "bevy_gizmos", + "default_font", "tonemapping_luts", "ktx2", "zstd", diff --git a/crates/examples_common_3d/src/lib.rs b/crates/examples_common_3d/src/lib.rs index e72a7b85..365cacc0 100644 --- a/crates/examples_common_3d/src/lib.rs +++ b/crates/examples_common_3d/src/lib.rs @@ -1,4 +1,8 @@ -use bevy::prelude::*; +use bevy::{ + diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin}, + prelude::*, + text::DEFAULT_FONT_HANDLE, +}; use bevy_xpbd_3d::prelude::*; #[derive(Default)] @@ -6,10 +10,12 @@ pub struct XpbdExamplePlugin; impl Plugin for XpbdExamplePlugin { fn build(&self, app: &mut App) { - app.add_plugins(PhysicsPlugins::default()) + app.add_plugins((PhysicsPlugins::default(), FrameTimeDiagnosticsPlugin)) .add_state::() + .add_systems(Startup, setup) .add_systems(OnEnter(AppState::Paused), bevy_xpbd_3d::pause) .add_systems(OnExit(AppState::Paused), bevy_xpbd_3d::resume) + .add_systems(Update, update_fps_text) .add_systems(Update, pause_button) .add_systems(Update, step_button.run_if(in_state(AppState::Paused))); } @@ -41,3 +47,37 @@ fn step_button(mut physics_loop: ResMut, keys: Res>) physics_loop.step(); } } + +#[derive(Component)] +struct FpsText; + +fn setup(mut commands: Commands) { + commands.spawn(( + TextBundle::from_section( + "FPS: ", + TextStyle { + font: DEFAULT_FONT_HANDLE.typed(), + font_size: 20.0, + color: Color::TOMATO, + }, + ) + .with_style(Style { + position_type: PositionType::Absolute, + top: Val::Px(5.0), + left: Val::Px(5.0), + ..default() + }), + FpsText, + )); +} + +fn update_fps_text(diagnostics: Res, mut query: Query<&mut Text, With>) { + for mut text in &mut query { + if let Some(fps) = diagnostics.get(FrameTimeDiagnosticsPlugin::FPS) { + if let Some(value) = fps.smoothed() { + // Update the value of the second section + text.sections[0].value = format!("FPS: {value:.2}"); + } + } + } +} From c0dff8e642d980ed8529e919f39499bb713078b0 Mon Sep 17 00:00:00 2001 From: Jondolf Date: Mon, 10 Jul 2023 15:32:15 +0300 Subject: [PATCH 8/8] Fix documentation code examples --- src/resources.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/resources.rs b/src/resources.rs index af1fb735..7eb5a6ff 100644 --- a/src/resources.rs +++ b/src/resources.rs @@ -19,8 +19,7 @@ use crate::prelude::*; /// /// fn main() { /// App::new() -/// .add_plugins(DefaultPlugins) -/// .add_plugins(PhysicsPlugins) +/// .add_plugins((DefaultPlugins, PhysicsPlugins::default())) /// // Use a 120 Hz fixed timestep instead of the default 60 Hz /// .insert_resource(PhysicsTimestep::Fixed(1.0 / 120.0)) /// .run(); @@ -81,8 +80,7 @@ pub struct SubDeltaTime(pub Scalar); /// /// fn main() { /// App::new() -/// .add_plugins(DefaultPlugins) -/// .add_plugins(PhysicsPlugins) +/// .add_plugins((DefaultPlugins, PhysicsPlugins::default())) /// .insert_resource(SubstepCount(30)) /// .run(); /// } @@ -173,8 +171,7 @@ impl Default for DeactivationTime { /// # #[cfg(all(feature = "3d", feature = "f32"))] /// fn main() { /// App::new() -/// .add_plugins(DefaultPlugins) -/// .add_plugins(PhysicsPlugins) +/// .add_plugins((DefaultPlugins, PhysicsPlugins::default())) /// .insert_resource(Gravity(Vec3::NEG_Y * 19.6)) /// .run(); /// }