Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backend agnosticism #39

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
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
19 changes: 15 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,37 @@ repository = "https://github.com/PROMETHIA-27/bevy_mod_wanderlust"
version = "0.4.0"

[features]
default = ["rapier"]
default = ["rapier3d"]
debug_lines = []
rapier = ["bevy_rapier3d"]
rapier = []
rapier3d = ["rapier", "bevy_rapier3d"]
rapier2d = ["rapier", "bevy_rapier2d"]
xpbd = []
xpbd3d = ["xpbd", "bevy_xpbd_3d"]
xpbd2d = ["xpbd", "bevy_xpbd_2d"]

[dependencies]
bevy = { version = "0.11", default-features = false, features = [
"bevy_render",
"bevy_gizmos",
] }
bevy_rapier3d = { version = "0.22", default-features = false, features = [
"debug-render",
"async-collider",
"dim3",
], optional = true }
bevy_rapier2d = { version = "0.22", default-features = false, features = [
"async-collider",
"dim2",
], optional = true }
bevy_xpbd_3d = { version = "0.2", optional = true }
bevy_xpbd_2d = { version = "0.2", optional = true }

[dev-dependencies]
bevy = "0.11"
aether_spyglass = "0.2"
bevy-inspector-egui = "0.19"
bevy_framepace = "0.13"
bevy_rapier3d = { version = "0.22", features = ["debug-render"] }

# Enable a small amount of optimization in debug mode
[profile.dev]
Expand All @@ -44,4 +55,4 @@ opt-level = 3

