actually kinda works, but needs simulated friction.

This commit is contained in:
Joe Ardent 2024-06-19 16:37:40 -07:00
parent 0fae893508
commit c3e955c1cd
3 changed files with 58 additions and 43 deletions

View file

@ -34,8 +34,7 @@ impl Plugin for CyberActionPlugin {
.add_systems( .add_systems(
Update, Update,
( (
reset_body_force, reset_external_forces,
reset_wheel_forces,
cyber_lean, cyber_lean,
falling_cat, falling_cat,
wheel_forces, wheel_forces,

View file

@ -6,9 +6,12 @@ use bevy::{
}, },
render::color::Color, render::color::Color,
}; };
use bevy_rapier3d::prelude::{ use bevy_rapier3d::{
geometry::Friction,
prelude::{
ExternalForce, QueryFilter, RapierConfiguration, RapierContext, ReadMassProperties, ExternalForce, QueryFilter, RapierConfiguration, RapierContext, ReadMassProperties,
TimestepMode, Velocity, TimestepMode, Velocity,
},
}; };
#[cfg(feature = "inspector")] #[cfg(feature = "inspector")]
@ -34,29 +37,23 @@ pub(super) fn physics_init(
config.gravity = Vec3::NEG_Y * settings.gravity; config.gravity = Vec3::NEG_Y * settings.gravity;
} }
pub(super) fn reset_body_force( pub(super) fn reset_external_forces(
mut query: Query<&mut ExternalForce, With<CyberBikeBody>>, mut query: Query<&mut ExternalForce>,
#[cfg(feature = "inspector")] mut debug_instant: ResMut<ActionDebugInstant>, #[cfg(feature = "inspector")] mut debug_instant: ResMut<ActionDebugInstant>,
) { ) {
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<CyberWheel>>) {
for mut force in query.iter_mut() { for mut force in query.iter_mut() {
#[cfg(feature = "inspector")]
if debug_instant.elapsed().as_millis() > 1000 {
info!("{force:?}");
}
force.force = Vec3::ZERO; force.force = Vec3::ZERO;
force.torque = 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. /// The desired lean angle, given steering input and speed.
@ -135,6 +132,7 @@ pub(super) fn wheel_forces(
&Transform, &Transform,
&Velocity, &Velocity,
&mut ExternalForce, &mut ExternalForce,
&mut Friction,
Option<&CyberSteering>, Option<&CyberSteering>,
), ),
With<CyberWheel>, With<CyberWheel>,
@ -149,32 +147,51 @@ pub(super) fn wheel_forces(
let radius = wheel_config.radius; let radius = wheel_config.radius;
// inputs // inputs
let steering = input.yaw; let yaw = input.yaw;
let throttle = input.throttle * settings.accel; let throttle = input.throttle * settings.accel;
for (xform, velocity, mut external_force, steering) in wheels_query.iter_mut() { for (xform, velocity, mut external_force, mut friction, steering) in wheels_query.iter_mut() {
if let Some((_, projected)) = let pos = xform.translation;
context.project_point(xform.translation, false, QueryFilter::only_fixed()) if let Some((_, projected)) = context.project_point(pos, false, QueryFilter::only_fixed()) {
{
let normal = (projected.point - xform.translation);
let len = normal.length();
if len < radius {
let mut force = Vec3::ZERO; 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 // do thrust's share
let thrust = normal.cross(xform.left().into()) * throttle; let thrust = norm.cross(xform.right().into()) * throttle;
force += thrust; force += thrust;
// do steering's share // do steering's share
if steering.is_some() {
let thrust = norm.cross(xform.back().into());
force += yaw * thrust;
}
// do the friction's share // do the friction's share
if input.brake {
friction.coefficient = 2.0;
} else {
friction.coefficient = 0.0;
}
// show the force // show the force
#[cfg(feature = "inspector")] #[cfg(feature = "inspector")]
gizmos.arrow(xform.translation, force, Color::RED); gizmos.arrow(pos, pos + force, Color::RED);
// ok apply the force // ok apply the force
let ef = ExternalForce::at_point(force, projected.point, xform.translation); *external_force = ExternalForce::at_point(force, point, pos);
*external_force = ef;
} }
} }
} }

View file

@ -83,14 +83,10 @@ pub(crate) fn spawn_wheels(
.insert(not_sleeping) .insert(not_sleeping)
.id(); .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_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_joint = MultibodyJoint::new(fork_rb_entity, neck_builder);
let neck = commands let neck = commands.spawn(RigidBody::Dynamic).insert(neck_joint).id();
.spawn(RigidBody::Dynamic)
.insert(neck_joint)
.insert(steering)
.id();
neck neck
} else { } else {
fork_rb_entity fork_rb_entity
@ -99,9 +95,9 @@ pub(crate) fn spawn_wheels(
let axel_builder = FixedJointBuilder::new(); let axel_builder = FixedJointBuilder::new();
let axel_joint = MultibodyJoint::new(axel_parent_entity, axel_builder); 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, mass_props,
//wheel_damping,
axel_joint, axel_joint,
CyberWheel, CyberWheel,
not_sleeping, not_sleeping,
@ -119,6 +115,9 @@ pub(crate) fn spawn_wheels(
wheels_collision_group, wheels_collision_group,
Collider::ball(conf.radius), Collider::ball(conf.radius),
)); ));
if steering.is_some() {
c.insert(CyberSteering);
}
} }
} }