From c3e955c1cdc0e6bcff4dae93c94b3a4903624d66 Mon Sep 17 00:00:00 2001 From: Joe Ardent Date: Wed, 19 Jun 2024 16:37:40 -0700 Subject: [PATCH] actually kinda works, but needs simulated friction. --- src/action/mod.rs | 3 +- src/action/systems.rs | 83 ++++++++++++++++++++++++++----------------- src/bike/wheels.rs | 15 ++++---- 3 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/action/mod.rs b/src/action/mod.rs index 3ec51f4..4e51863 100644 --- a/src/action/mod.rs +++ b/src/action/mod.rs @@ -34,8 +34,7 @@ impl Plugin for CyberActionPlugin { .add_systems( Update, ( - reset_body_force, - reset_wheel_forces, + reset_external_forces, cyber_lean, falling_cat, wheel_forces, diff --git a/src/action/systems.rs b/src/action/systems.rs index dcb941b..72f21f7 100644 --- a/src/action/systems.rs +++ b/src/action/systems.rs @@ -6,9 +6,12 @@ use bevy::{ }, render::color::Color, }; -use bevy_rapier3d::prelude::{ - ExternalForce, QueryFilter, RapierConfiguration, RapierContext, ReadMassProperties, - TimestepMode, Velocity, +use bevy_rapier3d::{ + geometry::Friction, + prelude::{ + ExternalForce, QueryFilter, RapierConfiguration, RapierContext, ReadMassProperties, + TimestepMode, Velocity, + }, }; #[cfg(feature = "inspector")] @@ -34,29 +37,23 @@ pub(super) fn physics_init( config.gravity = Vec3::NEG_Y * settings.gravity; } -pub(super) fn reset_body_force( - mut query: Query<&mut ExternalForce, With>, +pub(super) fn reset_external_forces( + mut query: Query<&mut ExternalForce>, #[cfg(feature = "inspector")] mut debug_instant: ResMut, ) { - let mut body_force = query.single_mut(); - - #[cfg(feature = "inspector")] - { - if debug_instant.elapsed().as_millis() > 1000 { - //dbg!(&body_force); - debug_instant.reset(); - } - } - - body_force.force = Vec3::ZERO; - body_force.torque = Vec3::ZERO; -} - -pub(super) fn reset_wheel_forces(mut query: Query<&mut ExternalForce, With>) { for mut force in query.iter_mut() { + #[cfg(feature = "inspector")] + if debug_instant.elapsed().as_millis() > 1000 { + info!("{force:?}"); + } + force.force = Vec3::ZERO; force.torque = Vec3::ZERO; } + #[cfg(feature = "inspector")] + if debug_instant.elapsed().as_millis() > 1000 { + debug_instant.reset(); + } } /// The desired lean angle, given steering input and speed. @@ -135,6 +132,7 @@ pub(super) fn wheel_forces( &Transform, &Velocity, &mut ExternalForce, + &mut Friction, Option<&CyberSteering>, ), With, @@ -149,32 +147,51 @@ pub(super) fn wheel_forces( let radius = wheel_config.radius; // inputs - let steering = input.yaw; + let yaw = input.yaw; let throttle = input.throttle * settings.accel; - for (xform, velocity, mut external_force, steering) in wheels_query.iter_mut() { - if let Some((_, projected)) = - context.project_point(xform.translation, false, QueryFilter::only_fixed()) - { - let normal = (projected.point - xform.translation); - let len = normal.length(); - if len < radius { - let mut force = Vec3::ZERO; + for (xform, velocity, mut external_force, mut friction, steering) in wheels_query.iter_mut() { + let pos = xform.translation; + if let Some((_, projected)) = context.project_point(pos, false, QueryFilter::only_fixed()) { + let mut force = Vec3::ZERO; + + gizmos.sphere(projected.point, Quat::IDENTITY, radius, Color::RED); + + let dir = (projected.point - pos).normalize(); + + if let Some((_, intersection)) = context.cast_ray_and_get_normal( + pos, + dir, + radius * 1.05, + false, + QueryFilter::only_fixed(), + ) { + let norm = intersection.normal; + let point = intersection.point; + // do thrust's share - let thrust = normal.cross(xform.left().into()) * throttle; + let thrust = norm.cross(xform.right().into()) * throttle; force += thrust; // do steering's share + if steering.is_some() { + let thrust = norm.cross(xform.back().into()); + force += yaw * thrust; + } // do the friction's share + if input.brake { + friction.coefficient = 2.0; + } else { + friction.coefficient = 0.0; + } // show the force #[cfg(feature = "inspector")] - gizmos.arrow(xform.translation, force, Color::RED); + gizmos.arrow(pos, pos + force, Color::RED); // ok apply the force - let ef = ExternalForce::at_point(force, projected.point, xform.translation); - *external_force = ef; + *external_force = ExternalForce::at_point(force, point, pos); } } } diff --git a/src/bike/wheels.rs b/src/bike/wheels.rs index 00524a1..ffb083f 100644 --- a/src/bike/wheels.rs +++ b/src/bike/wheels.rs @@ -83,14 +83,10 @@ pub(crate) fn spawn_wheels( .insert(not_sleeping) .id(); - let axel_parent_entity = if let Some(steering) = steering { + let axel_parent_entity = if steering.is_some() { let neck_builder = FixedJointBuilder::new().local_anchor1(Vec3::new(0.0, 0.0, 0.1)); // this adds another 0.1m of trail let neck_joint = MultibodyJoint::new(fork_rb_entity, neck_builder); - let neck = commands - .spawn(RigidBody::Dynamic) - .insert(neck_joint) - .insert(steering) - .id(); + let neck = commands.spawn(RigidBody::Dynamic).insert(neck_joint).id(); neck } else { fork_rb_entity @@ -99,9 +95,9 @@ pub(crate) fn spawn_wheels( let axel_builder = FixedJointBuilder::new(); let axel_joint = MultibodyJoint::new(axel_parent_entity, axel_builder); - commands.spawn(pbr_bundle).insert(( + let c = &mut commands.spawn(pbr_bundle); + c.insert(( mass_props, - //wheel_damping, axel_joint, CyberWheel, not_sleeping, @@ -119,6 +115,9 @@ pub(crate) fn spawn_wheels( wheels_collision_group, Collider::ball(conf.radius), )); + if steering.is_some() { + c.insert(CyberSteering); + } } }