[patch.crates-io]
#bevy_rapier3d = { path = "../bevy_rapier/bevy_rapier3d" }
bevy_rapier3d = { git = "https://github.com/dimforge/bevy_rapier", rev = "0ea000b" }
bevy_rapier3d = { git = "https://github.com/dimforge/bevy_rapier", rev = "0ea000b" }
5 changes: 2 additions & 3 deletions examples/playground.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,10 @@ fn main() {
}
},
)
// Add to PreUpdate to ensure updated before movement is calculated
.add_systems(
Update,
(
movement_input.before(bevy_mod_wanderlust::movement_force),
movement_input.before(bevy_mod_wanderlust::WanderlustSet::Sync),
toggle_cursor_lock,
oscillating,
controlled_platform,
Expand Down Expand Up @@ -154,7 +153,7 @@ pub fn player(
translation: Vec3::new(0.0, 3.0, 0.0),
..default()
},
rapier_physics: RapierPhysicsBundle {
rapier: RapierPhysicsBundle {
// Lock the axes to prevent camera shake whilst moving up slopes
//locked_axes: LockedAxes::ROTATION_LOCKED,
//locked_axes: LockedAxes::all(),
Expand Down
18 changes: 18 additions & 0 deletions src/backend/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#[cfg(feature = "rapier")]
pub mod rapier;
pub use rapier::*;

#[cfg(feature = "xpbd")]
mod xpbd;
#[cfg(feature = "xpbd")]
pub use xpbd::{
apply_forces,
apply_ground_forces,
cast_ray,
//cast_shape,
setup_physics_context,
Mass,
SpatialQuery,
Velocity,
XpbdPhysicsBundle as BackendPhysicsBundle,
};
22 changes: 22 additions & 0 deletions src/backend/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

#[derive(Debug, Copy, Clone, Reflect)]
pub struct RayCastResult {
pub entity: Entity,
pub toi: f32,
pub normal: Vec3,
pub point: Vec3,
}

#[derive(Debug, Copy, Clone, Reflect)]
pub struct ShapeCastResult {
pub entity: Entity,
pub toi: f32,
pub normal1: Vec3,
pub normal2: Vec3,
pub point1: Vec3,
pub point2: Vec3,
}

pub struct QueryFilter {
pub exclude: HashSet<Entity>,
}
49 changes: 1 addition & 48 deletions src/rapier.rs → src/backend/rapier/bundle.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::{controller::*, physics::*};
use super::rapier::prelude::*;
use bevy::prelude::*;
use bevy_rapier3d::prelude::*;

/// Contains common physics settings for character controllers.
#[derive(Bundle)]
Expand Down Expand Up @@ -58,49 +57,3 @@ impl Default for RapierPhysicsBundle {
}
}
}

/// Apply forces to the controller to make it float, move, jump, etc.
pub fn apply_forces(
mut forces: Query<(&mut ExternalImpulse, &ControllerForce)>,
ctx: Res<RapierContext>,
) {
let dt = ctx.integration_parameters.dt;
for (mut impulse, force) in &mut forces {
impulse.impulse += force.linear * dt;
impulse.torque_impulse += force.angular * dt;
}
}

/// Apply the opposing ground force to the entity we are pushing off of to float.
pub fn apply_ground_forces(
mut impulses: Query<&mut ExternalImpulse>,
ground_forces: Query<(&GroundForce, &ViableGroundCast)>,
ctx: Res<RapierContext>,
) {
let dt = ctx.integration_parameters.dt;
for (force, viable_ground) in &ground_forces {
if let Some(ground) = viable_ground.current() {
if let Ok(mut impulse) = impulses.get_mut(ground.entity) {
impulse.impulse += force.linear * dt;
impulse.torque_impulse += force.angular * dt;
}
}
}
}

/// Sync rapier masses over to our masses.
pub fn get_mass_from_rapier(mut query: Query<(&mut ControllerMass, &ReadMassProperties)>) {
for (mut mass, rapier_mass) in &mut query {
mass.mass = rapier_mass.mass;
mass.inertia = rapier_mass.principal_inertia;
mass.com = rapier_mass.local_center_of_mass;
}
}

/// Sync rapier velocities over to our velocities.
pub fn get_velocity_from_rapier(mut query: Query<(&mut ControllerVelocity, &Velocity)>) {
for (mut vel, rapier_vel) in &mut query {
vel.linear = rapier_vel.linvel;
vel.angular = rapier_vel.angvel;
}
}
19 changes: 19 additions & 0 deletions src/backend/rapier/mass.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use super::rapier::prelude::*;
use crate::*;
use bevy::{ecs::query::WorldQuery, prelude::*};

pub fn get_mass_from_backend(mut query: Query<(&mut ControllerMass, &ReadMassProperties)>) {
for (mut mass, rapier) in &mut query {
*mass = ControllerMass::from_rapier(&*rapier);
}
}

impl ControllerMass {
pub fn from_rapier(rapier: &MassProperties) -> Self {
Self {
mass: rapier.mass,
inertia: rapier.principal_inertia,
local_center_of_mass: rapier.local_center_of_mass,
}
}
}
74 changes: 74 additions & 0 deletions src/backend/rapier/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//use crate::{controller::*, physics::*};
use crate::*;
use bevy::prelude::*;

#[cfg(feature = "rapier2d")]
pub use bevy_rapier2d as rapier;
#[cfg(feature = "rapier3d")]
pub use bevy_rapier3d as rapier;

use rapier::prelude::*;

pub fn backend_label() -> PhysicsSet {
PhysicsSet::SyncBackend
}

mod bundle;
pub use bundle::RapierPhysicsBundle;
mod mass;
pub use mass::get_mass_from_backend;
mod velocity;
pub use velocity::get_velocity_from_backend;
mod plugin;
mod query;
pub use plugin::WanderlustRapierPlugin;

use rapier::prelude::Collider;

/// Apply forces to the controller to make it float, move, jump, etc.
pub fn apply_forces(
ctx: Res<RapierContext>,
mut forces: Query<(&mut ExternalImpulse, &ControllerForce)>,
) {
let dt = ctx.integration_parameters.dt;
for (mut impulse, force) in &mut forces {
impulse.impulse += force.linear * dt;
impulse.torque_impulse += force.angular * dt;
}
}

/// Apply the opposing ground force to the entity we are pushing off of to float.
pub fn apply_ground_forces(
ctx: Res<RapierContext>,
mut impulses: Query<&mut ExternalImpulse>,
ground_forces: Query<(&GroundForce, &ViableGroundCast)>,
) {
let dt = ctx.integration_parameters.dt;
for (force, cast) in &ground_forces {
if let Some(ground) = cast.current() {
if let Some(ground_body) = ctx.collider_parent(ground.entity) {
if let Ok(mut impulse) = impulses.get_mut(ground_body) {
impulse.impulse += force.linear * dt;
impulse.torque_impulse += force.angular * dt;
}
}
}
}
}

pub fn update_delta_time(mut physics_dt: ResMut<PhysicsDeltaTime>, ctx: Res<RapierContext>) {
physics_dt.0 = ctx.integration_parameters.dt;
}

/// *Note: Most users will not need to use this directly. Use [`WanderlustPlugin`](crate::plugins::WanderlustPlugin) instead.
/// Alternatively, if one only wants to disable the system, use [`WanderlustPhysicsTweaks`](WanderlustPhysicsTweaks).*
///
/// This system adds some tweaks to rapier's physics settings that make the character controller behave better.
pub fn setup_physics_context(mut ctx: ResMut<RapierContext>) {
let params = &mut ctx.integration_parameters;
// This prevents any noticeable jitter when running facefirst into a wall.
params.erp = 0.99;
// This prevents (most) noticeable jitter when running facefirst into an inverted corner.
params.max_velocity_iterations = 16;
// TODO: Fix jitter that occurs when running facefirst into a normal corner.
}
38 changes: 38 additions & 0 deletions src/backend/rapier/plugin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use crate::*;
use bevy::{ecs::schedule::ScheduleLabel, prelude::*, utils::HashSet};

pub struct WanderlustRapierPlugin {
pub tweaks: bool,
pub schedule: Box<dyn ScheduleLabel>,
}

impl Plugin for WanderlustRapierPlugin {
fn build(&self, app: &mut App) {
if self.tweaks {
app.add_systems(Startup, super::setup_physics_context);
}

app.configure_sets(
self.schedule.clone(),
(WanderlustSet::Apply,).before(crate::rapier::PhysicsSet::SyncBackend),
);

app.add_systems(
self.schedule.clone(),
(
super::update_delta_time,
super::get_mass_from_backend,
super::get_velocity_from_backend,
)
.chain()
.in_set(WanderlustSet::Sync),
);

app.add_systems(
self.schedule.clone(),
(super::apply_forces, super::apply_ground_forces)
.chain()
.in_set(WanderlustSet::Apply),
);
}
}
4 changes: 4 additions & 0 deletions src/backend/rapier/query.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use super::rapier::prelude::*;
use bevy::prelude::*;

pub type SpatialQuery<'w, 's> = Res<'s, RapierContext>;
10 changes: 10 additions & 0 deletions src/backend/rapier/velocity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use super::rapier::prelude::*;
use crate::*;
use bevy::{ecs::query::WorldQuery, prelude::*};

pub fn get_velocity_from_backend(mut query: Query<(&mut ControllerVelocity, &Velocity)>) {
for (mut velocity, rapier) in &mut query {
velocity.linear = rapier.linvel;
velocity.angular = rapier.angvel;
}
}
23 changes: 23 additions & 0 deletions src/backend/xpbd/mass.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use super::xpbd;
use bevy::{ecs::query::WorldQuery, prelude::*};

#[derive(WorldQuery)]
pub struct Mass {
mass: &'static xpbd::prelude::Mass,
inertia: &'static xpbd::prelude::Inertia,
center_of_mass: &'static xpbd::prelude::CenterOfMass,
}

impl<'a> MassItem<'a> {
pub fn mass(&self) -> f32 {
self.mass.0
}

pub fn inertia(&self) -> Mat3 {
self.inertia.0
}

pub fn local_center_of_mass(&self) -> Vec3 {
self.center_of_mass.0
}
}
Loading
Loading